I wish to make the linear motion of a dot sinusoidal so that is slows to a stop at the edges and changes direction and speeds up on the middle. Here is my attempt.
let q = 51;
let x = 100;
let chang = 4;
let radiu = 20;
function motion(){
requestAnimationFrame(motion);
ctx3.beginPath();
ctx3.fillStyle = "white";
ctx3.fillRect(0,0,canvas3.width,canvas3.height);
ctx3.fillStyle = "blue";
ctx3.arc(x * Math.sin(q), 100, radiu, 0, 2 * Math.PI);
ctx3.fill();
ctx3.closePath();
if(x + radiu > 200 || x - radiu < 50 ){
chang=-chang;
}
x += chang;
q=+1.0;
//q+=0.1;
}
You might need a custom easing function like:
f(t) = sin(t - PI / 2) * 0.5 + 0.5
that accepts a constant time t
and returns the sine in decimal values from 0.0 to 1.0.
The PI / 2
is used to start at -1.0 (instead of center 0
), and * 0.5 + 0.5
is used to convert the range -1.0 .. 1.0
to 0.0 .. 1.0
(exclusive).
To retrieve the new x
position: multiply the resulting easeSin value by the xEnd position you want to travel to, for the back and forth motion. (Account also for the radius to not pass the edges).
For the t
time, instead of using a separate variable you could make use of the requestAnimationFrame's first argument timeStamp:
const easeSin = (t) => Math.sin(t - Math.PI / 2) * 0.5 + 0.5;
const ctx = document.querySelector("canvas").getContext("2d");
// Circle properties:
const rad = 20;
let x = 0;
let y = 100;
const motion = (time) => {
const ease = easeSin(time * 0.001); // retrieve the sine (0.0, 1.0)
x = rad + ease * (300 - rad * 2);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.arc(x, y, rad, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
requestAnimationFrame(motion);
};
motion();
canvas {
border: 2px solid #000;
}
<canvas></canvas>