Flutter 之 变换(Transform)(四十二)
Transform可以在其子组件绘制时对其应用一些矩阵变换来实现一些特效
Matrix4是一个4D矩阵,通过它我们可以实现各种矩阵操作
示例
Container(
color: Colors.black,
child: Transform(
alignment: Alignment.topRight, //相对于坐标系原点的对齐方式
transform: Matrix4.skewY(0.3), //沿Y轴倾斜0.3弧度
child: Container(
padding: const EdgeInsets.all(8.0),
color: Colors.deepOrange,
child: const Text('Apartment for rent!'),
),
),
)
image.png
1. Transform
1.1 Transform.translate 平移
Transform.translate接收一个offset参数,可以在绘制时沿x、y轴对子组件平移指定的距离。
Transform.translate 定义
Transform.translate({
Key? key,
required Offset offset,
this.transformHitTests = true,
this.filterQuality,
Widget? child,
}) : transform = Matrix4.translationValues(offset.dx, offset.dy, 0.0),
origin = null,
alignment = null,
super(key: key, child: child);
示例
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
//默认原点为左上角,左移20像素,向上平移5像素
child: Transform.translate(
offset: Offset(-20.0, -5.0),
child: Text("Hello World"),
),
),
image.png
1.2 Transform.rotate 旋转
Transform.rotate可以对子组件进行旋转变换
Transform.rotate 定义
Transform.rotate({
Key? key,
required double angle,
this.origin,
this.alignment = Alignment.center,
this.transformHitTests = true,
this.filterQuality,
Widget? child,
}) : transform = Matrix4.rotationZ(angle),
super(key: key, child: child);
示例
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
// 旋转90度
child: Transform.rotate(
angle: pi / 2,
child: Text("Hello World"),
),
),
image.png
1.3 Transform.scale 缩放
Transform.scale可以对子组件进行缩小或放大
Transform.scale 定义
Transform.scale({
Key? key,
double? scale,
double? scaleX,
double? scaleY,
this.origin,
this.alignment = Alignment.center,
this.transformHitTests = true,
this.filterQuality,
Widget? child,
}) : assert(!(scale == null && scaleX == null && scaleY == null), "At least one of 'scale', 'scaleX' and 'scaleY' is required to be non-null"),
assert(scale == null || (scaleX == null && scaleY == null), "If 'scale' is non-null then 'scaleX' and 'scaleY' must be left null"),
transform = Matrix4.diagonal3Values(scale ?? scaleX ?? 1.0, scale ?? scaleY ?? 1.0, 1.0),
super(key: key, child: child);
示例
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Transform.scale(
// 放大2.5倍
scale: 2.5,
child: Text("Hello World"),
),
),
image.png
1.4 Transform 注意事项
Transform的变换是应用在绘制阶段,而并不是应用在布局(layout)阶段,所以无论对子组件应用何种变化,其占用空间的大小和在屏幕上的位置都是固定不变的,因为这些是在布局阶段就确定的
示例
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Transform.scale(
scale: 1.5,
child: Text("Hello World"),
),
),
Text("你好"),
],
)
image.png
由于第一个Text应用变换(放大)后,其在绘制时会放大,但其占用的空间依然为红色部分,所以第二个Text会紧挨着红色部分,最终就会出现文字重合
由于矩阵变化只会作用在绘制阶段,所以在某些场景下,在UI需要变化时,可以直接通过矩阵变化来达到视觉上的UI改变,而不需要去重新触发build流程,这样会节省layout的开销,所以性能会比较好。
如 Flow组件,它内部就是用矩阵变换来更新UI,除此之外,Flutter的动画组件中也大量使用了Transform以提高性能
2. RotatedBox
RotatedBox和Transform.rotate功能相似,它们都可以对子组件进行旋转变换,但是有一点不同:RotatedBox的变换是在layout阶段,会影响在子组件的位置和大小
示例
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: RotatedBox(
quarterTurns: 1,
child: Text("Hello World"),
),
),
Text("你好"),
],
),
image.png
由于RotatedBox是作用于layout阶段,所以子组件会旋转90度(而不只是绘制的内容),decoration会作用到子组件所占用的实际空间上,所以最终就是上图的效果。