const vid = document.querySelector('video');
const canvas = document.getElementById('soblurme');
const ctx = canvas.getContext('2d');
if( ctx.filter !== "none" ) {
// in case 2DContext.filter is not supported (Safari), some libraries can do the blur for us
// I'll let the readers choose the one they prefer and implement it
console.warn( "we should use a falbback like StackBlur.js" );
}
const spread = 10;
ctx.filter = 'blur(' + spread + 'px)';
const border_width = 1; // because we add a css border around the canvas element
let playing = false;
vid.onplaying = startDrawing;
vid.onpause = stopDrawing;
function startDrawing() {
playing = true;
loop();
}
function stopDrawing() {
playing = false;
}
function loop() {
if( mouse.dirty ) {
canvas.style.left = mouse.x + 'px';
canvas.style.top = mouse.y + 'px';
mouse.dirty = false;
}
draw();
if( playing ) {
requestAnimationFrame(loop);
}
}
function draw() {
const vid_rect = vid.getBoundingClientRect();
const can_rect = canvas.getBoundingClientRect();
const s_x = (can_rect.left - vid_rect.left) + border_width;
const s_y = (can_rect.top - vid_rect.top) + border_width;
ctx.clearRect(0, 0, canvas.width, canvas.height);
// if we are lazy, we can draw the whole image
// but the blur effect is quite heavy to calculate
// ctx.drawImage(vid, -s_x, -s_y, vid_rect.width, vid_rect.height);
// so for better performances we may prefer to calculate the smallest area to draw
// because blur spreads we need to draw outside a little bit anyway
const offset = spread * 2;
const output_w = canvas.width + (offset * 2);
const output_h = canvas.height + (offset * 2);
const ratio_x = vid_rect.width / vid.videoWidth;
const ratio_y = vid_rect.height / vid.videoHeight;
ctx.drawImage(
vid,
(s_x - offset) / ratio_x, (s_y - offset) / ratio_y, output_w / ratio_x, output_h / ratio_y,
-offset, -offset, output_w, output_h
);
}
// move with mouse
const mouse = {
x: 0,
y: 0,
dirty: false
};
document.querySelector('.container')
.addEventListener( 'mousemove', ( evt ) => {
mouse.x = evt.offsetX - canvas.width / 2;
mouse.y = evt.offsetY - canvas.height / 2;
if( !mouse.dirty && !playing ) {
requestAnimationFrame( loop );
}
mouse.dirty = true;
});
.container { position: relative; }
#soblurme {
position: absolute;
border: 1px solid white;
pointer-events: none;
left: 70px;
top: 20px;
}
video {
width: 100%;
}
<div class="container">
<video autoplay muted controls>
<source src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm">
<source src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4">
</video>
<canvas id="soblurme" width="50" height="50"></canvas>
</div>