简单易用的缓动算法
返回顶部按钮执行的函数
var backToTop = function (rate){
var doc = document.body.scrollTop? document.body : document.documentElement;
var scrollTop = doc.scrollTop;
if(!window.requestAnimationFrame){
requestAnimationFrame = function (fn){
setTimeout(fn, 17);
}
}
var step = function (){
scrollTop = scrollTop + ( 0 - scrollTop ) / ( rate || 2 );
if(scrollTop < 1) {
doc.scrollTop = 0;
return
}
doc.scrollTop = scrollTop;
requestAnimationFrame(step);
};
step();
};
进度条函数(使用封装后的缓动算法)
/*
{
A: 初始值,
B: 最终值,
rate: 缓动速率,
callback: 回调函数,用来对每一帧动画的进行监控(对目标元素的属性进行操作),执行动画。
}
*/
Math.easeout = function (A, B, rate, callback){
let args = arguments;
B = B || 0;
rate = rate || 2;
if( A == B || typeof A != 'number' ) {
console.error(args[0] + ' and ' + args[1] + ' must be number');
}
//兼容性处理
if(!window.requestAnimationFrame){
requestAnimationFrame = function (fn){
//1000 / 60 约等于 17,每秒60帧保证动画的顺畅。
setTimeout(fn, 17);
}
}
//每帧动画跑起来之前执行的函数
const step = function (){
A = A + ( B - A ) / rate;
//结束条件, 在A > B的情况下,A小于1时结束;在 A < B的情况下,B - A 小于1时结束。
if(Math.abs(A) < 1 || Math.abs(B - A) < 1) {
callback(B, true);
return;
}
callback(A, false);
requestAnimationFrame(step);
};
step();
};
const _$ = function (query){
return document.querySelector(query);
};
let leftDiv = _$('#moveLeft');
const WIDTH = leftDiv.parentElement.clientWidth;
_$('#width-all').addEventListener('click', function (){
let me = this;
//避免重复触发
me.disabled = true;
Math.easeout(0, WIDTH, 60, function (val, isEnding){
leftDiv.style.width = val + 'px';
leftDiv.textContent = parseInt(val / WIDTH * 100) + '%';
if(isEnding) {
alert('加载完成');
me.disabled = false;
}
});
});
<body>
<a href="http://www.zhangxinxu.com/wordpress/2017/01/share-a-animation-algorithm-js/" class="source">参考:张鑫旭——即插即用缓动js算法</a>
<div class="padding" style="line-height: 1;color: red;padding: 1rem 0;">
点击下面的按钮查看效果
<p>ps: 在PC端下使用,貌似博客园在移动端下不支持button节点的点击事件</p>
</div>
<button class="backToTop" id="default-rate" onclick="backToTop(2);">点击我返回顶部</button>
<button class="backToTop" onclick="backToTop(4);">backToTop(4)</button>
<button class="backToTop" onclick="backToTop(10);">backToTop(10)</button>
<button class="backToTop" onclick="backToTop(20);">backToTop(20)</button>
<button id="width-all" >点我加载缓动进度条</button>
<div id="moveLeft" style="width: 0px;height: 20px;background: lightblue;text-align:right;">0%</div>
<script>
var backToTop = function (rate){
var doc = document.body.scrollTop? document.body : document.documentElement;
var scrollTop = doc.scrollTop;
if(!window.requestAnimationFrame){
requestAnimationFrame = function (fn){
setTimeout(fn, 17);
}
}
var step = function (){
scrollTop = scrollTop + ( 0 - scrollTop ) / ( rate || 2 );
if(scrollTop < 1) {
doc.scrollTop = 0;
return
}
doc.scrollTop = scrollTop;
requestAnimationFrame(step);
};
step();
};
/*
{
A: 初始值,
B: 最终值,
rate: 缓动速率,
callback: 回调函数,用来对每一帧动画的进行监控(对目标元素的属性进行操作),执行动画。
}
*/
Math.easeout = function (A, B, rate, callback){
let args = arguments;
B = B || 0;
rate = rate || 2;
if( A == B || typeof A != 'number' ) {
console.error(args[0] + ' and ' + args[1] + ' must be string');
}
if(!window.requestAnimationFrame){
requestAnimationFrame = function (fn){
setTimeout(fn, 17);
}
}
const step = function (){
A = A + ( B - A ) / rate;
if(Math.abs(A) < 1 || Math.abs(B - A) < 1) {
callback(B, true);
return;
}
callback(A, false);
requestAnimationFrame(step);
};
step();
};
const _$ = function (query){
return document.querySelector(query);
};
let leftDiv = _$('#moveLeft');
const WIDTH = leftDiv.parentElement.clientWidth;
_$('#width-all').addEventListener('click', function (){
var me = this;
me.disabled = true;
Math.easeout(0, WIDTH, 60, function (val, isEnding){
leftDiv.style.width = val + 'px';
leftDiv.textContent = (val / WIDTH * 100).toFixed(1) + '%';
if(isEnding) {
alert('加载完成');
me.disabled = false;
}
});
});
</script>
</body>
行为影响状态,状态影响视图