前言
返回顶部这个功能用jq实现,好容易实现,一个animate
配合scrollTo
就搞定了
今天我们来试试vue
封装一个原生js实现的返回顶部;
github
,看了别人的gist
,稍微封装了下; 当然不是用scrollTo
直接调位那种,没有过渡效果怎么说得过去!!还是捣鼓出来了.
废话不多说,看效果图...
效果图
实现思路
- 过渡用的是
requestAnimationFrame
,这货只支持IE10+,所以必须做兼容 - 滚动视图是
window.pageYOffset
,这货支持IE9+; - 为了让可控性更强,图标采用
iconfont
,具体瞅代码
你能学到什么?
- 学到一些页面计算相关的东东
- 动画API的一些知识
- Vue封装组件相关知识和生命周期和事件监听销毁相关知识的运用
实现功能
- 视图默认在
350
处显示返回顶部的按钮和图标 - 提示文字和颜色,在图标上下左右的自定义,字段都限制了格式和默认值
- 图标颜色和形状,大小的自定义,字段都限制了格式和默认值
- 过渡动效的自定义,用法:
scrollIt(0, 1500, 'easeInOutCubic', callback);
- 返回到视图的
point
,也就是滚动到哪里 - 过渡时间(ms级别)
- 一堆过渡效果,字符串格式,其实就是滚动的计算函数..
- 当然少不了默认参数了,除了
callback
- 返回到视图的
- 兼容性是
IE9+
,特意开了虚拟机去尝试
代码
scrollIt.js
--过渡滚动实现
export function scrollIt( destination = 0, duration = 200, easing = "linear", callback) { // define timing functions -- 过渡动效 let easings = { // no easing, no acceleration linear(t) { return t; }, // accelerating from zero velocity easeInQuad(t) { return t * t; }, // decelerating to zero velocity easeOutQuad(t) { return t * (2 - t); }, // acceleration until halfway, then deceleration easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; }, // accelerating from zero velocity easeInCubic(t) { return t * t * t; }, // decelerating to zero velocity easeOutCubic(t) { return --t * t * t + 1; }, // acceleration until halfway, then deceleration easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; }, // accelerating from zero velocity easeInQuart(t) { return t * t * t * t; }, // decelerating to zero velocity easeOutQuart(t) { return 1 - --t * t * t * t; }, // acceleration until halfway, then deceleration easeInOutQuart(t) { return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t; }, // accelerating from zero velocity easeInQuint(t) { return t * t * t * t * t; }, // decelerating to zero velocity easeOutQuint(t) { return 1 + --t * t * t * t * t; }, // acceleration until halfway, then deceleration easeInOutQuint(t) { return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t; } }; // requestAnimationFrame()的兼容性封装:先判断是否原生支持各种带前缀的 //不行的话就采用延时的方案 (function() { var lastTime = 0; var vendors = ["ms", "moz", "webkit", "o"]; for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"]; window.cancelAnimationFrame = window[vendors[x] + "CancelAnimationFrame"] || window[vendors[x] + "CancelRequestAnimationFrame"]; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; })(); function checkElement() { // chrome,safari及一些浏览器对于documentElemnt的计算标准化,reset的作用 document.documentElement.scrollTop += 1; let elm = document.documentElement.scrollTop !== 0 ? document.documentElement : document.body; document.documentElement.scrollTop -= 1; return elm; } let element = checkElement(); let start = element.scrollTop; // 当前滚动距离 let startTime = Date.now(); // 当前时间 function scroll() { // 滚动的实现 let now = Date.now(); let time = Math.min(1, (now - startTime) / duration); let timeFunction = easings[easing](time); element.scrollTop = timeFunction * (destination - start) + start; if (element.scrollTop === destination) { callback; // 此次执行回调函数 return; } window.requestAnimationFrame(scroll); } scroll();}复制代码
- backToTop.vue
{ {bttOption.text}}复制代码
总结
从心血来潮到折腾出来,为了兼顾兼容性和拓展性,好像几个小时了.
不过实现了.你再搬到其他语言,类似ng4
,也就是十来分钟的事情,思路会了,实现更多的是写法而已,至于性能优化,可以一边写一边考虑,也可以实现后有空再优化.有更好的实现方案和思路可以往下面留言,谢谢