一、变换Transform
对其子部件应用各种变换,例如平移(Translation)、旋转(Rotation)、缩放(Scale)
1. 缩放
Transform.scale(
scale: 0.5,
child: Container(
padding: const EdgeInsets.all(8.0),
color: const Color(0xFFE8581C),
child: const Text('Bad Idea Bears'),
),
/// )
- 旋转
Transform.rotate(
angle: 30 * (pi / 180),//30度
origin: Offset(50,50),//默认中心,这里设置右下角
child: Container(
padding: const EdgeInsets.all(8.0),
color: Colors.green,
width: 100,
height: 100,
),
)
3. 组合
var combinedMatrix = Matrix4.identity();
combinedMatrix.scale(1.5, 1.5, 1.0); // 缩放
combinedMatrix.rotateZ(0.3); // 旋转
combinedMatrix.translate(10.0, 20.0, 0.0); // 平移
Transform(
transform: combinedMatrix,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
Transform(
alignment: Alignment(0.5, 0),
transform: Matrix4.identity()
..scale(_scaleAnimation.value)
..rotateZ(_scaleAnimation.value * 3.14),
child: Container(
padding: const EdgeInsets.all(8.0),
color: const Color(0xFFE8581C),
width: 100,
height: 100,
),
)
4. 变换原点
默认的变换原点是被变换部件的左上角(0,0)位置
以中心为原点
Transform(
alignment: Alignment.center,
transform: combinedMatrix,
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
)
自定义原点位置
Alignment的坐标中,(0.0, 0.0) 表示部件的中心位置(水平和垂直方向的中心)。水平方向上,-1.0 表示最左边,1.0 表示最右边;垂直方向上,-1.0 表示最上边,1.0 表示最下边(可以自己画一个,x轴向右,Y轴向下的坐标轴)
Transform.scale(
...
alignment: Alignment(0, -1.0),
)
二、动起来
使用AnimationController和Tween实现动画
- 单个
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_animation = Tween<double>(begin: 1.0, end: 1.2).animate(_controller);
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 60),
child: AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget? child) {
return Transform.scale(
scale: _animation.value,
alignment: Alignment(0, -1.0),
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
);
},
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
- 多个动画
先放大再缩小
_scaleController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
_scaleAnimation = Tween<double>(begin: 0.0, end: 1.1).animate(CurvedAnimation(
parent: _scaleController,
curve: const Interval(0.0, 2 / 3, curve: Curves.linear),
));
_scaleController.addListener(() {
if (_scaleController.value >= 2 / 3) {
_scaleAnimation = Tween<double>(begin: 1.1, end: 1.0).animate(CurvedAnimation(
parent: _scaleController,
curve: const Interval(2 / 3, 1, curve: Curves.linear),
));
}
});
// 启动动画
_animationController.forward();
AnimatedBuilder(
animation: _scaleAnimation,
builder: (BuildContext context, Widget? child) {
return Transform.scale(
scale: _scaleAnimation.value,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
);
},
),
- 另一种方式:TweenSequenceItem多个动画
_scaleController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 750),
);
_scaleAnimation = TweenSequence([
TweenSequenceItem(
tween: Tween<double>(begin: 0.0, end: 1.1).chain(CurveTween(curve: Curves.linear)),
weight: 2 / 3,
),
TweenSequenceItem(
tween: Tween<double>(begin: 1.1, end: 1.0).chain(CurveTween(curve: Curves.linear)),
weight: 1 / 3,
),
]).animate(_scaleController);
_scaleController.addListener(() {
setState(() {});
});
- 当需要控制原点,却不知道子控件大小情况
[本想用AnimatedBuilder,但是不行,不得不setState,后续有其他方案了再更新]
_scaleController.addListener(() {
setState(() {});//这样RenderBox才能获取到值
});
...
RenderBox? renderBox = context.findRenderObject() as RenderBox?;
Size size = renderBox?.size ?? Size.zero;
Transform.scale(
scale: scale,
alignment: Alignment(centerOffsetX / (size.width / 2), -1.0),
child: child,
)
三、Matrix4
- 变形
_skewAnimation = Tween<double>(begin: 0, end: 0.2).animate(
_animationController
);
AnimatedBuilder(
animation: _skewAnimation,
builder: (context, child) {
return Transform(
transform: Matrix4.skewY(_skewAnimation.value),
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
);
},
)