Same as this example, but supporting the intersection of three regions. The code could be easily generalized to more regions.
/* get a D3 reference of the SVG
*/
(function() {
var A, B, C, c, defs, hatches, new_patterns, svg, vis;
svg = d3.select('svg');
vis = svg.append('g').attr('transform', 'translate(350,45) scale(0.8)');
/* define three colors
*/
c = 40;
A = d3.hcl(60, c, 80);
B = d3.hcl(180, c, 70);
C = d3.hcl(300, c, 60);
/* create hatch patterns
*/
hatches = [
{
size: 40,
c: [A, B],
id: 'AB'
}, {
size: 40,
c: [B, C],
id: 'BC'
}, {
size: 40,
c: [A, C],
id: 'AC'
}, {
size: 60,
c: [A, B, C],
id: 'ABC'
}
];
defs = svg.append('defs');
new_patterns = defs.selectAll('.hatch').data(hatches).enter().append('pattern').attr('class', 'hatch').attr('id', function(d) {
return d.id;
}).attr('patternUnits', 'userSpaceOnUse').attr('width', function(d) {
return d.size;
}).attr('height', function(d) {
return d.size;
});
new_patterns.append('rect').attr('x', 0).attr('y', 0).attr('width', function(d) {
return d.size;
}).attr('height', function(d) {
return d.size;
}).attr('fill', function(d) {
return d.c[0];
});
new_patterns.append('path').attr('d', function(d) {
return "M0 0 L" + (d.size / d.c.length) + " 0 L0 " + (d.size / d.c.length) + " z\nM" + d.size + " 0 L" + d.size + " " + (d.size / d.c.length) + " L" + (d.size / d.c.length) + " " + d.size + " L0 " + d.size + " z";
}).attr('fill', function(d) {
return d.c[1];
});
new_patterns.filter(function(d) {
return d.c.length === 3;
}).append('path').attr('d', function(d) {
return "M" + (d.size / 3) + " 0 L" + (2 * d.size / 3) + " 0 L0 " + (2 * d.size / 3) + " L0 " + (d.size / 3) + " z\nM" + d.size + " " + (d.size / 3) + " L" + d.size + " " + (2 * d.size / 3) + " L" + (2 * d.size / 3) + " " + d.size + " L" + (d.size / 3) + " " + d.size + " z";
}).attr('fill', function(d) {
return d.c[2];
});
/* create a fake intersection of two squares
*/
vis.append('path').attr('d', 'M0 0 l300 0 l0 100 l-200 0 l0 100 l-100 0 z').attr('fill', A);
vis.append('path').attr('d', 'M300 100 l100 0 l0 300 l-200 0 l0 -100 l100 0 z').attr('fill', B);
vis.append('path').attr('d', 'M-100 200 l100 0 l0 100 l100 0 l0 100 l100 0 l0 100 l-300 0 z').attr('fill', C);
vis.append('path').attr('d', 'M100 100 l200 0 l0 200 l-100 0 l0 -100 l-100 0 z').attr('fill', 'url(#AB)');
vis.append('rect').attr('x', 0).attr('y', 200).attr('width', 100).attr('height', 100).attr('fill', 'url(#AC)');
vis.append('rect').attr('x', 100).attr('y', 200).attr('width', 100).attr('height', 100).attr('fill', 'url(#ABC)');
vis.append('rect').attr('x', 100).attr('y', 300).attr('width', 100).attr('height', 100).attr('fill', 'url(#BC)');
}).call(this);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="Coloring of intersecting regions"/>
<title>Coloring of intersecting regions</title>
<script src="//d3js.org/d3.v3.min.js"></script>
</head>
<body>
<svg width="960" height="500">
</svg>
<script src="index.js"></script>
</html>
### get a D3 reference of the SVG ###
svg = d3.select('svg')
vis = svg.append('g')
.attr('transform', 'translate(350,45) scale(0.8)')
### define three colors ###
c = 40
A = d3.hcl(60,c,80)
B = d3.hcl(180,c,70)
C = d3.hcl(300,c,60)
### create hatch patterns ###
hatches = [
{size:40,c:[A,B],id:'AB'},
{size:40,c:[B,C],id:'BC'},
{size:40,c:[A,C],id:'AC'},
{size:60,c:[A,B,C],id:'ABC'}
]
defs = svg.append('defs')
new_patterns = defs.selectAll('.hatch')
.data(hatches)
.enter().append('pattern')
.attr('class', 'hatch')
.attr('id', (d)->d.id)
.attr('patternUnits', 'userSpaceOnUse')
.attr('width', (d)->d.size)
.attr('height', (d)->d.size)
new_patterns.append('rect')
.attr('x',0)
.attr('y',0)
.attr('width', (d)->d.size)
.attr('height', (d)->d.size)
.attr('fill', (d)->d.c[0])
new_patterns.append('path')
.attr('d', (d) -> """
M0 0 L#{d.size/d.c.length} 0 L0 #{d.size/d.c.length} z
M#{d.size} 0 L#{d.size} #{d.size/d.c.length} L#{d.size/d.c.length} #{d.size} L0 #{d.size} z
""")
.attr('fill', (d)->d.c[1])
new_patterns.filter((d)->d.c.length is 3).append('path')
.attr('d', (d) -> """
M#{d.size/3} 0 L#{2*d.size/3} 0 L0 #{2*d.size/3} L0 #{d.size/3} z
M#{d.size} #{d.size/3} L#{d.size} #{2*d.size/3} L#{2*d.size/3} #{d.size} L#{d.size/3} #{d.size} z
""")
.attr('fill', (d)->d.c[2])
### create a fake intersection of two squares ###
vis.append('path')
.attr('d', 'M0 0 l300 0 l0 100 l-200 0 l0 100 l-100 0 z')
.attr('fill', A)
vis.append('path')
.attr('d', 'M300 100 l100 0 l0 300 l-200 0 l0 -100 l100 0 z')
.attr('fill', B)
vis.append('path')
.attr('d', 'M-100 200 l100 0 l0 100 l100 0 l0 100 l100 0 l0 100 l-300 0 z')
.attr('fill', C)
vis.append('path')
.attr('d', 'M100 100 l200 0 l0 200 l-100 0 l0 -100 l-100 0 z')
.attr('fill', 'url(#AB)')
vis.append('rect')
.attr('x', 0)
.attr('y', 200)
.attr('width', 100)
.attr('height', 100)
.attr('fill', 'url(#AC)')
vis.append('rect')
.attr('x', 100)
.attr('y', 200)
.attr('width', 100)
.attr('height', 100)
.attr('fill', 'url(#ABC)')
vis.append('rect')
.attr('x', 100)
.attr('y', 300)
.attr('width', 100)
.attr('height', 100)
.attr('fill', 'url(#BC)')