D3 Multi Circle Series Data Chart
Solution 1:
Most of it is just organising the data before plotting it. Within each series give each item an index, and then sort by value. The index property will then tell us the initial position of each item in the series. The first item in each series will now be the biggest value. Use this to build an offset for each series, and sum all these offsets to make a scale for positioning.
Then make group elements for each series, positioning using the offset we calculated.
Within each group, draw the circle elements. Since we sorted them they'll be drawn biggest first. The .index property can be used to colour by their original place in the series.
http://jsfiddle.net/0ht35rpb/2/
var width = 600;
var height = 400;
var svg = d3.select('svg').attr("width", width).attr("height",height);
var data = [{
"name": "Twitter",
"items": [{
"value": 2000
}, {
"value": 3000
}]
}, {
"name": "Facebook",
"items": [{
"value": 200
}, {
"value": 300
}]
}, {
"name": "Ebay",
"items": [{
"value": 2000
}, {
"value": 1000
}]
}, {
"name": "Foursquare",
"items": [{
"value": 2000
}, {
"value": 3000
},
{
"value": 4000
}]
}];
// organise the data. // Insert indices and sort items in each series// keep a running total of max circle size in each series// for later positioningvar x = 0;
var totalWidth = d3.sum (
data.map (function (series) {
series.items.forEach (function (item, i) {
item.index = i;
});
series.items.sort (function (a, b) {
return b.value - a.value;
});
var maxr = Math.sqrt(series.items[0].value);
x += maxr;
series.xcentre = x;
x += maxr;
return maxr * 2;
})
);
// make scales for position and colourvar scale = d3.scale.linear().domain([0,totalWidth]).range([0, width]);
var colScale = d3.scale.category10();
// add a group per series, position the group according to the values and position scale we calculated abovevar groups = svg.selectAll("g").data(data);
groups.enter().append("g");
groups.attr("transform", function(d) {
return ("translate("+scale(d.xcentre)+",0)");
});
// then add circles per series, biggest first as items are sorted// colour according to index (the property we inserted previously so we can// keep track of their original position in the series)var circles = groups.selectAll("circle").data(function(d) { return d.items;}, function(d) { return d.index; });
circles.enter().append("circle").attr("cy", height/2).attr("cx",0);
circles
.attr("r", function(d) { returnscale(Math.sqrt (d.value)); })
.style ("fill", function (d) { returncolScale(d.index); });
Solution 2:
mgraham's answer is great! But since I had already written this out (and then had to go to a meeting) here's how I would code it:
$(document).ready(function() {
var el = $('.serieschart');
var w = el.data("width");
var h = el.data("height");
var margin = {
top: 65,
right: 90,
bottom: 5,
left: 150
};
var svg = d3.select(el[0]).append("svg")
.attr("class", "series")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data = [{
"name": "Twitter",
"items": [{
"value": 2000
}, {
"value": 3000
}]
}, {
"name": "Facebook",
"items": [{
"value": 300
}, {
"value": 200
}]
}, {
"name": "Ebay",
"items": [{
"value": 1000
}, {
"value": 2000
}]
}, {
"name": "Foursquare",
"items": [{
"value": 2000
}, {
"value": 3000
}]
}]
// sort items array descending by size// this will help us draw the bigger one first// introduce an index for color assignment
data.forEach(function(d){
d.items.forEach(function(d1,i){
d1.id = i;
})
d.items.sort(function(x, y){
return d3.descending(x.value, y.value);
});
});
circleMaker();
functioncircleMaker() {
var colors = d3.scale.category10();
var counter = 0,
prevR = 0;
svg.selectAll("g")
.data(data)
.enter()
.append("g")
.selectAll("circle")
.data(function(d){
return d.items;
})
.enter()
.append("circle")
.attr("cy", 60)
.attr("cx", function(d, i) {
d.r = Math.sqrt(d.value);
if (i === 0) {
counter += prevR + d.r;
prevR = d.r;
}
return counter;
})
.attr("r", function(d){
return d.r;
})
.style("fill", function(d){
returncolors(d.id);
});
}
});
body {
background: #eeeeee;
}
<scriptsrc="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script><scriptsrc="http://d3js.org/d3.v3.min.js"></script><divid="holder"><divclass="serieschart"data-role="serieschart"data-width=450data-height=180></div></div>
Post a Comment for "D3 Multi Circle Series Data Chart"