Instagram Style Video Preload Static Effect
📣 Sponsor
Instagram reels, a relatively new feature to instagram, have this interesting noise effect before the video loads. Recently, my airpods have had some issue connecting to instagram and I often get this static effect before the app catches up and connects to them.
This noise effect is pretty cool, and it's nostalgic of old TV sets. It got me thinking about how we could do this for videos on the web or in Javascript applications. Let's take a look at how to do that, with some perlin noise.
Perlin Noise
First off, we need a good perlin noise function. Perlin noise is a way of generating random noise which we can use to create the static effect we're after.
I'm going to be using the code from this repository. This code gives us a function called noise
which we can use to generate our noise context. Let's use this to generate some noise:
let video = document.getElementById('video');
let canvas = document.getElementById('noise-canvas');
canvas.width = 250;
canvas.height = 250;
let ctx = canvas.getContext('2d');
function generateNoise() {
var image = ctx.createImageData(canvas.width, canvas.height);
var data = image.data;
for (var x = 0; x < canvas.width; x++) {
noise.seed(Math.random());
for (var y = 0; y < canvas.height; y++) {
var value = Math.abs(noise.perlin2(x / 2, y / 2));
value *= 500;
var cell = (x + y * canvas.width) * 4;
data[cell] = data[cell + 1] = data[cell + 2] = value;
data[cell + 3] = 255; // alpha.
}
}
ctx.putImageData(image, 0, 0);
}
function animation(timestamp) {
generateNoise();
window.requestAnimationFrame(animation);
}
window.requestAnimationFrame(animation);
<div id="video-container">
<video id="video" muted>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>
<div id="canvas-overlay"></div>
<canvas id="noise-canvas"></canvas>
</div>
Essentially this code goes pixel by pixel and generates an image which has random colors for each pixel. For this demo, the canvas width and height are set to 250px in this code on the 4th and 5th line. You might have to change this if your video is much bigger.
I've also created a canvas overlay div which has a slight gradient on it. The styles for this look like this:
canvas, #canvas-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: black;
height: 100%;
z-index: 9999;
}
#canvas-overlay {
z-index: 9999999;
background: linear-gradient(-135deg, #343fa99e, #2ed29d1c);
}
video {
height: 100%;
width: auto;
position: absolute;
}
#video-container {
position: relative;
width: 250px;
box-shadow: 0 5px 25px rgb(0 0 0 / 7%), 0 2px 5px rgb(0 0 0 / 15%), 0 15px 30px rgb(0 0 0 / 10%), 0 0 0px 5px #00000000, 0 0 3px 1px #00000000;
border-radius: 15px;
overflow: hidden;
height: 250px;
}
Video autoplay
The next step takes advantage of the Javascript Video API. When the video is loaded, we will hide the static canvas and the canvas overlay:
video.addEventListener('loadeddata', function() {
canvas.style.display = 'none';
document.getElementById('canvas-overlay').style.display = 'none';
video.play();
}, false);
And that's it
Full code below:
More Tips and Tricks for Javascript
- Javascript on Click Confetti Effect
- Resolving HTTP Cannot set headers after they are sent to the client in Node.JS
- Javascript Objects Cheatsheet
- Javascript Array Reduce Method
- Javascript Immediately invoked function expressions (IIFE)
- Javascript: Check if an Array is a Subset of Another Array
- Using an Array as Function Parameter in JavaScript
- Deleting an Item in an Array at a Specific Index
- Setting the Default Node.JS version with nvm
- What are NodeLists, and how do they work?