写在最前面
最近在复习原生JS,结合 setInterval 和 贝塞尔曲线 实现元素的平滑过渡性效果。
先做了一个基础demo,后期再完善。
贝塞尔曲线 oy.easing.js
'use strict';
(function() {
var OY = window.OY = {};
var cubicBezier = function(p1x, p1y, p2x, p2y) {
var cX = 3 * p1x,
bX = 3 * (p2x - p1x) - cX,
aX = 1 - cX - bX,
cY = 3 * p1y,
bY = 3 * (p2y - p1y) - cY,
aY = 1 - cY - bY;
var bezierX = function(t) {
return t * (cX + t * (bX + t * aX));
};
var bezierXDerivative = function(t) {
return cX + t * (2 * bX + 3 * aX * t);
};
var newtonRaphson = function(x) {
var prev,
// Initial estimation is linear
t = x;
do {
prev = t;
t = t - (bezierX(t) - x) / bezierXDerivative(t);
} while (Math.abs(t - prev) > 1e-4);
return t;
};
return function(x) {
var t = newtonRaphson(x);
return t * (cY + t * (bY + t * aY));
};
};
// 可以根据自己的需求再添加
OY.Easing = {
ease: cubicBezier(0.25, 0.1, 0.25, 1),
easeIn: cubicBezier(0.42, 0, 1, 1),
easeOut: cubicBezier(0, 0, 0.58, 1),
easeInOut: cubicBezier(0.42, 0, 0.58, 1)
};
})();
基本使用
<img class="easing" src="./images/pikachu.jpeg">
<script src="js/oy.easing.js"></script>
<script>
'use strict';
let x = 0;
let easing = document.querySelector('.easing');
let id = setInterval(function() {
if (x >= 1) {
clearInterval(id);
return;
}
easing.style.top = 200 * OY.Easing.easeInOut(x).toFixed(2) + 'px';
x += 0.01;
}, 10);
</script>
生产使用
<img class="easing" src="./images/pikachu.jpeg">
<script src="js/oy.easing.js"></script>
<script>
'use strict';
function animate(el, render, duration, easing, callback) {
let start = Date.now();
(function loop() {
let p = (Date.now() - start) / duration;
if (p > 1) {
render(1, el);
callback && callback();
} else {
requestAnimationFrame(loop);
render(easing(p), el);
}
})();
};
let easing = document.querySelector('.easing');
animate(
easing,
moveGo,
1000,
OY.Easing.easeInOut
);
function moveGo(p, el) {
el.style.top = 200 * p + 'px';
}
</script>