LOG

Robert Penner’s Easingの例

イージングに関してはここに言語別でのリンクが貼られてる。
ビジュアルで確認したい場合はここ
作者の資料はここ

// ===============================
// HTML
// ===============================

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title></title>
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<style>
html,body{
position : relative;
width : 100%;
height : 100%;
}
*{
margin : 0;
padding : 0;
}
#area{
width : 500px;
height : 500px;
background : #AAA;
position : absolute;
top : 50%;
left : 50%;
/*top : 0;*/
/*left : 0;*/
margin : -250px 0 0 -250px;
}
#ball{
width : 10px;
height : 10px;
border-radius : 10px;
position : absolute;
background : #000;
top : 0;
left : 0;
}
</style>
</head>
<body>
<div id="area"><p id="ball"></p></div>
<script src="dist.js"></script>
</body>
</html>


// ===============================
// JavaScript : ES2015
// ===============================

class Timer{
constructor(){
this.startTime = undefined;
}
start(){
this.startTime = new Date().getTime();
}
now(){
return new Date().getTime() - this.startTime;
}
}

// t : time : 経過時間
// b : begin : 初期値
// c : change : 変化量
// d : duration : 完了までの時間

class Ease{
constructor(){}
static linearTween(t,b,c,d){
return c * t / d + b;
}
static easeInOutExpo(t,b,c,d){
t /= d/2;
if (t < 1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b;
t--;
return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b;
}
static easeOutBack(t,b,c,d,s=1.70158){
// 1.70158については
// http://void.heteml.jp/blog/archives/2014/05/easing_magicnumber.html
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
}
static easeInOutExpo(t,b,c,d){
if (t==0) return b;
if (t==d) return b+c;
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
}
}

const FPS = 60;
let $ball = $('#ball');
let timer = new Timer();
let begin = 0;
let startPos = $('#ball').position();
let endPos = {
top : 500 - 10, // -10はボールの大きさ
left : 500 - 10
};
let duration = 2000;
let animation = undefined;
let timeOffset = false;
let render = ()=>{
let time = new Date().getTime() - timer.startTime;
// -------------------------------------------------------------------------
// スタート時間から実際のアニメーションまでに差が出来てしまうので埋める
if(timeOffset == false) timeOffset = time;
time -= timeOffset;
// -------------------------------------------------------------------------
let offset = {
top : Ease.easeOutBack(
time,
startPos.top,
endPos.top - startPos.top,
duration
),
left : Ease.easeOutBack(
time,
startPos.left,
endPos.left - startPos.left,
duration
)
};
let pos = {
top : Ease.linearTween(
time,
startPos.top,
endPos.top - startPos.top,
duration
),
left : Ease.linearTween(
time,
startPos.left,
endPos.left - startPos.left,
duration
)
};
pos.top += (offset.top - pos.top);
pos.left += (offset.left - pos.left);
$ball.css(pos);
// -------------------------------------------------------------------------
// アニメーション時間を超えたら、位置のズレを直しアニメーションを終了させる
if(time > duration){
$ball.css(endPos);
clearInterval(animation);
}
// -------------------------------------------------------------------------
}

timer.start();

setTimeout(function(){
animation = setInterval(render,1000 / FPS);
},100);

結果