一、业务背景
在做微信小程序的项目时,有一个需求是当用户左右旋转手机屏幕时,页面上特定的元素要随着用户的旋转动作左右移动。当将手机屏幕向左旋转时,人物向左移动;手机屏幕向右旋转时,人物向右移动。
二、用到的微信API
这里主用到了微信小程序的加速计:
- 开始监听加速度数据,wx.startAccelerometer(Object object)
- 监听加速度数据事件,wx.onAccelerometerChange(function callback)
官方文档链接:https://developers.weixin.qq.com/miniprogram/dev/api/device/accelerometer/wx.startAccelerometer.html
先来写个demo,看下 wx.onAccelerometerChange() 回调函数里参数的打印:
wx.startAccelerometer({
interval: 'normal',
success: () => {
wx.onAccelerometerChange((res) => {
console.log('res :>> ', res);
})
}
})
这个API效果在微信开发者工具里模拟不了,只能在手机上看。微信开发者工具点击预览,在手机的控制台上我们可以看到,将手机屏幕向左旋转至垂直于水平面,打印出来的 x 值无限接近于 -1。将手机屏幕向右旋转至垂直于水平面,打印出来的 x 值无限接近于 1。
有了这个API的帮助,我们就可以愉快地开始写效果了。
三、效果实现
思路:如果元素向左向右最大移动的距离是20,而且既然我能拿到手机旋转的 res.x 值,那么当手机旋转的时候,将元素向左或向右移动 res.x *20 距离,不就可以了。
既然是移动,首先想到的就是用 transform 来实现这个效果,在手机上预览时,发现人物在移动的过程中会一卡一卡的,不是很流畅,就像下面这样。
思考了好久后,想到既然是要做动画效果,那么能想到的有以下三种方式:
- animation
- transition
- requestAnimationFrame
transform 不行,那就换 transition。两种实现方式在下面也都写出来了。
3.1 transform
当手机屏幕旋转时,设置元素的 transform:translateX(res.x*20)
页面结构代码:
<view class="wrap">
<image src="/assets/bg.png" />
<image src="/assets/img.png" style="transform:translateX({{left}}%);" />
</view>
css 代码:
.wrap {
width: 100%;
height: 422rpx;
position: relative;
}
image {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
js 代码:
Page({
data: {
left: ""
},
onShow() {
wx.startAccelerometer({
interval: 'normal',
success: () => {
wx.onAccelerometerChange((res) => {
this.setData({
left: res.x*20
})
})
}
}),
onHide: function () {
// 停止监听加速计数据
wx.offAccelerometerChange()
wx.stopAccelerometer()
}
})
3.2 transition
用 transition 来实现位移的效果,当手机屏幕旋转时,改变元素的 left 值,还可以指定转速曲线和时间。具体的效果大家可以试一下。
css 和 js 代码同上,只需要将上面的 html 改成下面这样,就可以实现完美的移动了。
<view class="wrap">
<image src="/assets/bg.png" />
<image src="/assets/img.png" style="left:{{left}}%;transition:left .3s;" />
</view>
在同一情况下旋转手机屏幕,两种实现方式的效果对比,可以看出使用 transition 元素移动的效果更流畅一些。
后来我想了下, 好像 transform 结合 animation 一起使用,也可以达到这个效果。