freelance developer of javascript, python and more!

At the moment I’m working on a small project that has a futuristic computer theme. To make it a bit more visually exciting for the users, I wanted to have a transition between the steps of the application, so I thought it would be cool to have some kind of computer glitch effect followed by a scan line that comes down the screen to reveal the next page.

ImageGlitcher

With a bit of googling, I found ImageGlitcher by Felix Turner. This takes an image, puts it into an HTML5 canvas, and applies some filters to create the glitched effect. Looking at the source code, you can see that it achieves the effect via the following steps:

Offset random slices of the image

Offset one of the color channels

Apply a matrix filter to lighten the image

Overlay black ‘scan lines’ to give that crt monitor effect

This creates exactly the effect I’m looking for, but it has 2 problems:

Only Images are Supported

In my application, I want to be able to apply the glitch to the actual web page, not just an image… Easy, you might think, just call canvas.drawWindow on the with the current window and you can fill the canvas up with the rendered page. Unfortunately not! It seems that there are a load of security issues with this, so it’s restricted to authorized extensions only. Imagine if a webpage could insert an iframe containing your personal details from Facebook, or your bank, screenshot it, and upload it to a server.

This is where the awesome html2canvas project comes in. It’s a JavaScript library that can render an element into a canvas by inspecting the contents of the DOM. It doesn’t support all css effects, and can’t capture the contents of any iframes on the page, but for my application it works perfectly. Plus, the limited rendering may actually add to the glitched effect I’m creating.

The API is pretty simple, just include the script on the page, and call the html2canvas function with callback (it has to load any images that are within the element so needs to be an asynchronous function.)

html2canvas($("#targetElement"),{
onrendered:function(canvas){// the element has been rendered into the HTMLCanvasElement
$("body").append(canvas);}});

Rendering is Quite Slow

The second problem I came across was that the ImageGlitcher implementation seems to be quite slow! It’s fine for just creating one off images, but I want the effect to work as a transition between pages, so every millisecond of rendering counts. When I tried the ImageGlitcher code on an 840×840 canvas element that I’m going to apply the transition to, it took about 10 seconds to create the glitched image. This is far too long, so I jumped into the Chrome Profiler tab and started looking for the cause.

It turns out that ImageGlitcher uses a library called BitmapData, a port of the Flash BitmapData class to JavaScript. While this makes applying the required effects quite simple, it does a lot of extra work that isn’t required. Take this bit of ImageGlitcher code as an example:

As you can see, it will call context.putImageData, hexToRGB and context.getImageData on each iteration of the loop. By removing the BitmapData class and working directly on the canvas context, we go from a few seconds to add the scan lines to under 10 ms!

Glitching a DOM element

So, the first step to creating a glitched version of a dom element is creating a canvas containing an image of the dom element we want to glitch using html2canvas:

// get the ImageData from the original canvasvar srcData = canvas.getContext('2d').getImageData(0,0, canvas.width, canvas.height).data;

// get hold of the ImageData for the working imagevar targetImageData = tempCtx.getImageData(0,0, canvas.width, canvas.height);

// and get a local reference to the rgba data arrayvar data = targetImageData.data;

// Copy a random color channel from the original image into// the working canvas, offsetting it by a random amount//// ImageData arrays are a single dimension array that contains// 4 values for each pixel (r,g,b,a).// so, by initializing `i` to a random number between 0 and 2,// and incrementing by 4 on each iteration, we can replace only// a single channel in the imagefor(var i = getRandInt(0,3), _len = srcData.length; i < _len; i +=4){
data[i+channelOffset]= srcData[i];}

Now that’s done, tempCanvas contains the glitched images and it’s pretty trivial to write a transition that overlays the glitched canvas and removes it via some effect. Check out the source if you’re interested!

Usage and Examples

It requires the html2canvas library and, if you want to use the transition effect, a fairly recent jQuery.

To create a glitched version of an element, call the glitch function:

glitch(document.getElementById("currentContent"),{
amount:8,
complete:function(canvas){// do something with the glitched canvas}});

// jQuery plugin version
$("#currentContent").glitch({
amount:8,
complete:function(canvas){// do something with the glitched canvas}});

To replace an element with a glitched version of it, use glitch.replace or just call $.fn.glitch with no arguments:

glitch.replace(document.getElementById("currentContent"));

// jQuery version
$("#currentContent").glitch();

If you want to create a transition between two bits of content, jQuery is required to perform the animation:

$("#currentContent").glitch($("<div><p>New Content</p></div>"),{
amount:7,
effect:"slide",
complete:function(){// do something when the animation is complete}});

A few things to be aware of:

As html2canvas has to iterate over the contents of the element when rendering it to the canvas, it stands to reason that the more complex the DOM, the longer the rendering will take. This is especially true of any images that are attached (including background images,) as they have to be re-loaded asynchronously by the browser. If there are any images from another domain, then they have to be loaded via a proxy to avoid tainting the canvas. So, it’s wise to remove any unneeded elements from the dom before applying the effect.

html2canvas scrolls the window to the top when rendering the page (see Issue 57) which is fine for my usage, but may not be ideal for you. There are 2 answers for this: store the scroll position before calling glitch, and set it back in the complete handler, or contribute a fix to the html2canvas project (I’m working on a fix on my fork!)

In the project i’m using this on the effect is triggered via a delegated click event handler (attached to a Backbone.js view,) which seems to create an error in chrome to do with the event listeners that were attached. To get around this, I deferred the call to the glitch function to the next tick.

Hi – this is awesome. I’m not entirely clear on how you replace the glitched content with the original content created before the glitch effect took place. Do you have an example of that?

sjhewitt

Hi Mike, I don’t really understand what you mean, could you try explaining a different way?

http://www.facebook.com/alexandru.ardelean.355 Alexandru Ardelean

Hello,

I would like to thank and congratulate you on the work for this glitch script.

I’ve used on http://ctf365.com [to simulate a transmission-glitch script] and I decided to put it on github.com. It’s still work-in-progress; it’s rather raw, but I think it’s a decent start to using your script.

thanks for interesting image processing ways.
I’m writing text games with javascript, although myself not very proficient with coding.
I’m looking for some really cool glitch text effects for HTML with js and jQuery, which would in some way simulate what Memory of a Broken Dimension does with text console. TV scan lines on the background, some text glitches etc.
Do you do commercial work? I’d like to pay someone to help me spice up my HTML output with what I mentioned.