Flutter(59):Layout組件之Transform

1.Transform介紹

可以在其子組件繪制前對其應用一些矩陣變換來實現(xiàn)一些特效渗钉。
這里需要注意的是這種變換特效是應用在繪制階段而不是布局階段彤恶,也就是說子控件雖然進行了變換钞钙,但是他所占用的實際空間,位置等都是固定不變的声离,只是視覺上改變了芒炼。

2.Transform.rotate

  • angle:旋轉弧度 注意這里不是角度,需要將角度轉為弧度术徊,180度 = π弧度 即1度=π/180 弧度
  • origin:以某一個原點旋轉本刽,這個是相對于alignment位置所設置的Offset的偏移點為原點旋轉
  • alignment = Alignment.center:以alignment位置為原點旋轉
  • child:
    關于Alignment之前已經(jīng)介紹過了:Flutter(44):Layout組件之Container

這里的旋轉內部實現(xiàn)是Matrix4.rotationZ(angle)變換,即以Z軸為旋轉軸旋轉angle弧度
我們來看個例子:

  _myChild() {
    return Text(
      'Hello Flutter',
      style: TextStyle(
        backgroundColor: Colors.blue,
        fontSize: 20,
        color: Colors.white,
      ),
    );
  }

  _myTransformRotate() {
    return Stack(
      children: [
        Center(
          child: _myChild(),
        ),
        Center(
          child: Transform.rotate(
            angle: dartMath.pi * 0.25,
            alignment: Alignment.center,
            child: _myChild(),
          ),
        ),
        Center(
          child: Transform.rotate(
            angle: dartMath.pi * 0.25,
            origin: Offset(50, 50),
            alignment: Alignment.center,
            child: _myChild(),
          ),
        ),
        Center(
          child: Transform.rotate(
            angle: dartMath.pi * 0.25,
            alignment: null,
            child: _myChild(),
          ),
        ),
      ],
    );
  }

這里我們分別有四個“Hello Flutter”赠涮,第一個不做任何變換子寓;第二個設置Alignment.center為原點旋轉45度,即以控件的中心點旋轉45度笋除;第三個是以Alignment.center偏移Offset(50, 50)的點為原點旋轉15度斜友,即以控件的中心點,向右偏移50垃它,向下偏移50的一個點為原點旋轉45度鲜屏;第四個就是設置alignment旋轉45度,即以控件的Alignment.topLeft(左上角)為原點旋轉45度国拇。

  • Stack組件洛史,它是一個多子節(jié)點組件,支持疊放子控件酱吝,這個組件后面我們會詳細介紹也殖。
  • dartMath其實是導入的dart中的math
import 'dart:math' as dartMath;
image.png

3.Transform.translate

  • offset:Offset 偏移位置
  • child:

這里就是平移變換到原位置的Offset位置,內部實現(xiàn)是Matrix4.translationValues(offset.dx, offset.dy, 0.0)變換

  _myTransformTranslate() {
    return Stack(
      children: [
        Center(
          child: Transform.translate(
            offset: Offset(0, 0),
            child: _myChild(),
          ),
        ),
        Center(
          child: Transform.translate(
            offset: Offset(50, 50),
            child: _myChild(),
          ),
        ),
      ],
    );
  }

這里就是將“Hello Flutter”相對于原來位置向右平移50向下平移50

image.png

4.Transform.scale

  • scale:縮放系數(shù)
  • origin:以某一個原點縮放掉瞳,這個是相對于alignment位置所設置的Offset的偏移點為原點縮放
  • alignment = Alignment.center:以alignment位置為原點縮放
  • child:

這里的縮放內部實現(xiàn)是Matrix4.diagonal3Values(scale, scale, 1.0)變換

  _myTransformScale() {
    return Stack(
      children: [
        Center(
          child: Transform.scale(
            scale: 2,
            origin: Offset(50, 50),
            alignment: Alignment.center,
            child: _myChild(),
          ),
        ),
        Center(
          child: Transform.scale(
            scale: 2,
            alignment: Alignment.center,
            child: _myChild(),
          ),
        ),
        Center(
          child: Transform.scale(
            scale: 1,
            alignment: Alignment.center,
            child: _myChild(),
          ),
        ),
      ],
    );
  }

這里呢我們從下往上看毕源,最后一個就是以Alignment.center為原點縮放一倍,即維持原樣陕习;倒數(shù)第二個就是以Alignment.center為原點放大兩倍霎褐;倒數(shù)第三個也就是第一個是以Alignment.center向左偏移50,向下偏移50的位置為原點放大兩倍

image.png

5.Transform

  • transform:Matrix4
  • origin:相對于alignment的偏移原點
  • alignment:alignment
  • child:

前面幾種的變化其實都是基于Matrix4進行的變換该镣,那么如果以上三種無法滿足需求還有一種就是由你自己去設置transform變換

例如我們這里想實現(xiàn)一個以中心點為原點冻璃,X軸為旋轉軸旋轉180的變換

  _myTransform(Matrix4 transform) {
    return Center(
      child: Transform(
        transform: transform,
        alignment: Alignment.center,
        child: _myChild(),
      ),
    );
  }

      body: _myTransform(Matrix4.rotationX(dartMath.pi * 0.75)),
image.png

6.Matrix4

Matrix4還提供了非常之多的矩陣變換,例如沿Y軸旋轉损合,沿X扭曲省艳,沿Y軸扭曲,還支持復合嫁审。我們這里簡單介紹一些:

平移
  • Matrix4.translationValues(double x, double y, double z)
    x代表X軸跋炕,大于0向右,小于0向左律适;y代表Y軸辐烂,大于0向下遏插,小于0向上;z代表Z軸纠修,大于0凸起胳嘲,小于0下凹,但是這個在這種平面圖上是顯示不出來效果的扣草。
  • Matrix4.translation(Vector3 translation)
    這種方式是使用向量的方式了牛,需要import 'package:vector_math/vector_math_64.dart',
    Vector3(double x, double y, double z)辰妙,跟第一種本質沒區(qū)別鹰祸。
body: _myTransform(Matrix4.translationValues(-50, 20, 0)),
body: _myTransform(Matrix4.translation(vectorMath.Vector3(-50, 20, 0))),
body: _myTransform(
    Matrix4.translation(vectorMath.Vector3.array([-50, 20, 0]))),
image.png
旋轉
  • Matrix4.rotationX(double radians)
    X軸旋轉,旋轉弧度大于0就是由Y軸正方向向Z軸正方向旋轉密浑,小于0就是Z軸正方向向Y軸正方向旋轉
body: _myTransform(Matrix4.rotationX(dartMath.pi * 0.25)),
image.png
  • Matrix4.rotationY(double radians)
    沿Y軸旋轉福荸,旋轉弧度大于0就是由X軸正方向向Z軸正方向旋轉,小于0就是Z軸正方向向X軸正方向旋轉
body: _myTransform(Matrix4.rotationY(dartMath.pi * 0.25)),
image.png
  • Matrix4.rotationZ(double radians)
    沿Z軸旋轉肴掷,旋轉弧度大于0就是由Y軸正方向向X軸正方向旋轉,小于0就是X軸正方向向Y軸正方向旋轉
body: _myTransform(Matrix4.rotationZ(dartMath.pi * 0.25)),
image.png
縮放
  • Matrix4.diagonal3(Vector3(double x, double y, double z))
  • Matrix4.diagonal3Values(double x, double y, double z)
    這里的值表示縮放的比例背传,分別沿x,y,z三個方向呆瞻,x軸正向向右,y軸正向向下径玖,z軸正向從屏幕朝上痴脾,正值表示正向,>1表示放大梳星,小于1大于0表示縮小赞赖,負值表示反向,會翻轉冤灾。
body: _myTransform(Matrix4.diagonal3(vectorMath.Vector3(2, -0.8, 0))),
image.png
扭曲
  • Matrix4.skewX(double alpha)
    沿X軸扭曲
body: _myTransform(Matrix4.skewX(dartMath.pi * 0.25)),
image.png
  • Matrix4.skewY(double beta)
    沿Y軸扭曲
body: _myTransform(Matrix4.skewY(dartMath.pi * 0.25)),
image.png
  • Matrix4.skew(double alpha, double beta)
body: _myTransform(Matrix4.skew(dartMath.pi * 0.2,dartMath.pi * 0.1)),
image.png

其他還有使用矩陣創(chuàng)建前域,取反(inverted),合并(outer)韵吨,復合(compose)這些都些矩陣變換都需要對線性代數(shù)有了解了匿垄,這里就不說了。

7.驗證Transform變換是在繪制階段而不是在布局階段

  _myRow() {
    return Center(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Transform.scale(
            scale: 2,
            alignment: Alignment.center,
            child: _myChild(),
          ),
          _myChild()
        ],
      ),
    );
  }
image.png

這里可以看到前一個“Hello Flutter”放大后并沒有影響后面一個的位置归粉,由此也可以看出變換是繪制階段而不是在布局階段椿疗。這種矩陣變換的優(yōu)點就是發(fā)生在繪制階段,他不需要去重新布局或者構建糠悼,對性能上很友好届榄。

下一節(jié):Layout組件之UnconstrainedBox

Flutter(60):Layout組件之UnconstrainedBox

Flutter教學目錄持續(xù)更新中

Github源代碼持續(xù)更新中

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市倔喂,隨后出現(xiàn)的幾起案子铝条,更是在濱河造成了極大的恐慌靖苇,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攻晒,死亡現(xiàn)場離奇詭異顾复,居然都是意外死亡,警方通過查閱死者的電腦和手機鲁捏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門芯砸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人给梅,你說我怎么就攤上這事假丧。” “怎么了动羽?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵包帚,是天一觀的道長。 經(jīng)常有香客問我运吓,道長渴邦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任拘哨,我火速辦了婚禮谋梭,結果婚禮上,老公的妹妹穿的比我還像新娘倦青。我一直安慰自己瓮床,他們只是感情好,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布产镐。 她就那樣靜靜地躺著隘庄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪癣亚。 梳的紋絲不亂的頭發(fā)上丑掺,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音逃糟,去河邊找鬼吼鱼。 笑死,一個胖子當著我的面吹牛绰咽,可吹牛的內容都是我干的菇肃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼取募,長吁一口氣:“原來是場噩夢啊……” “哼琐谤!你這毒婦竟也來了?” 一聲冷哼從身側響起玩敏,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤斗忌,失蹤者是張志新(化名)和其女友劉穎质礼,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體织阳,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡眶蕉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了唧躲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片造挽。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖弄痹,靈堂內的尸體忽然破棺而出饭入,到底是詐尸還是另有隱情,我是刑警寧澤肛真,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布谐丢,位于F島的核電站,受9級特大地震影響蚓让,放射性物質發(fā)生泄漏乾忱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一历极、第九天 我趴在偏房一處隱蔽的房頂上張望饭耳。 院中可真熱鬧,春花似錦执解、人聲如沸耳标。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽读虏。三九已至浮定,卻和暖如春哑舒,著一層夾襖步出監(jiān)牢的瞬間砰奕,已是汗流浹背脯丝。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工吮螺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饶囚,地道東北人。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓鸠补,卻偏偏與公主長得像萝风,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子紫岩,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355