A slight variation on this SVG pixelation that leaves the background transparent during pixelation for a bit of a different effect.
See also: Gradual pixelation
height: 600 |
A slight variation on this SVG pixelation that leaves the background transparent during pixelation for a bit of a different effect.
See also: Gradual pixelation
<!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.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> |