老孟导读:此文讲解3个酷炫的3D动画效果。
下面是要实现的效果:
Flutter 中3D效果是通过 Transform 组件实现的,没有变换效果的实现:
class TransformDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('3D 变换Demo'),),body: Container(
alignment: Alignment.center,color: Colors.white,child: Text('3D 变换Demo'),);
}
}
通过 GestureDetector 组件添加滑动事件监听:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('3D 变换Demo'),body: GestureDetector(
onPanUpdate: (details) {
print('$details');
},child: Container(
alignment: Alignment.center,);
}
添加 Transform 对组件进入旋转:
@override
Widget build(BuildContext context) {
return Transform(
transform: Matrix4.identity()
..setEntry(3,2,0.001)
..rotateX(pi/6)
..rotateY(pi/6),alignment: Alignment.center,child: Scaffold(
appBar: AppBar(
title: Text('3D 变换Demo'),body: GestureDetector(
onPanUpdate: (details) {
},child: Container(
alignment: Alignment.center,));
}
将滑动的偏移和旋转进行关联:
class TransformDemo extends StatefulWidget {
@override
_TransformDemoState createState() => _TransformDemoState();
}
class _TransformDemoState extends State<TransformDemo> {
double _rotateX = .0;
double _rotateY = .0;
@override
Widget build(BuildContext context) {
return Transform(
transform: Matrix4.identity()
..rotateX(_rotateX)
..rotateY(_rotateY),child: Scaffold(
appBar: AppBar(
title: Text('3D 变换Demo'),body: GestureDetector(
onPanUpdate: (details) {
setState(() {
_rotateX += details.delta.dy * .01;
_rotateY += details.delta.dx * -.01;
});
},child: Container(
alignment: Alignment.center,));
}
}
基本已经实现了3D效果,但效果比较生硬,尤其垂直方向旋转的时候远点和近点在屏幕上的宽度是一样,
Transform(
transform: Matrix4.identity()
..setEntry(3,0.001)
..rotateX(_rotateX)
..rotateY(_rotateY),...
翻书效果
实现的原理:
将图片左右切割为两部分,两张图片共分割为4个新的组件,如下图,分别为1、2、3、4
代码实现:
_child1 = ClipRect(
child: Align(
alignment: Alignment.centerLeft,widthFactor: 0.5,child: child1,);
_child2 = ClipRect(
child: Align(
alignment: Alignment.centerRight,);
_child3 = ClipRect(
child: Align(
alignment: Alignment.centerLeft,child: child2,);
_child4 = ClipRect(
child: Align(
alignment: Alignment.centerRight,);
将第一张图片放在第二种图片的上面,先旋转 组件2 从 0度到 90度,然后再旋转 组件3 从 -90度到0度,代码实现:
Row(
mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
Stack(
children: [
_child1,Transform(
alignment: Alignment.centerRight,transform: Matrix4.identity()
..setEntry(3,0.001)
..rotateY(_animation1.value),child: _child3,],Container(
width: 3,Stack(
children: [
_child4,Transform(
alignment: Alignment.centerLeft,0.001)
..rotateY(_animation.value),child: _child2,)
],)
],)
动画控制器设置:
@override
void initState() {
init();
_controller =
AnimationController(vsync: this,duration: Duration(seconds: 5))
..addListener(() {
setState(() {});
});
_animation = Tween(begin: .0,end: pi / 2)
.animate(CurvedAnimation(parent: _controller,curve: Interval(.0,.5)));
_animation1 = Tween(begin: -pi / 2,end: 0.0).animate(
CurvedAnimation(parent: _controller,curve: Interval(.5,1.0)));
_controller.forward();
super.initState();
}
_FlipUpDemoState(
Container(
width: 300,height: 400,child: Image.asset(
'assets/images/b.jpg',fit: BoxFit.cover,Container(
width: 300,child: Image.asset(
'assets/images/c.jpeg',))
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),body: Column(
mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
Stack(
children: [
_upperChild1,Transform(
alignment: Alignment.bottomCenter,transform: Matrix4.identity()
..setEntry(3,0.003)
..rotateX(_animation1.value),child: _upperChild2,SizedBox(
height: 2,Stack(
children: [
_lowerChild2,Transform(
alignment: Alignment.topCenter,0.003)
..rotateX(_animation.value),child: _lowerChild1,)
],);
}
交流
老孟Flutter博客地址(330个控件用法):http://laomengit.com
欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】: