在Flutter中,Transform组件通过4×4矩阵(Matrix4)实现旋转、缩放、平移、倾斜和3D透视效果。当迁移到鸿蒙ArkTS时,虽然没有直接的Transform组件,但通过属性级联和matrix接口可以完成绝大部分变换需求。本文基于实际迁移经验,梳理ArkTS中实现3D变换的关键写法、适配细节以及常见踩坑点。
一、ArkTS变换基础
ArkTS的变换操作更接近CSS的写法,支持直接在组件属性上链式配置。例如:- Image('bg.jpg')
- .rotate({ x: -1, y: 0, z: 0, angle: 30 })
- .scale({ x: 1.2, y: 1.2 })
复制代码
对于更复杂的矩阵变换(如透视、倾斜),需要使用matrix属性传入一个4×4的数组。数组顺序与Matrix4一致,按行优先排列。
二、基础变换实现
1. 旋转
与Flutter的Transform.rotate类似,ArkTS通过.rotate()设置绕轴旋转角度(角度制)。- Text('旋转45度')
- .rotate({ x: 0, y: 0, z: 1, angle: 45 })
复制代码 注意:z轴正方向为屏幕向外,正角度为顺时针,负角度为逆时针。
2. 缩放- Text('缩放1.5倍')
- .scale({ x: 1.5, y: 1.5 })
复制代码 scale只支持2D缩放,如果需要3D非均匀缩放,需使用matrix属性。
3. 平移
ArkTS没有.translate(),但可以通过matrix方式实现,或使用offset属性(仅部分组件支持)。更通用的方式是直接修改组件的position或margin。
4. 倾斜(Skew)
Flutter通过Matrix4.skewX/skewY实现,ArkTS同样需要自定义matrix:- // X轴倾斜0.3弧度(约17度)
- Image('test.jpg')
- .matrix([
- 1, Math.tan(0.3), 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
- ])
复制代码 注意:ArkTS中matrix属性需要传入number[16]数组,且三角函数需使用Math对象。
5. 3D透视与绕轴旋转
Flutter中透视通过setEntry(3,2, value)实现,ArkTS中透视系数放在矩阵的(3,2)位置(即第3行第2列,数组索引为14):- // 绕Y轴旋转45度,透视强度0.002
- Column()
- .matrix([
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0.002, 1
- ])
- .rotate({ x: 0, y: 1, z: 0, angle: 45 })
复制代码 注意:绕Y轴旋转需要使用.rotate(),而matrix中的透视系数需要手动组合。因为ArkTS的matrix和rotate是叠加关系,旋转矩阵的生成逻辑需要自行计算并填入matrix。更推荐的做法是纯用matrix实现完整变换矩阵,避免混用。
三、3D翻转卡片(带透视)
ArkTS实现翻牌的思路与Flutter类似:
- 通过animation驱动角度变化;
- 前半段显示正面,后半段显示反面,反面内容需额外旋转180度以消除镜像。- // 简化示意
- @State angle: number = 0;
- build() {
- return Stack() {
- if (this.angle < 90) {
- // 正面
- CardFront()
- .rotate({ x: 0, y: 1, z: 0, angle: this.angle })
- .matrix(this.perspectiveMatrix)
- } else {
- // 反面,需再绕Y轴旋转180度
- CardBack()
- .rotate({ x: 0, y: 1, z: 0, angle: 180 })
- .matrix(this.perspectiveMatrix)
- }
- }.onClick(() => {
- // 动画驱动this.angle在0~180之间变化
- })
- }
复制代码 注意:ArkTS的旋转角度是角度制,而Flutter是弧度制。
四、踩坑记录(Flutter迁移经验)
1. 矩阵顺序
ArkTS中同时使用.rotate()和.matrix()时,先后顺序会影响最终效果。建议全部使用matrix属性一次性定义变换矩阵,避免混淆。
2. 透视值的选择
Flutter中0.002是适中值;ArkTS中相同透视值的效果基本一致,但需注意单位。如果卡片尺寸小(如200×300),透视值可调大至0.005;若卡片很大(如全屏),应调小至0.001。
3. 镜像问题
ArkTS中绕Y轴旋转超过90度后,文字默认不会自动翻转。需要在显示反面时主动再绕Y轴旋转180度。
4. offset与alignment
Flutter中的alignment和origin控制变换中心,ArkTS中可以通过.transformOrigin(百分比或像素偏移)实现类似效果:- Text('左上角旋转')
- .transformOrigin({ x: 0, y: 0 })
- .rotate({ z: 1, angle: 45 })
复制代码 注意:transformOrigin默认值(0.5, 0.5)对应中心。
5. 越界裁剪
Flutter中Transform不改变布局,可能导致越界。ArkTS中,变换同样不影响父容器尺寸。如需裁剪,使用.clip形状或设置overflow: Clip。
五、选型建议
- 纯2D旋转/缩放:优先使用.rotate()/.scale(),简洁直观。
- 倾斜/透视/3D翻转:使用.matrix()一次性传入组合矩阵。
- 动画场景:配合@State动画变量和onClick/onPan事件驱动。
- 性能注意:频繁更新matrix属性可能触发重绘,建议使用animateTo或弹簧动画减少计算。
从Flutter迁移到鸿蒙ArkTS,虽然API形态不同,但底层矩阵数学一致。掌握Matrix4到ArkTS矩阵数组的映射关系,即可流畅实现所有3D变换效果。 |