最近在做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.
也就是如下這幅圖仪糖,出自這里
翻譯一下就是,要想指定變換原點(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).如下圖
結(jié)語
我這代碼中的矩陣操作全是手動(dòng)擼的纱皆,矩陣變換本來就是個(gè)麻煩而且枯燥的工作湾趾,所以如果大家在實(shí)際項(xiàng)目中需要用到各種矩陣操作的話,可以推薦 gl-matrix 這個(gè)庫派草。react-native項(xiàng)目里面的話搀缠,可以直接使用 MatrixMath 模塊。
如果深究一下css 的transform 文檔近迁,其實(shí)會(huì)發(fā)現(xiàn)所有的變換都可以用矩陣來表示艺普,比如perspective
,perspective-origin
等屬性鉴竭。