Glitching out a <canvas> by converting it to JPEG and trashing some random bytes.
See also: Video glitching
Glitching out a <canvas> by converting it to JPEG and trashing some random bytes.
See also: Video glitching
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <body> | |
| <canvas width="960" height="500"></canvas> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script> | |
| <script src="https://d3js.org/topojson.v2.min.js"></script> | |
| <script> | |
| var canvas = document.querySelector("canvas"), | |
| context = canvas.getContext("2d"), | |
| delay = d3.randomExponential(1 / 900), | |
| duration = d3.randomExponential(1 / 175), | |
| glitched = false, | |
| width = 960, | |
| height = 500; | |
| var projection = d3.geoOrthographic() | |
| .scale(195) | |
| .translate([width / 2, height / 2]) | |
| .precision(.1); | |
| var path = d3.geoPath() | |
| .projection(projection) | |
| .context(context); | |
| d3.json("/mbostock/raw/4090846/world-110m.json",function(err,world){ | |
| var land = topojson.feature(world,world.objects.land), | |
| mesh = topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }); | |
| d3.timer(function(t){ | |
| if (glitched) return true; | |
| projection.rotate([360 * (t % 10000 / 10000)]); | |
| context.lineWidth = 1; | |
| context.fillStyle = "#fff"; | |
| context.fillRect(0, 0, width, height); | |
| context.strokeStyle = "#222"; | |
| context.beginPath(); | |
| path({type: "Sphere"}); | |
| context.stroke(); | |
| context.fillStyle = "#222"; | |
| context.beginPath(); | |
| path(land); | |
| context.fill(); | |
| context.strokeStyle = "#fff"; | |
| context.beginPath(); | |
| path(mesh); | |
| context.stroke(); | |
| }); | |
| d3.timeout(glitch, delay()); | |
| }); | |
| function glitch() { | |
| var bytes = toByteArray(canvas.toDataURL("image/jpeg").substring(23)), | |
| density = glitchDensity(), | |
| glitchedBytes = fromByteArray(glitchBytes(bytes, density)), | |
| img = new Image(); | |
| img.onload = function(){ | |
| context.drawImage(img, 0, 0); | |
| glitched = true; | |
| d3.timeout(function(){ | |
| glitched = false; | |
| d3.timeout(glitch, Math.min(3000, delay())); | |
| }, duration()); | |
| }; | |
| img.src = "data:image/jpeg;base64," + glitchedBytes; | |
| } | |
| function glitchDensity() { | |
| return [2, 3, 5, 10, 25, 100][~~(Math.random() * 6)]; | |
| } | |
| function glitchBytes( byteArray, density ) { | |
| var generator = d3.randomExponential(density / byteArray.length), | |
| i = 611 + ~~generator(), | |
| max = byteArray.length - 4, | |
| val = ~~(Math.random() * 256); | |
| while (i < max) { | |
| byteArray[i] = val; | |
| i += ~~generator(); | |
| } | |
| return byteArray; | |
| } | |
| function toByteArray(str) { | |
| var byteString = atob(str), | |
| len = byteString.length, | |
| byteArray = new Uint8Array(len); | |
| for (var i = 0; i < len; i++) { | |
| byteArray[i] = byteString.charCodeAt(i); | |
| } | |
| return byteArray; | |
| } | |
| function fromByteArray(arr) { | |
| return btoa(String.fromCharCode.apply(null, arr)); | |
| } | |
| </script> |