Skip to content

Instantly share code, notes, and snippets.

@annabsmylie
Last active September 28, 2016 05:00
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 annabsmylie/20dc799fd8f3376ba2ebefb2daa2d8bb to your computer and use it in GitHub Desktop.
Save annabsmylie/20dc799fd8f3376ba2ebefb2daa2d8bb to your computer and use it in GitHub Desktop.
texture block
license: mit
<!DOCTYPE html>
<html>
<head>
<script src="http://riccardoscalco.github.io/textures/textures.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<meta charset="utf-8">
<title>Texture Test</title>
</head>
<body>
<div id="example"></div>
<script>
var width = 500,
height = 500,
// An n X n grid of circles will be created.
n = 12,
x = d3.scale.linear()
.domain([0, n])
.range([0, width]),
y = d3.scale.linear()
.domain([0, n])
.range([0, height]),
radius = 20,
transitionDuration = 1000,
svg = d3.select("#example").append("svg")
.attr("width", width)
.attr("height", height)
// Center the SVG with respect to default width of bl.ocks.
.style("position", "absolute")
.style("left", 960 / 2 - width / 2),
// Textures need to be generated multiple times,
// once for each color they are paired with.
textureGenerators = [
function(){
return textures.lines().thicker();
},
function(){
return textures.circles().size(5);
},
function(){
return textures.paths().d("squares").size(8);
}
],
// Create a scale that encapsulates texture mappings.
textureScale = d3.scale.ordinal()
.domain(["X", "Y", "Z"])
.range(textureGenerators),
// Create a scale that encapsulates colors.
// Colors from http://colorbrewer2.org/
colorScale = d3.scale.ordinal()
.domain(["A", "B", "C"])
.range(["#1b9e77", "#d95f02", "#7570b3"]),
// Create a nested ordinal scale for color and texture.
colorTextureScale = d3.scale.ordinal()
// The first level is for color.
.domain(colorScale.domain())
.range(colorScale.range().map(function(color){
// The second level is for texture.
return d3.scale.ordinal()
.domain(textureScale.domain())
.range(textureScale.range().map(function(generateTexture){
// Generate a new texture for each (color, texture) pair.
return colorizeTexture(generateTexture(), color);
}))
}));
// Makes the given texture appear as the given color.
function colorizeTexture(texture, color){
// Use stroke, present on all textures.
var texture = texture.stroke(color);
// Use fill, present only on some textures (e.g. "circles", not "lines").
if(texture.fill){
texture.fill(color);
}
return texture;
}
// Initialize defs for each (texture, color) pair.
colorTextureScale.range().forEach(function(scale){
scale.range().forEach(svg.call, svg);
});
// Initialize the data grid.
var data = [];
for(var i = 0; i < n; i++){
for(var j = 0; j < n; j++){
data.push({
i: i,
j: j,
// "a" corresponds to color.
a: i < n / 3 ? "A" : i < (n * 2 / 3) ? "B" : "C",
// "b" corresponds to texture.
b: j < n / 3 ? "X" : j < (n * 2 / 3) ? "Y" : "Z"
});
}
}
// Create the marks.
var marks = svg.selectAll(".mark")
.data(data)
.enter().append("circle")
// The "mark" class is necessary, because
// selectAll("circle") conflicts with the circle texture.
.attr("class", "mark")
.attr("cx", function(d){ return x(d.i) + radius; })
.attr("cy", function(d){ return y(d.j) + radius; })
// Use the color scale for the stroke around each circle.
.style("stroke", function(d){ return colorScale(d.a); })
// Use the nested texture & color scale to define the texture.
.style("fill", function(d){
return colorTextureScale(d.a)(d.b).url();
});
// Periodically set a random radius on each circle.
function randomizeSize(){
marks.transition().duration(transitionDuration)
.attr("r", function(){ return Math.random() * radius; });
}
randomizeSize();
setInterval(randomizeSize, transitionDuration);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment