这是关于jsfiddle的项目:http://jsfiddle.net/mLnB3/
我有这种格式的数据:
var data = [ { "category": "Category1", "subcategories": [ { "subcategory": "Subcategory1A", "comments": [ { "comment" : "1Acomment1", "count": 8, }, { "comment": "1Acomment2", "count": 7 } ] }, { "subcategory": "Subcategory1B", "comments": [ { "comment": "1Bcomment1", "count": 11, } ] }, { "subcategory": "Subcategory1C", "comments": [ { "comment": "1Ccomment1", "count": 2, } ] } ] }, { "category": "Category2", "subcategories": [ { "subcategory": "Subcategory2A", "comments": [ { "comment": "2Acomment1", "count": 6, }, { "comment": "2Acomment2", "count": 9, }, { "comment": "2Acomment3", "count": 9, }, { "comment": "2Acomment4", "count": 9, } ] }, { "subcategory": "Subcategory2B", "comments": [ { "comment": "2Bcomment1", "count": 14 } ] } ] }
].
我想为每个类别创建一个条形图.因此,类别1将是条形图,类别2将是条形图,依此类推(还有更多类别).每个类别具有不同数量的子类别,每个子类别具有不同数量的注释(范围从1到30).在每个条形图中,注释将填充X轴.因此,对于每个图表,我需要生成这样的东西:
我正在使用d3.select("body").selectAll("svg").data(data).enter().append("svg")....来创建它们.
我的问题是,由于每个不同的图表将具有不同数量的xAxis刻度,我不知道如何为每个图表的xAxis设置序数比例的域.yAxis的线性比例也存在同样的问题,因为我通常会为那个做一个[0,d3.max(...)],但对于每个条形图也是如此.
这是我到目前为止:
var margin = {top: 20, right: 20, bottom: 20, left: 20}, width = 400 - margin.left - margin.right, height = 300 - margin.top - margin.bottom; var xScale = d3.scale.ordinal() //.domain(???help???) .rangeRoundBands([0, width], .3); var yScale = d3.scale.linear() //.domain(???help???) .range([height, 0]); var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom"); var yAxis = d3.svg.axis() .scale(yScale) .orient("left") .ticks(5); var svg = d3.select("body").selectAll("svg") .data(data) .enter() .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("id", function(d){return d.category}) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("transform", function(d) { return "rotate(-25)" }); svg.append("g") .attr("class", "y axis") .call(yAxis); var subcategory = svg.selectAll(".subcategory") .data(function(d){ return d3.values(d.subcategories);}) .enter() .append("g") .attr("class", "subcategory") .attr("id", function(d){return d.subcategory;}); var comment = subcategory.selectAll(".comment") .data(function(d){return d3.values(d.comments);}) .enter() .append("g") .attr("class", "comment") .attr("id", function(d){return d.comment;}); comment.append("rect") .attr("height", function(d){ return height - yScale(d.count); }) .attr("width", xScale.rangeBand()/2) .attr("y", function(d){ return yScale(d.count); }); comment.append("text") .text(function(d){ return d.count; }) .attr("x", xScale.rangeBand() / 2) .attr("y", function(d){ return yScale(d.count) - 5; }) .attr("text-anchor", "middle") .attr("fill", "#353535") .attr("font-weight", "bold");
当然,这会使矩形和文本元素上的轴和宽度,高度,x和y属性变得疯狂.这是一个基本的条形图模板,我已经多次使用,当我只有1个xscale域和1个yscale域时,它总能正常工作.
那么如何设置xScale域?和yScale域名?如何从类别中获取每个注释并说"这些将是此图表的xScale"?请记住,一些图表将有30条评论,一些将有7条评论,一些将有最多评论数为200,一些将具有最大评论数为2.它们对于每个图表是可变的.因此,如果我使用d3为数据数组中的每个类别创建一个SVG元素,我该如何解决这个问题呢?
xScale和yScale将针对每个类别图表而变化,因为它们具有不同的域(在y比例的情况下为最大值).因此,我建议你创建一个每个呼叫中的独立的人在这个小提琴
d3.select("body").selectAll("svg") .data(data) .enter() .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("id", function(d){return d.category}) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .each(function(d, i){ var svg = d3.select(this); var allComments = d.subcategories.reduce(function(prev, curr, i, array){ return prev.concat(curr.comments); }, []); var xDomain = allComments.reduce(function(prev, curr, i, array){ prev.push(curr.comment); return prev; }, []); var yMax = d3.max(allComments, function(comment) { return comment.count; }) var xScale = d3.scale.ordinal() .domain(xDomain) .rangeRoundBands([0, width], .3); var yScale = d3.scale.linear() .domain([0, yMax + 2]) // giving ticks specific padding .range([height, 0]); var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom"); var yAxis = d3.svg.axis() .scale(yScale) .orient("left") .ticks(5); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("transform", function(d) { return "rotate(-25)" }); ....