为scrollTo添加平滑滚动降级方案
Element.scrollTo 是一个dom元素上的方法,可以将元素滚动到指定的坐标位置,使用方法如下:
element.scrollTo(x-coord, y-coord)
element.scrollTo(options)
参数说明:
x-coord
是期望滚动到位置水平轴上距元素左上角的像素。y-coord
是期望滚动到位置竖直轴上距元素左上角的像素。options
是一个ScrollToOptions对象。
1、原生API实现方式
我们可以使用 options 参数去让滚动平滑,代码可以如下实现:
el.scrollTo({
left: 100,
top: 0,
behavior: 'smooth'
})
behavior属性在有些浏览器上不支持,不限于有些app修改过的webview等,我们就需要一个降级方案,可以使用浏览器的新的API实现。
2、requestAnimationFrame
2.1、实现方式
如果是静态页面的话,js的动画好像要稍微流畅一点;并且可以控制滚动的速度;
下面的实现仅仅是在x轴上实现的,如果需要在y轴实现,只需要将滚动参数修改一下;
实例:x轴实现的实例如顶部的tab定位等,需求是顶部的tab可以左右滑动,点击tab后底部的卡片会滑动到对应的位置,滑动底部的卡片,顶部的tab也会激活并居中,这就需要实现顶部的平滑滚动;
requestAnimationFrame 是一个新兴的API,专门为执行动画而生,这个方法每秒会执行60次,其实这个60并不是固定值,和刷新率有关系;
/**
* 使用动画滚动导航部分
* @param el {Element} 需要滚动的元素
* @param start {Number} 滚动开始的位置
* @param end {Number} 滚动结束的位置
* @param step {Number} 每一步滚动的长度
*/
export const scrollAnimation = (el, start, end, step) => {
// 向右滑动的逻辑
if (start < end) {
start = start + step;
// 要是剩下的不够一步就直接撑满,防止页面出现滚动偏移错误
if (start > end) {
start = end;
}
}
// 向左滑动的逻辑
if (start > end) {
start = start - step;
if (start < end) {
start = end;
}
}
el.scrollTo(start, 0);
// 要是开始和结束是一样的就不会安排下一次的滚动了
// 在高刷新的屏幕上会有运行的比较块
if (start !== end) {
requestAnimationFrame(() => {
scrollAnimation(el, start, end, step);
})
}
};
2.2、使用说明
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘(浏览器重绘通常是60次每秒,回调函数执行次数通常与浏览器屏幕刷新次数相匹配)之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行;
优点:
- 为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame() 运行在后台标签页或者隐藏的<iframe> 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命。
- 可以用个调用requestAnimationFrame返回的一个数字取消执行:cancelAnimationFrame(num);
在高刷新屏幕上运行更快的问题解决(可以通过传进来的参数处理)
3、参考文档