前天看了《自如客APP裸眼3D效果的實現》的效果,以爲這個交互很棒也很好玩,遂用Flutter實現了一個。git
巧婦難爲無米之炊,因沒有設計稿,因此相較於自如的能夠說很醜。 (●'◡'●)
複製代碼
如《自如客APP裸眼3D效果的實現》 中介紹的,總體構成爲3層:github
底層、中層、上層
複製代碼
在轉動手機時,中層
保持不動,底層
和上層
作相反運動。 咱們先集成插件sensors
:markdown
sensors: ^2.0.3
https://pub.flutter-io.cn/packages/sensors/install
複製代碼
以後經過StreamSubscription
監聽插件的AccelerometerEvent
事件,其攜帶3個值,分別是:x, y, z
。app
這裏介紹一下此處三個值的意思,它們分別表明三個軸的重力感應,以下:async
三個軸得取值範圍是同樣的: [-10 , 10]
,方向朝天爲正,反之爲負。ide
以後,咱們藉助stack
和 position
就能夠實現這個交互效果了。oop
這裏須要注意的是,sensor
傳遞的值是經過event channel
,並且值變動的時間窗口較大,粗暴地在收到event後,刷新頁面效果並很差。佈局
所以,介於傳感器值的範圍,和時間窗口的問題,這裏建議將x
和y
的值作略微擴大,並經過AnimatedPositioned
進行位移動畫。也就是說,用動畫時間合理的填充空窗期
,並銜接先後值的變化。相似以下:post
由於沒有設計圖,具體位置只能摸索,因此值的設置看起來有點瑣碎,見諒。
複製代碼
///值僅做參考,具體要根據設計稿和頁面環境靈活配置
///監聽
_streamSubscription =
accelerometerEvents.listen((AccelerometerEvent event) async {
setState(() {
x = event.x * 2.5;
y = event.y * 1.8;
});
});
///主要佈局
Stack(
alignment: Alignment.center,
children: [
AnimatedPositioned(
top: y - 40,
right: x - 10,
duration: Duration(milliseconds: duration),
child: _bottom()),
Positioned(
child: _middle()),
AnimatedPositioned(
bottom: y - 10 ,
left: x + size.width / 3,
duration: Duration(milliseconds: duration),
child: _top()),
],
)
複製代碼
經過這種方式,H5
應該也能實現不錯的效果。不過在實際應用中,考慮的因素仍是比較多的,如:弱網、機型、兜底方案等等
。至此文章就結束了,謝謝閱讀。優化
Demo代碼書寫隨意,且還有不少值得優化的地方,歡迎評論區討論。
複製代碼
進入路徑: 首頁 —— 實驗室DEMO —— 裸眼3D