react-native transform-origin實(shí)現(xiàn)

image.png

最近在做RN項(xiàng)目的時(shí)候忘嫉,有一個(gè)旋轉(zhuǎn)效果需要指定非元素中心的原點(diǎn)。我們都知道在CSS3里進(jìn)行transform變換的時(shí)候桑驱,默認(rèn)的變換原點(diǎn)是元素的中心位置,css3提供了transform-origin屬性來設(shè)置變換原點(diǎn)脉顿,但是在RN里,我翻遍了官方文檔和一些源碼都沒有看到可以在設(shè)置類似transform-origin東西点寥,但是RN的transform支持 matrix艾疟。

一個(gè)使用矩陣實(shí)現(xiàn)縮放的栗子

將圖片旋轉(zhuǎn)放大2倍,我們用matrix實(shí)現(xiàn)

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
          <Image style={[
            styles.imageBox,
            {transform: [{matrix: [
                2, 0, 0, 0,
                0, 2, 0, 0,
                0, 0, 1, 0,
                0, 0, 0, 1]}]}
            ]} 
            source={{uri: 'http://www.google.cn/landing/cnexp/google-search.png'}} />
      </View>
    );
  }
}

這個(gè)時(shí)候的效果就和使用scale(2) 一毛一樣敢辩。

順便提一下蔽莱,話說在transform的matrix屬性是在rn的某個(gè)版本中才加入的,更老的版本使用的是 transformMatrix 屬性戚长,它與transform平級盗冷。

指定變換中心(transform-origin)

這里主要說明transform-origin的實(shí)現(xiàn)原理。其實(shí)transform-origin在css規(guī)范里面也有具體的說明同廉。

div { 
  height: 100px; 
  width: 100px; 
  transform-origin: 50px 50px; 
  transform: rotate(45deg);
}

The transform-origin property moves the point of origin by 50 pixels in both the X and Y directions. The transform rotates the element clockwise by 45° about the point of origin. After all transform functions were applied, the translation of the origin gets translated back by -50 pixels in both the X and Y directions.

也就是如下這幅圖仪糖,出自這里

css規(guī)范中的表述

翻譯一下就是,要想指定變換原點(diǎn)迫肖,其實(shí)只需要先把元素的中心平移到變換原點(diǎn)锅劝,然后開始變換,完了過后再反向平移到原來的位置蟆湖。

說得這么晦澀故爵,什么變換啥的,其實(shí)矩陣變換對應(yīng)到數(shù)學(xué)上就是進(jìn)行矩陣乘法隅津,不知道基礎(chǔ)的同學(xué)建議先看看相關(guān)的知識(shí)诬垂,線性代數(shù)、基本圖形變換之類的饥瓷。

demo

代碼在這里, 可在線預(yù)覽剥纷, 有可能需要科學(xué)上網(wǎng)才能訪問到痹籍。
下面選取了部分關(guān)鍵代碼說明一下


    // 旋轉(zhuǎn)中心
    const transformOrigin = [50, -50];
    const translate = [
       1, 0, 0, 0,
       0, 1, 0, 0,
       0, 0, 1, 0,
       transformOrigin[0], transformOrigin[1], 0, 1
      ];
    const unUseTranslate = [
       1, 0, 0, 0,
       0, 1, 0, 0,
       0, 0, 1, 0,
       -transformOrigin[0], -transformOrigin[1], 0, 1
      ];
    const a = Math.PI/6;
    const rotateMatrix = [
       Math.cos(a), Math.sin(a), 0, 0,
      -Math.sin(a), Math.cos(a), 0, 0,
       0,            0,          1, 0,
       0,            0,          0, 1
      ];
    
    // 結(jié)果矩陣
    // 先平移到旋轉(zhuǎn)中心呢铆,再旋轉(zhuǎn)
    let m = Matrix.multMatrix(translate, rotateMatrix);
    
    // 再平移回去
    m = Matrix.multMatrix(m, unUseTranslate);
    
    this.setState({
      matrix: m
    });

圖片(容器)大小為100*100,我們?nèi)绻O(shè)置變換中心為圖片的右上角的話蹲缠,那么需要的旋轉(zhuǎn)中心應(yīng)該是 transformOrigin = [50, -50]; 這里為什么是[50, -50]呢棺克?而不是像css屬性里的是transform-origin: 100px, 0悠垛。 這是因?yàn)檫M(jìn)行矩陣變換的時(shí)候,所應(yīng)用的坐標(biāo)系是元素的本地坐標(biāo)系(local coordinate space)娜谊,圖片的中心是0,0, x軸向右為正确买,y軸向下為正。所以此時(shí)圖片的右上角所對應(yīng)的坐標(biāo)是(50, -50).如下圖

local coordinate space

結(jié)語

我這代碼中的矩陣操作全是手動(dòng)擼的纱皆,矩陣變換本來就是個(gè)麻煩而且枯燥的工作湾趾,所以如果大家在實(shí)際項(xiàng)目中需要用到各種矩陣操作的話,可以推薦 gl-matrix 這個(gè)庫派草。react-native項(xiàng)目里面的話搀缠,可以直接使用 MatrixMath 模塊。
如果深究一下css 的transform 文檔近迁,其實(shí)會(huì)發(fā)現(xiàn)所有的變換都可以用矩陣來表示艺普,比如perspectiveperspective-origin等屬性鉴竭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歧譬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子搏存,更是在濱河造成了極大的恐慌瑰步,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件璧眠,死亡現(xiàn)場離奇詭異面氓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蛆橡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門舌界,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泰演,你說我怎么就攤上這事呻拌。” “怎么了睦焕?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵藐握,是天一觀的道長。 經(jīng)常有香客問我垃喊,道長猾普,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任本谜,我火速辦了婚禮初家,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己溜在,他們只是感情好陌知,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掖肋,像睡著了一般仆葡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上志笼,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天沿盅,我揣著相機(jī)與錄音,去河邊找鬼纫溃。 笑死嗡呼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的皇耗。 我是一名探鬼主播南窗,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼郎楼!你這毒婦竟也來了万伤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤呜袁,失蹤者是張志新(化名)和其女友劉穎敌买,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阶界,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虹钮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了膘融。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芙粱。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖氧映,靈堂內(nèi)的尸體忽然破棺而出春畔,到底是詐尸還是另有隱情,我是刑警寧澤岛都,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布律姨,位于F島的核電站,受9級特大地震影響臼疫,放射性物質(zhì)發(fā)生泄漏择份。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一烫堤、第九天 我趴在偏房一處隱蔽的房頂上張望荣赶。 院中可真熱鬧凤价,春花似錦、人聲如沸讯壶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伏蚊。三九已至,卻和暖如春格粪,著一層夾襖步出監(jiān)牢的瞬間躏吊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工帐萎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留比伏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓疆导,卻偏偏與公主長得像赁项,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子澈段,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于css3變形 CSS3變形是一些效果的集合悠菜,比如平移、旋轉(zhuǎn)败富、縮放和傾斜效果悔醋,每個(gè)效果都被稱作為變形函數(shù)(Tra...
    hopevow閱讀 6,336評論 2 13
  • 看了很多視頻、文章兽叮,最后卻通通忘記了芬骄,別人的知識(shí)依舊是別人的,自己卻什么都沒獲得鹦聪。此系列文章旨在加深自己的印象账阻,因...
    DCbryant閱讀 1,866評論 0 4
  • Transform字面上就是變形,改變的意思泽本。在CSS3中transform主要包括以下幾種:旋轉(zhuǎn)rotate宰僧、扭...
    hzrWeber閱讀 22,145評論 0 19
  • CSS里transform變形這個(gè)屬性有點(diǎn)學(xué)習(xí)難度,尤其在CSS3里加上了3D效果之后观挎,2維變3維學(xué)習(xí)成本更是成倍...
    張歆琳閱讀 27,879評論 5 81
  • 偶然在一篇曹將的公眾號(hào)上看到了印象筆記APP的介紹嘁捷,第一時(shí)間就下載嘗試造成。然而發(fā)現(xiàn)并沒有掌握這個(gè)應(yīng)用的精髓,于是乎雄嚣,...
    嘟嘟陳者閱讀 383評論 0 0