Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active July 6, 2017 14:15
Show Gist options
  • Save veltman/82d40e866ed9612bf30540480860e6fc to your computer and use it in GitHub Desktop.
Save veltman/82d40e866ed9612bf30540480860e6fc to your computer and use it in GitHub Desktop.
Glitchy globe

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment