欢迎来到258分享网,纯净的网络源码分享基地!

258资源分享网

全部作品
全部作品
网站源码
微信源码
素材特效
源码插件
视频教程
建站学院
热门搜索: 织梦  农业种植  农业  安全设置  官方
258资源分享 > 建站学院 > 微信开发 > 从微信小程序重力感应API到requestAnimationFrame探索实现

推荐下载

HTML5响应式自适应网咯设计

2020-05-12   浏览:740

高端HTML5响应式企业通用网

2020-05-06   浏览:521

html5响应式外贸网站英文版

2020-05-08   浏览:510

HTML5自适应律师工作室类网

2020-04-04   浏览:505

HTML5影视传媒文化公司类网

2020-05-12   浏览:502

从微信小程序重力感应API到requestAnimationFrame探索实现

发布时间:2021-01-07  

最近做微信小程序的开发时,想做一个靠感知手机方向,使页面上节点跟随移动的动画(即重力感应视差效果)功能。结果发现微信小程序有一些坑:微信小程序不支持html5的DeviceOrientationEv ...

 

 

 

最近做微信小程序的开发时,想做一个靠感知手机方向,使页面上节点跟随移动的动画(即重力感应视差效果)功能。结果发现微信小程序有一些坑:

微信小程序不支持html5的DeviceOrientationEvent重力感应API,而是自己实现的wx.onAccelerometerChange

这个API回调实现,频率为5次/s

在这个背景下,要实现平滑的重力感应的视差体验就那么优雅了,因为人对至少60帧每秒的动画才会感觉流畅。最终实现的效果会有卡顿现象。

实现期间,想起好像有requestAnimationFrame这个跟动画相关的API,其功能表现与setTimeout类似,即隔一段时间调用一个回调函数。对于这个API,之前了解不深,这次拿起来产生了一个疑问:既生setTimeout,何生requestAnimationFrame?带着疑问,开始调研。

与setTimeout的不同

在MDN上,关于requestAnimationFrame的定义是:

window.requestAnimationFrame()这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数,以满足开发者操作动画的需求。这个方法接受一个函数为参,该函数会在重绘前调用。

在这里,我产生一个疑问,所谓的“在页面重绘之前”,指的是,这个指定函数(以下简称cb)会在底层机制的运行下,在页面重绘之前调用;还是人为地设置一个间隔时间,去调用cb,导致重绘?

之前大概了解过页面的重排和重绘。动画能用重排和重绘来实现(这里指的是能用这两种途径来达到动画目的,而不是两者都适合用来实现动画),而定义里只提到重绘,没提到重排的原因,虽然我没去细究,但很重要一点肯定是因为,重绘性能远高于重排。所以动画不要通过left、margin等来实现,应该通过translate属性来实现。

既然说到translate,稍微延伸一下,动画如果要用translate,最好用tranlate3d。因为较于tranlate,tranlate3d能得到更完整的GPU加速的支持,使得性能更优。

言归正传,继续解决刚刚的疑问。往下阅读,发现这么一段解释:

如果你想做逐帧动画的时候,你应该用这个方法。这就要求你的动画函数执行会先于浏览器重绘动作。通常来说,被调用的频率是每秒60次,但是一般会遵循W3C标准规定的频率。如果是后台标签页面,重绘频率则会大大降低。

从这段话可以看出,在用了这个方法后,浏览器会根据自己的重绘频率,而每次重绘前会调用cb。用以下代码验证:

var laststart function test () { laststart && console.log(Date.now() - laststart) laststart = Date.now() requestAnimationFrame(test) } requestAnimationFrame(test)

得到结果,我所在的浏览器环境(mac + chrome[55.0.2883.95])的重绘频率约为60次每秒:

对此我产生几个疑问:

问题1:如果我干扰了重绘的频率,是否还会是一个几乎保持在每秒60帧的频率呢(只针对提高频率进行探究)?

问题2:是否调用了requestAnimationFrame就会产生一定频率的重绘?

问题3:如果不调用requestAnimationFrame,在无其他代码去重绘页面的话,页面就不会重绘吗?

为了验证问题1,我加了这么一段代码:

var x = 1 var style = document.querySelectorAll('.test')[0].style function interference () { x *= -1 style.transform = `translate3d(${x * 20}px, 0 ,0)` setTimeout(interference, 5) } interference()

得到的结果与上一个结果一致。

由此得出结论:cb的调用频率在人为干扰重绘频率的情况下,依旧我行我素。

等等,人为干扰重绘频率成功了吗?会不会虽然interference的调用频率为5ms一次,但浏览器的重绘频率依旧是约等于60次每秒,即interference虽然试图去触发浏览器5ms重绘一次,但浏览器只会阻塞住,等下一次浏览器默认频率重绘时再一起重绘?

为了探究这个问题,我将interference的setTimeout时间分别设置为16ms(简称为i16)、10ms(简称为i10)、8ms(简称为i8)、5ms(简称为i5),如果浏览器重绘频率无法人为干扰,因以下两个原因:

interference的函数对$('.test')的改变为水平位移正负20px交替出现

浏览器默认重绘频率接近16ms一次