返回頂部這個功能用jq實現,好容易實現,一個animate
配合scrollTo
就搞定了javascript
今天咱們來試試vue
封裝一個原生js實現的返回頂部;css
寫起來夠嗆,藉助github
,看了別人的gist
,稍微封裝了下;html
固然不是用scrollTo
直接調位那種,沒有過渡效果怎麼說得過去,仍是搗鼓出來了。vue
實現思路java
requestAnimationFrame
,這貨只支持IE10+,因此必須作兼容window.pageYOffset
,這貨支持IE9+;iconfont
,具體瞅代碼你能學到什麼?git
實現功能github
350
處顯示返回頂部的按鈕和圖標scrollIt(0, 1500, 'easeInOutCubic', callback);
point
,也就是滾動到哪裏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();
}
複製代碼
<template>
<div class="back-to-top" @click="backToTop" v-show="showReturnToTop" @mouseenter="show" @mouseleave="hide">
<i :class="[bttOption.iClass]" :style="{color:bttOption.iColor,'font-size':bttOption.iFontsize}"></i>
<span class="tips" :class="[bttOption.iPos]" :style="{color:bttOption.textColor}" v-show="showTooltips">{{bttOption.text}}</span>
</div>
</template>
<script> import { scrollIt } from './scrollIt'; // 引入動畫過渡的實現 export default { name: 'back-to-top', props: { text: { // 文本提示 type: String, default: '返回頂部' }, textColor: { // 文本顏色 type: String, default: '#f00' }, iPos: { // 文本位置 type: String, default: 'right' }, iClass: { // 圖標形狀 type: String, default: 'fzicon fz-ad-fanhuidingbu1' }, iColor: { // 圖標顏色 type: String, default: '#f00' }, iFontsize: { // 圖標大小 type: String, default: '32px' }, pageY: { // 默認在哪一個視圖顯示返回按鈕 type: Number, default: 400 }, transitionName: { // 過渡動畫名稱 type: String, default: 'linear' } }, data: function () { return { showTooltips: false, showReturnToTop: false } }, computed: { bttOption () { return { text: this.text, textColor: this.textColor, iPos: this.iPos, iClass: this.iClass, iColor: this.iColor, iFontsize: this.iFontsize } } }, methods: { show () { // 顯示隱藏提示文字 return this.showTooltips = true; }, hide () { return this.showTooltips = false; }, currentPageYOffset () { // 判斷滾動區域大於多少的時候顯示返回頂部的按鈕 window.pageYOffset > this.pageY ? this.showReturnToTop = true : this.showReturnToTop = false; }, backToTop () { scrollIt(0, 1500, this.transitionName, this.currentPageYOffset); } }, created () { window.addEventListener('scroll', this.currentPageYOffset); }, beforeDestroy () { window.removeEventListener('scroll', this.currentPageYOffset) } } </script>
<style scoped lang="scss"> .back-to-top { position: fixed; bottom: 5%; right: 100px; z-index: 9999; cursor: pointer; width: auto; i { font-size: 32px; display: inline-block; position: relative; text-align: center; padding: 5px; background-color: rgba(234, 231, 231, 0.52); border-radius: 5px; transition: all 0.3s linear; &:hover { border-radius: 50%; background: #222; color: #fff !important; } } .tips { display: inline-block; position: absolute; word-break: normal; white-space: nowrap; width: auto; font-size: 12px; color: #fff; z-index: -1; } .left { right: 0; top: 50%; margin-right: 50px; transform: translateY(-50%); } .right { left: 0; top: 50%; margin-left: 50px; transform: translateY(-50%); } .bottom { bottom: 0; margin-top: 50px; } .top { top: 0; margin-bottom: 50px; } } </style>
複製代碼
有更好的實現方案和思路能夠往下面留言,謝謝web