Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active January 17, 2024 16:32
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veltman/50a350e86de82278ffb2df248499d3e2 to your computer and use it in GitHub Desktop.
Save veltman/50a350e86de82278ffb2df248499d3e2 to your computer and use it in GitHub Desktop.
CMYK halftone printing
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var defs = svg.append("defs");
var background = svg.append("g")
.attr("class", "dots");
// r=0 is a bug in Chrome
var radius = d3.scaleSqrt()
.range([1e-9, 6]);
var colors = ["yellow", "magenta", "cyan", "black"],
rotation = [0, -15, 15, 45];
var patterns = defs.selectAll("pattern")
.data(colors)
.enter()
.append("pattern")
.attr("id", Object)
.attr("patternUnits", "userSpaceOnUse")
.attr("width", 12)
.attr("height", 12)
.append("circle")
.attr("fill", Object)
.attr("cx", 6)
.attr("cy", 6);
defs.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width / 5)
.attr("height", height / 5);
svg.append("g").attr("clip-path", "url(#clip)")
.attr("transform", "translate(" + (width * 2 / 5) + " " + (height * 2 / 5) + ")")
.append("g")
.attr("class", "dots")
.attr("transform", "scale(0.1 0.1)")
.append("rect")
.attr("width", width * 2)
.attr("height", height * 2)
.attr("fill", "#fff");
d3.selectAll(".dots")
.selectAll(".color")
.data(colors)
.enter()
.append("rect")
.attr("class", "color")
.attr("width", width * 4)
.attr("height", width * 4)
.attr("x", width * -3 / 2)
.attr("y", width * -3 / 2)
.style("mix-blend-mode", "multiply")
.attr("fill", function(d){
return "url(#" + d + ")";
})
.attr("transform", function(d, i){
return rotation[i] ? "rotate(" + rotation[i] + " " + (width / 2) + " " + (height / 2) + ")" : null;
});
d3.timer(function(t){
t = t % 16000 / 8000;
if (t > 1) {
t = 2 - t;
}
var cmyk = rgbToCmyk(d3.color(d3.interpolateRainbow(t)));
patterns.attr("r", function(d){
return radius(cmyk[d]);
});
});
function rgbToCmyk(rgb) {
var r = rgb.r / 255,
g = rgb.g / 255,
b = rgb.b / 255,
k = 1 - Math.max(r, g, b);
return {
cyan: (1 - r - k) / (1 - k),
magenta: (1 - g - k) / (1 - k),
yellow: (1 - b - k) / (1 - k),
black: k
};
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment