您的位置:首页 > 其它

腾讯大佬教你6个操作,快速用Flutter 实现酷炫的3D效果

2020-07-24 14:00 239 查看

下面是要实现的效果:

Flutter 中3D效果是通过 Transform 组件实现的,没有变换效果的实现:

[code]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 组件添加滑动事件监听:

[code]@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('3D 变换Demo'),
),
body: GestureDetector(
onPanUpdate: (details) {
print('$details');
},
child: Container(
alignment: Alignment.center,
color: Colors.white,
child: Text('3D 变换Demo'),
),
),
);
}

添加 Transform 对组件进入旋转:

[code]@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,
color: Colors.white,
child: Text('3D 变换Demo'),
),
),
));
}

将滑动的偏移和旋转进行关联:

[code]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),
alignment: Alignment.center,
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,
color: Colors.white,
child: Text('3D 变换Demo'),
),
),
));
}
}

基本已经实现了3D效果,但效果比较生硬,尤其垂直方向旋转的时候远点和近点在屏幕上的宽度是一样,

添加近大远小的效果:

[code]Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateX(_rotateX)
..rotateY(_rotateY),
...

翻书效果

上面的效果类似于翻书的效果。

实现的原理:

将图片左右切割为两部分,两张图片共分割为4个新的组件,如下图,分别为1、2、3、4

代码实现:

[code]_child1 = ClipRect(
child: Align(
alignment: Alignment.centerLeft,
widthFactor: 0.5,
child: child1,
),
);
_child2 = ClipRect(
child: Align(
alignment: Alignment.centerRight,
widthFactor: 0.5,
child: child1,
),
);

_child3 = ClipRect(
child: Align(
alignment: Alignment.centerLeft,
widthFactor: 0.5,
child: child2,
),
);

_child4 = ClipRect(
child: Align(
alignment: Alignment.centerRight,
widthFactor: 0.5,
child: child2,
),
);

将第一张图片放在第二种图片的上面,先旋转 组件2 从 0度到 90度,然后再旋转 组件3 从 -90度到0度,代码实现:

[code]Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Stack(
children: [
_child1,
Transform(
alignment: Alignment.centerRight,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(_animation1.value),
child: _child3,
),
],
),
Container(
width: 3,
color: Colors.white,
),
Stack(
children: [
_child4,
Transform(
alignment: Alignment.centerLeft,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(_animation.value),
child: _child2,
)
],
)
],
)

动画控制器设置:

[code]@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();
}

其中 child1, child2为两种图片,代码如下:

[code]_FlipUpDemoState(
Container(
width: 300,
height: 400,
child: Image.asset(
'assets/images/b.jpg',
fit: BoxFit.cover,
),
),
Container(
width: 300,
height: 400,
child: Image.asset(
'assets/images/c.jpeg',
fit: BoxFit.cover,
),
))

最后生成的效果就是开始的翻书效果。

上面是左右翻页效果,同理换成上下翻页效果:

[code]@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, 2, 0.003)
..rotateX(_animation1.value),
child: _upperChild2,
),
],
),
SizedBox(
height: 2,
),
Stack(
children: [
_lowerChild2,
Transform(
alignment: Alignment.topCenter,
transform: Matrix4.identity()
..setEntry(3, 2, 0.003)
..rotateX(_animation.value),
child: _lowerChild1,
)
],
)
],
),
);
}

交流

欢迎加入Android技术交流群、关注公众号谈谈Android那些事

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: