Infinite argyle with random ColorBrewer and d3 4.0 color scales.
Created
May 20, 2017 13:39
-
-
Save Thanaporn-sk/43be56a28d7c26efc701ad7772ec103c to your computer and use it in GitHub Desktop.
Argyle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
var runs = 0, | |
scheme; | |
var colorSchemes = d3.shuffle([ | |
["#e0f3db", "#a8ddb5", "#43a2ca"], // GnBu | |
["#ece2f0", "#a6bddb", "#1c9099"], // PuBuGn | |
["#fde0dd", "#fa9fb5", "#c51b8a"], // RdPu | |
["#f7fcb9", "#addd8e", "#31a354"], // YlGn | |
["#edf8b1", "#7fcdbb", "#2c7fb8"], // YlGnBlue | |
["#ffeda0", "#feb24c", "#f03b20"], // YlOrRd | |
["#d8b365", "#f6e8c3", "#c7eae5", "#5ab4ac"], // BrBG | |
["#fc8d59", "#ffffbf", "#99d594"], // Spectral3 | |
["#d7191c", "#fdae61", "#abdda4", "#2b83ba"], // Spectral4 | |
["#fc8d59", "#ffffbf", "#91bfdb"], // RdYlBu | |
["#fc8d59", "#fee090", "#e0f3f8", "#91bfdb"], // RdYlBu | |
d3.interpolateViridis, | |
d3.interpolatePlasma, | |
d3.interpolateWarm, | |
d3.interpolateCool, | |
d3.interpolateRainbow | |
]); | |
var greys = ["#222", "#666", "#ccc", "#f7f7f7"]; | |
var patterns = [standard, checker, wave, bowtie, columns]; | |
function getPattern() { | |
var r = Math.random(), | |
totalColors = r < 0.1 ? 5 : r < 0.5 ? 4 : 3, | |
colors = scheme.slice(0), | |
stitchColors; | |
// Pad with greys | |
if (colors.length < totalColors) { | |
d3.shuffle(greys); | |
colors = colors.concat(greys.slice(0, totalColors - colors.length)); | |
} else { | |
colors = d3.shuffle(colors).slice(0, totalColors); | |
// Mix in a grey sometimes anyway | |
if (Math.random() < 0.3) { | |
colors[0] = choose(greys); | |
} | |
} | |
stitchColors = getStitchColors(colors); | |
d3.shuffle(colors); | |
return { | |
stitch: stitchColors, | |
color: choose(patterns)(colors), | |
}; | |
} | |
// Set stitch coloring based on highest contrast ratio | |
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef | |
function getStitchColors(colors) { | |
var l = colors.map(relativeLuminance), | |
stitchColors = {}, | |
splice = colors.length === 5 || (colors.length === 4 && Math.random() < 0.35), | |
primary, | |
ratios; | |
// Calculate contrast ratios for other colors | |
ratios = colors.map(function(color, i){ | |
return colors.map(function(d, j){ | |
return (Math.max(l[i], l[j]) + 0.05) / (Math.min(l[i], l[j]) + 0.05); | |
}); | |
}); | |
// Color with highest average contrast | |
primary = d3.scan(ratios, function(a, b) { return 1 / d3.mean(a) - 1 / d3.mean(b); }); | |
// Dedicated stitch color | |
if (splice) { | |
colors.forEach(function(color, i){ | |
if (i !== primary) { | |
stitchColors[color] = colors[primary]; | |
} | |
}); | |
colors.splice(primary, 1); | |
// Background colors as stitch colors on each other | |
} else { | |
colors.forEach(function(color, i){ | |
var secondary; | |
if (i === primary) { | |
secondary = d3.scan(ratios[i], function(a, b) { return 1 / a - 1 / b; }); | |
stitchColors[color] = colors[secondary]; | |
} else { | |
stitchColors[color] = colors[primary]; | |
} | |
}); | |
} | |
return stitchColors; | |
} | |
// sRGB relative luminance | |
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef | |
function relativeLuminance(color) { | |
var rgb = d3.rgb(color); | |
var weights = ["r", "g", "b"].map(function(key){ | |
var val = rgb[key] / 255; | |
return val <= 0.03928 ? | |
val / 12.92 : | |
Math.pow((val + 0.055) / 1.055, 2.4); | |
}); | |
return weights[0] * 0.2126 + weights[1] * 0.7152 + weights[2] * 0.0722; | |
} | |
function nextColorScheme() { | |
var offset, | |
numColors; | |
// Move first to last | |
colorSchemes.push(scheme = colorSchemes.shift()); | |
// For d3 scales, get random evenly spaced colors | |
if (typeof scheme === "function") { | |
offset = Math.random(); | |
numColors = choose([3, 4]); | |
scheme = d3.range(numColors).map(function(d){ | |
return scheme((offset + d / (numColors)) % 1); | |
}); | |
} | |
} | |
function standard(colors){ | |
return function(d){ | |
return d[0] % 2 ? | |
colors[0] : | |
colors[1 + d[1] % (colors.length - 1)]; | |
}; | |
} | |
function checker(colors){ | |
return function(d) { | |
return d[0] % 2 ? | |
colors[0] : | |
colors[1 + ((d[1] + d[0] / 2) % (colors.length - 1))]; | |
}; | |
} | |
function wave(colors){ | |
return function(d){ | |
return d[0] % 2 ? | |
colors[0] : | |
d[0] % 4 ? | |
colors[2 + Math.floor(d[0] / 4) % (colors.length - 2)] : | |
colors[1]; | |
}; | |
} | |
function bowtie(colors){ | |
if (colors.length < 4) { | |
return standard(colors); | |
} | |
return function(d){ | |
return d[0] % 2 ? | |
colors[d[1] % 2] : | |
colors[2 + (d[0] / 2) % 2]; | |
}; | |
} | |
function columns(colors) { | |
if (colors.length < 4) { | |
return checker(colors); | |
} | |
return function(d) { | |
return d[0] % 2 ? | |
colors[d[1] % 2] : | |
colors[2 + d[1] % 2]; | |
}; | |
} | |
function choose(arr) { | |
return arr[Math.floor(Math.random() * arr.length)]; | |
} | |
window.argyle = function(){ | |
if (runs++ % 3 === 0) { | |
nextColorScheme(); | |
} | |
return getPattern(); | |
}; | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<style> | |
path { | |
stroke: none; | |
} | |
line { | |
stroke: #444; | |
stroke-width: 1px; | |
stroke-linecap: round; | |
opacity: 0.8; | |
} | |
@media (-webkit-min-device-pixel-ratio: 1.5), | |
(min-resolution: 1.5dppx) { | |
line { | |
stroke-width: 0.6px; | |
opacity: 0.95; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="argyle.js"></script> | |
<script> | |
var angle = Math.PI / 6, | |
rx = 30, | |
ry = rx / Math.tan(angle), | |
diagonal = Math.sqrt(rx * rx + ry * ry); | |
width = 960, | |
height = Math.ceil(500 / ry) * ry; | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var diamond = d3.symbol() | |
.type(d3.symbolDiamond) | |
.size(ry * rx * 2); | |
// Array of [row, column] positions | |
var positions = d3.merge(d3.range(Math.ceil(height / ry) + 1).map(function(r){ | |
return d3.range(Math.ceil(width / (rx * 2)) + 1).map(function(c){ | |
return [r, c]; | |
}); | |
})); | |
var g = svg.selectAll(".diamond") | |
.data(positions) | |
.enter() | |
.append("g") | |
.attr("transform", function(d){ | |
// Odd-r coordinates | |
var x = (d[0] % 2 ? rx : 0) + d[1] * rx * 2, | |
y = d[0] * ry; | |
return "translate(" + x + " " + y + ")"; | |
}); | |
var background = g.append("path") | |
.attr("d", diamond); | |
g.append("line") | |
.attr("x1", rx / 2) | |
.attr("x2", -rx / 2); | |
g.append("line") | |
.attr("x1", -rx / 2) | |
.attr("x2", rx / 2); | |
// Separate lines + calculated dasharray to prevent cuts | |
var stitch = g.selectAll("line") | |
.attr("y1", -ry / 2) | |
.attr("y2", ry / 2) | |
.attr("stroke-dasharray",(diagonal / 30) + "," + (diagonal / 30)) | |
.attr("stroke-dashoffset",(-diagonal / 60)); | |
recolor(true); | |
function recolor(first) { | |
var pattern = argyle(); | |
var t = d3.transition() | |
.delay(first ? 0 : 1000) | |
.duration(first ? 0 : 1000) | |
.on("end", recolor); | |
background.transition(t) | |
.styleTween("fill", function(d){ | |
return d3.interpolateLab(getComputedStyle(this).getPropertyValue("fill"), pattern.color(d)); | |
}); | |
stitch.transition(t) | |
.styleTween("stroke", function(d){ | |
return d3.interpolateLab(getComputedStyle(this).getPropertyValue("stroke"), pattern.stitch[pattern.color(d)]); | |
}); | |
} | |
d3.select(self.frameElement).style("height", height + "px"); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
�PNG | |