I have an animation which is created using canvas. The animation is almost complete and it shows an explosion. I was wondering if there was a way to create a shaking effect which would seem as though the contents of the canvas were shaking for a few seconds when the explosion takes place.
Any help appreciated.
An easy way to shake the screen is to translate the whole context in a random direction before each draw.
You have to save/restore the context to keep it in a 'clean' status.
var ctx=cv.getContext('2d');
function preShake() {
ctx.save();
var dx = Math.random()*10;
var dy = Math.random()*10;
ctx.translate(dx, dy);
}
function postShake() {
ctx.restore();
}
function drawThings() {
ctx.fillStyle = '#F00';
ctx.fillRect(10, 10, 50, 30);
ctx.fillStyle = '#0F0';
ctx.fillRect(140, 30, 90, 110);
ctx.fillStyle = '#00F';
ctx.fillRect(80, 70, 60, 40);
}
drawThings();
function animate() {
// keep animation alive
requestAnimationFrame(animate);
// erase
ctx.clearRect(0,0,cv.width, cv.height);
//
preShake();
//
drawThings();
//
postShake();
}
animate();
<canvas id='cv'></canvas>
Notice you might prefer to use some sin function and some easing to have a smoother effect :
var ctx=cv.getContext('2d');
var shakeDuration = 800;
var shakeStartTime = -1;
function preShake() {
if (shakeStartTime ==-1) return;
var dt = Date.now()-shakeStartTime;
if (dt>shakeDuration) {
shakeStartTime = -1;
return;
}
var easingCoef = dt / shakeDuration;
var easing = Math.pow(easingCoef-1,3) +1;
ctx.save();
var dx = easing*(Math.cos(dt*0.1 ) + Math.cos( dt *0.3115))*15;
var dy = easing*(Math.sin(dt*0.05) + Math.sin(dt*0.057113))*15;
ctx.translate(dx, dy);
}
function postShake() {
if (shakeStartTime ==-1) return;
ctx.restore();
}
function startShake() {
shakeStartTime=Date.now();
}
function drawThings() {
ctx.fillStyle = '#F00';
ctx.fillRect(10, 10, 50, 30);
ctx.fillStyle = '#0F0';
ctx.fillRect(140, 30, 90, 110);
ctx.fillStyle = '#00F';
ctx.fillRect(80, 70, 60, 40);
}
drawThings();
function animate() {
// keep animation alive
requestAnimationFrame(animate);
// erase
ctx.clearRect(0,0,cv.width, cv.height);
//
preShake();
//
drawThings();
//
postShake();
}
startShake();
setInterval(startShake,2500);
animate();
<canvas id='cv'></canvas>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With