天天看點

Flutter 44: 圖解矩陣變換 Transform 類 (一)

      小菜在學習矩陣變換時需要用到 Transform 類,可以實作子 Widget 的 scale 縮放 / translate 平移 / rotate 旋轉 / skew 斜切 等效果,對應于 Canvas 繪制過程中的矩陣變換等;小菜今對此進行初步整理;

scale 縮放

      scale 縮放 可以通過 Transform 提供的構造方法或 Matrix4 矩陣變化來實作;

Transform.scale 構造方法

Transform.scale({
    Key key,
    @required double scale,     // 縮放比例
    this.origin,    // 縮放原點
    this.alignment = Alignment.center,  // 對齊方式
    this.transformHitTests = true,
    Widget child,
}) : transform = Matrix4.diagonal3Values(scale, scale, 1.0),
    super(key: key, child: child);           

Tips:

  1. 設定縮放比例後,水準/豎直方向按同比例縮放,z 軸方向不縮放;
  2. 對齊方式是與初始位置為準;
Center(
    child: Transform.scale(
        scale: 1.2,
//      origin: Offset(120.0, 120.0),
        alignment: Alignment.bottomRight,
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(
                    color: Colors.blueAccent))))),           

Transform Matrix4 方式

void scale(dynamic x, [double y, double z]) {}           

      Matrix4 為 4D 矩陣,使用更靈活,可以分别設定 x / y / z 軸方向縮放比例;若隻設定一個則水準/垂直方向同比例縮放;

Center(
    child: Transform(
        transform: Matrix4.identity()
          ..scale(1.2, 1.0, 0.5),
        alignment: Alignment.bottomRight,
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(
                    color: Colors.blueAccent)))))           

translate 平移

      translate 平移 可通過構造方法或 Matrix4 矩陣變化來實作;

Transform.translate 構造方法

Transform.translate({
    Key key,
    @required Offset offset,
    this.transformHitTests = true,
    Widget child,
}) : transform = Matrix4.translationValues(offset.dx, offset.dy, 0.0),
    origin = null,
    alignment = null,
    super(key: key, child: child);           

      translate 按坐标點 Offset 平移,水準向右為正向,豎直向下為正向;z 軸方向不平移;

Center(
    child: Transform.translate(
        offset: Offset(60.0, -40.0),
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(
                    color: Colors.blueAccent))))),           

void translate(dynamic x, [double y = 0.0, double z = 0.0]) {}           

      Matrix4 平移方式可分别設定 x / y / z 軸方向平移量,必須設定 x 軸方向平移量;

Center(
    child: Transform(
        transform: Matrix4.identity()
          ..translate(60.0, -40.0, 100.0),
        alignment: Alignment.bottomRight,
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(
                    color: Colors.blueAccent))))),           

rotate 旋轉

      rotate 旋轉可通過構造方法或 Matrix4 矩陣變化來實作;

Taransform.rotate 構造方法

Transform.rotate({
    Key key,
    @required double angle,     // 旋轉角度
    this.origin,
    this.alignment = Alignment.center,
    this.transformHitTests = true,
    Widget child,
}) : transform = Matrix4.rotationZ(angle),
       super(key: key, child: child);           

      由此可看出旋轉是沿 z 軸旋轉,即垂直手機螢幕方向,視覺上的正常旋轉;

Center(
    child: Transform.rotate(
        angle: pi / 4,
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(
                    color: Colors.blueAccent))))),           

void rotate(Vector3 axis, double angle) {}           

      Matrix4 可靈活設定旋轉方向,包括沿 x / y / z 軸方向立體旋轉,且旋轉效果可以重疊;而 Matrix4 也提供了兩種旋轉方式;

  1. Matrix4.rotationZ
  2. Matrix4.identity()..rotateZ

      對于單軸旋轉,兩種方式實際是完全相同的,且第一種方式隻可進行單軸旋轉;第二種方式更靈活,可以多個軸疊加;

Center(
    child: Transform(
        transform: Matrix4.rotationZ(pi / 4),
        alignment: Alignment.center,
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(
                    color: Colors.blueAccent))))),
Center(
    child: Transform(
        transform: Matrix4.identity()..rotateX(pi / 4),
        alignment: Alignment.center,
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(
                    color: Colors.greenAccent))))),
Center(
    child: Transform(
        transform: Matrix4.identity()..rotateY(pi / 4),
        alignment: Alignment.center,
        child: ClipOval(
            child: SizedBox(
                width: 120.0,
                height: 80.0,
                child: Container(color: Colors.brown))))),
Center(
    child: ClipOval(
        child: SizedBox(
            width: 120.0,
            height: 80.0,
            child: Container(color: Colors.black12))))           

skew 斜切

      Transform 未提供關于 skew 斜切的構造方法,隻能用 Matrix4 方式建構;

  1. skewX 沿水準方向斜切;
  2. skewY 沿豎直方向斜切;
  3. skew 與 x / y 軸共同矩陣轉換産生斜切;
Center(
    child: Transform(
        transform: Matrix4.skewY(pi / 4),
        alignment: Alignment.topLeft,
        child: Container(
            width: 120.0,
            height: 80.0,
            color: Colors.brown))),
Center(
    child: Transform(
        transform: Matrix4.skewX(pi / 4),
        alignment: Alignment.topLeft,
        child: Container(
            width: 120.0,
            height: 80.0,
            color: Colors.redAccent))),
Center(
    child: Transform(
        transform: Matrix4.skew(pi / 6, pi / 6),
        alignment: Alignment.topLeft,
        child: Container(
            width: 120.0,
            height: 80.0,
            color: Colors.white70))),
Center(
    child: Transform(
        transform: Matrix4.skew(0.0, 0.0),
        alignment: Alignment.topLeft,
        child: Container(
            width: 120.0,
            height: 80.0,
            color: Colors.black12))),           

      所有的矩陣變換均可通過 Matrix4 疊加,在實際應用中更加靈活,下節會重點學習 Matrix4 矩陣方面的小知識點;

      如有錯誤請多多指導!

繼續閱讀