大数跨境
0
0

如何使用 Flutter 更好的平滑视差效果?

如何使用 Flutter 更好的平滑视差效果? RTE开发者社区
2021-02-26
0
导读:你看过Apple iOS的视差壁纸吗?
你看过Apple iOS的视差壁纸吗?如果你在iOS的墙纸设置中启用“透视缩放”,你会发现你的主屏幕将根据设备的倾斜/位置做出视觉响应。这虽然是简单的视觉上的把戏,却令人印象深刻。

以下是我们今天要构建的示例:


注意:本文中所有图像都在FAIR USE内使用,并且实际文件不外传。

开始啦..

我们将使用Flutter的官方传感器插件来获取设备的倾斜/旋转。

只需将以下内容作为你的依赖项,然后在项目文件夹中运行“pub get”就能完成简单的安装了。

  
1sensors: ^0.4.2+6

注意:需检查并使用最新版本。在写本文时,我使用了以上叙述的版本。

现在我们需要两张图像,一张用作星空背景,另一张用于行星。我们要确保行星的图像是透明的,因为我们要将它堆叠在背景图像的顶部。

我们将用Stack小部件来放置图像。将小部件放在堆栈里的图像中。

对于设备的倾斜/旋转检测,我们将使用运动事件来获取x、y轴上的加速度。

开始编写

  
1class PerspectiveZoomDemo extends StatefulWidget {
2  PerspectiveZoomDemo({
3    Key key,
4  }) : super(key: key);
5
6  @override
7  _PerspectiveZoomDemoState createState() => _PerspectiveZoomDemoState();
8}
9
10class _PerspectiveZoomDemoState extends State<PerspectiveZoomDemo{
11  AccelerometerEvent acceleration;
12  StreamSubscription<AccelerometerEvent> _streamSubscription;
13
14  int planetMotionSensitivity = 4;
15  int bgMotionSensitivity = 2;
16
17  @override
18  void initState() {
19    _streamSubscription = accelerometerEvents.listen((AccelerometerEvent event) {
20      setState(() {
21        acceleration = event;
22      });
23    });
24    super.initState();
25  }
26
27  @override
28  void dispose() {
29    _streamSubscription.cancel();
30    super.dispose();
31  }
32
33  @override
34  Widget build(BuildContext context) {
35    return Scaffold(
36      backgroundColor: Colors.black,
37      body: Center(
38        child: Stack(
39          children: <Widget>[
40            Positioned(
41              top: acceleration.y * bgMotionSensitivity,
42              bottom: acceleration.y * -bgMotionSensitivity,
43              right: acceleration.x * -bgMotionSensitivity,
44              left: acceleration.x * bgMotionSensitivity,
45              child: Align(
46                child: Image.asset(
47                  "assets/images/bg.jpg",
48                  height: 1920,
49                  fit: BoxFit.fitHeight,
50                ),
51              ),
52            ),
53            Positioned(
54              top: acceleration.y * planetMotionSensitivity,
55              bottom: acceleration.y * -planetMotionSensitivity,
56              right: acceleration.x * -planetMotionSensitivity,
57              left: acceleration.x * planetMotionSensitivity,
58              child: Align(
59                child: Image.asset(
60                  "assets/images/earth_2.png",
61                  width: 250,
62                ),
63              ),
64            ),
65          ],
66        ),
67      ),
68    );
69  }
70}

说明:
我们已经订阅了设备的accelerometer events,并且正在乘数bgMotionSensitivity和planetMotionSensitivity的基础上更改背景和行星图像的位置。

问:为什么bgMotionSensitivity低于planetMotionSensitivity?
答:这是因为视差效果的工作原理,即离你较远的对象要比离你近的对象移动得慢。

结果:
行星和背景对设备运动的响应及时,但是…



如果对它进行试运行,你就会发现它非常不稳定并且断断续续的。
那我们在哪里做错了呢?

问题及解决方案
这里的问题是加速度计的事件太快了,并且值变化得也很快,因此每当值突然变化时,我们的动画就会停顿。

我们需要添加某种过渡延迟来填补这些快速变化的值。幸运的是,flutter提供了一个名为AnimatedPositioned的小部件,它可以在Stack小部件中使用。

解决方案:

  
1AnimatedPositioned(
2    duration: Duration(milliseconds: 250),
3    top: acceleration.y * bgMotionSensitivity,
4    bottom: acceleration.y * -bgMotionSensitivity,
5    right: acceleration.x * -bgMotionSensitivity,
6    left: acceleration.x * bgMotionSensitivity,
7    child: Align(
8      child: Image.asset(
9        "assets/images/bg.jpg",
10        height: 1920,
11        fit: BoxFit.fitHeight,
12      ),
13    ),
14  ),
15  AnimatedPositioned(
16    duration: Duration(milliseconds: 250),
17    top: acceleration.y * planetMotionSensitivity,
18    bottom: acceleration.y * -planetMotionSensitivity,
19    right: acceleration.x * -planetMotionSensitivity,
20    left: acceleration.x * planetMotionSensitivity,
21    child: Align(
22      child: Image.asset(
23        "assets/images/earth_2.png",
24        width: 250,
25      ),
26    ),
27  ),

说明:
我们已用AnimatedPositioned替换了Positioning,并设置了一些延迟(以毫秒为单位)以创建平滑的过渡效果。

结果

它就像漂浮在屏幕中一样流畅。
这可以用作登录或介绍屏幕的良好背景。

【声明】内容源于网络
0
0
RTE开发者社区
RTE 开发者社区是聚焦实时互动领域的中立开发者社区。不止于纯粹的技术交流,我们相信开发者具备更加丰盈的个体价值。行业发展变革、开发者职涯发展、技术创业创新资源,我们将陪跑开发者,共享、共建、共成长。
内容 1122
粉丝 0
RTE开发者社区 RTE 开发者社区是聚焦实时互动领域的中立开发者社区。不止于纯粹的技术交流,我们相信开发者具备更加丰盈的个体价值。行业发展变革、开发者职涯发展、技术创业创新资源,我们将陪跑开发者,共享、共建、共成长。
总阅读653
粉丝0
内容1.1k