Flutter教学

Flutter(59):Layout组件之Transform

2020-10-20  本文已影响0人  starryxp

Flutter教学目录持续更新中

Github源代码持续更新中

1.Transform介绍

可以在其子组件绘制前对其应用一些矩阵变换来实现一些特效。
这里需要注意的是这种变换特效是应用在绘制阶段而不是布局阶段,也就是说子控件虽然进行了变换,但是他所占用的实际空间,位置等都是固定不变的,只是视觉上改变了。

2.Transform.rotate

这里的旋转内部实现是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度。

import 'dart:math' as dartMath;
image.png

3.Transform.translate

这里就是平移变换到原位置的Offset位置,内部实现是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

这里的缩放内部实现是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为原点缩放一倍,即维持原样;倒数第二个就是以Alignment.center为原点放大两倍;倒数第三个也就是第一个是以Alignment.center向左偏移50,向下偏移50的位置为原点放大两倍

image.png

5.Transform

前面几种的变化其实都是基于Matrix4进行的变换,那么如果以上三种无法满足需求还有一种就是由你自己去设置transform变换

例如我们这里想实现一个以中心点为原点,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轴扭曲,还支持复合。我们这里简单介绍一些:

平移
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
旋转
body: _myTransform(Matrix4.rotationX(dartMath.pi * 0.25)),
image.png
body: _myTransform(Matrix4.rotationY(dartMath.pi * 0.25)),
image.png
body: _myTransform(Matrix4.rotationZ(dartMath.pi * 0.25)),
image.png
缩放
body: _myTransform(Matrix4.diagonal3(vectorMath.Vector3(2, -0.8, 0))),
image.png
扭曲
body: _myTransform(Matrix4.skewX(dartMath.pi * 0.25)),
image.png
body: _myTransform(Matrix4.skewY(dartMath.pi * 0.25)),
image.png
body: _myTransform(Matrix4.skew(dartMath.pi * 0.2,dartMath.pi * 0.1)),
image.png

其他还有使用矩阵创建,取反(inverted),合并(outer),复合(compose)这些都些矩阵变换都需要对线性代数有了解了,这里就不说了。

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”放大后并没有影响后面一个的位置,由此也可以看出变换是绘制阶段而不是在布局阶段。这种矩阵变换的优点就是发生在绘制阶段,他不需要去重新布局或者构建,对性能上很友好。

下一节:Layout组件之UnconstrainedBox

Flutter(60):Layout组件之UnconstrainedBox

Flutter教学目录持续更新中

Github源代码持续更新中

上一篇下一篇

猜你喜欢

热点阅读