Skip to content

Instantly share code, notes, and snippets.

@phuctvt
Last active January 31, 2020 08:39
Show Gist options
  • Save phuctvt/7b9f2c41131f6dd6603bc8eeb5e0e26a to your computer and use it in GitHub Desktop.
Save phuctvt/7b9f2c41131f6dd6603bc8eeb5e0e26a to your computer and use it in GitHub Desktop.
Easing functions demo
class Ball {
constructor(x, y, endX, endY, movingDuration) {
this.x = x;
this.y = y;
this.r = 10;
this.movingDuration = movingDuration; // millisecond
this.beginX = x;
this.beginY = y;
this.endX = endX;
this.endY = endY;
this.moved = false;
}
draw(ctx) {
ctx.save();
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.restore();
ctx.save();
ctx.moveTo(this.beginX, this.beginY + 20);
ctx.lineTo(this.endX, this.endY + 20);
ctx.strokeStyle = 'green';
ctx.stroke();
ctx.beginPath();
ctx.arc(this.beginX, this.beginY + 20, 2, 0, Math.PI * 2);
ctx.arc(this.endX, this.endY + 20, 2, 0, Math.PI * 2);
ctx.fillStyle = 'green';
ctx.fill();
ctx.restore();
}
updatePosition() {
if (this.x >= this.endX) return;
let timestamp = new Date().getTime();
let percentTs = (timestamp - this.beginTs) / (this.endTs - this.beginTs);
let percent = this.easingFunction(percentTs);
this.x = percent * (this.endX - this.beginX) + this.beginX;
this.y = percent * (this.endY - this.beginY) + this.beginY;
}
startMoving(easingFunction) {
this.easingFunction = easingFunction;
this.beginTs = new Date().getTime(); // millisecond
this.endTs = this.movingDuration + this.beginTs;
this.moved = true;
}
startOver(easingFunction) {
this.x = this.beginX;
this.y = this.beginY;
this.startMoving(easingFunction);
}
}
<!DOCTYPE html>
<html>
<head>
<title>Ball</title>
</head>
<body>
<canvas id="canvas" width="700" height="400"></canvas>
<script type="text/javascript" src="tool.js"></script>
<script type="text/javascript" src="ball.js"></script>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
let c, ctx, w, h;
let balls;
function setup() {
c = document.querySelector('#canvas');
ctx = c.getContext('2d');
w = c.width;
h = c.height;
balls = [
new Ball(50, 100, 500, 200, 1500),
new Ball(50, 300, 500, 300, 1500)
];
c.onclick = () => balls.forEach(ball => ball.startOver(EasingFunctions.easeInOutQuint));
}
function draw() {
ctx.fillStyle = 'lightgray';
ctx.fillRect(0, 0, w, h);
for (let ball of balls) {
if (!ball.moved) {
ball.startMoving(EasingFunctions.easeInOutQuint);
}
ball.updatePosition();
ball.draw(ctx);
}
window.requestAnimationFrame(draw);
}
setup();
window.requestAnimationFrame(draw);
// Source: https://gist.github.com/gre/1650294
EasingFunctions = {
// no easing, no acceleration
linear: t => t,
// accelerating from zero velocity
easeInQuad: t => t*t,
// decelerating to zero velocity
easeOutQuad: t => t*(2-t),
// acceleration until halfway, then deceleration
easeInOutQuad: t => t<.5 ? 2*t*t : -1+(4-2*t)*t,
// accelerating from zero velocity
easeInCubic: t => t*t*t,
// decelerating to zero velocity
easeOutCubic: t => (--t)*t*t+1,
// acceleration until halfway, then deceleration
easeInOutCubic: t => t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1,
// accelerating from zero velocity
easeInQuart: t => t*t*t*t,
// decelerating to zero velocity
easeOutQuart: t => 1-(--t)*t*t*t,
// acceleration until halfway, then deceleration
easeInOutQuart: t => t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t,
// accelerating from zero velocity
easeInQuint: t => t*t*t*t*t,
// decelerating to zero velocity
easeOutQuint: t => 1+(--t)*t*t*t*t,
// acceleration until halfway, then deceleration
easeInOutQuint: t => t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment