Symbols as Nodes in Force Layout
HTML
<a href="http://stackoverflow.com/questions/25050011/complex-symbols-within-a-single-node-in-d3-js-where-symbols-depend-on-data">complex-symbols-within-a-single-node-in-d3-js-where-symbols-depend-on-data</a>
CSS
svg {
border: 2px solid #efefef;
}
JavaScript
var w = 500,
h = 400;
var tau = 2 * Math.PI;
// EACH DATUM IS AN ARRAY OF SHAPES
var data = [
['diamond', 'triangle-up'],
['triangle-up', 'cross', 'square', 'triangle-down', 'circle'],
['square', 'triangle-down', 'diamond'],
['diamond', 'circle'],
['triangle-down', 'square', 'cross', 'diamond']
];
// GIVE EACH SHAPE A COLOR
var color = d3.scale.category10()
.domain(d3.svg.symbolTypes);
// MAKE EACH DATUM AN OBJECT SO THAT `x` AND `y` VALUES CAN BE ATTACHED BY LAYOUT
var nodes = data.map(function(d,i) {
return {data: d};
});
// CREATE THE FORCE LAYOUT, IN THIS CASE USING A HIGHLY REPULSIVE CHARGE TO AVOID OVERLAP
var force = d3.layout.force()
.nodes(nodes)
.size([1, 1])
.charge(-400)
.on('tick', tick)
.start();
var svg = d3.select('body').append('svg')
.attr('width', w)
.attr('height', h);
// USE THE `nodes` DATA TO CREATE **GROUPS** RATHER THAN SINGLE ELEMENTS
var groups = svg.selectAll('.symbol-group')
.data(nodes)
.enter().append('g')
.attr('class', 'symbol-group')
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
});
// WITHIN EACH GROUP USE THE ARRAY OF SHAPES TO CREATE MULTIPLE SYMBOLS
var symbols = groups.selectAll('.symbol')
.data(function(d) {return d.data;})
.enter().append('path')
.attr('d', d3.svg.symbol().type(function(d) {return d;}))
.attr('fill', function(d) {return color(d);})
.attr('transform', function(d,i) {
// THIS FUNCTION SIMPLY PLACES THE SYMBOLS EVENLY SPACED IN A CIRCLE AROUND THE CENTER OF EACH GROUP
var numSymbols = d3.select(this.parentNode).datum().data.length;
var radius = 12;
var angle = i * (tau / numSymbols);
var x = radius * Math.cos(angle),
y = radius * Math.sin(angle);
return 'translate(' + x + ',' + y + ')';
});
// ON EACH TICK, UPDATE THE TRANSLATION OF THE GROUPS
function tick(e) {
svg.selectAll('.symbol-group')
.attr('transform', function(d) {
return...