Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active May 5, 2017 00:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veltman/2f7cea54978d3c73e03988134adc72a3 to your computer and use it in GitHub Desktop.
Save veltman/2f7cea54978d3c73e03988134adc72a3 to your computer and use it in GitHub Desktop.
SVG pixelation
height: 600
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
svg, canvas {
position: absolute;
}
</style>
</head>
<body>
<svg width="960" height="600"></svg>
<canvas width="960" height="600"></svg>
<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 svg = d3.select("svg"),
path = d3.geoPath(),
canvas = document.querySelector("canvas"),
offscreen = document.createElement("canvas"),
context = canvas.getContext("2d"),
offscreenContext = offscreen.getContext("2d"),
img = new Image(),
width = offscreen.width = canvas.width,
height = offscreen.height = canvas.height,
colors = ["#6af09c","#f362ba","#f2ef5f","#6dd4e8","#e39460"],
grain = 64,
up = true;
context.msImageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
d3.json("https://d3js.org/us-10m.v1.json", function(err, us){
const neighbors = topojson.neighbors(us.objects.states.geometries),
features = topojson.feature(us, us.objects.states).features;
// Greedy color selection
features.forEach(function(d,i){
d.properties.color = colors.filter(function(c){
return neighbors[i].every(n => features[n].properties.color !== c);
})[0];
colors.push(colors.shift());
});
svg.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", "#fff");
svg.selectAll("path")
.data(features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", d => d.properties.color)
.attr("stroke", "none");
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("d", path)
.attr("class", "mesh")
.attr("stroke-width", "1")
.attr("stroke", "#fff")
.attr("fill", "none");
render();
});
function render() {
var serialized = new XMLSerializer().serializeToString(svg.node()),
blob = new Blob([serialized], {type: "image/svg+xml"}),
url = URL.createObjectURL(blob);
img.onload = pixelate;
img.src = url;
}
function pixelate() {
var dx = Math.round(width / grain),
dy = Math.round(height / grain),
delay = 25;
canvas.style.display = "block";
context.clearRect(0, 0, width, height);
offscreenContext.clearRect(0, 0, width, height);
offscreenContext.drawImage(img, 0, 0, width, height, 0, 0, dx, dy);
context.drawImage(offscreen, 0, 0, dx, dy, 0, 0, width, height);
up ? grain-- : grain++;
if (grain === 64 || grain === 1) {
up = !up;
delay = 500;
}
if (grain === 1) {
canvas.style.display = "none";
}
setTimeout(pixelate, delay);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment