我正在尝试实施分组条形图,但无法使其正常工作。我的数据结构如下:
[{
"Type": "Email",
"DataPoints": [{
"xValue": 1,
"Value": 17
},
{
"xValue": 2,
"Value": 59
}]
},
{
"Type": "Phone",
"DataPoints": [{
"xValue": 1,
"Value": 1
}]
}]
我的代码如下:
var margin = { top: 20, right: 0, bottom: 40, left: 50 },
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
tooltipTextColour = "white";
if (data.length > 0) {
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = placeholder.append("svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var types = d3.entries(data);
x0.domain(types.map(function (d) { return d.Type; }));
x1.domain(types).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(types, function (d) { return d3.max(d.value.DataPoints, function (d) { return d.Value; }); })]);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.append('text')
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Complaints");
var type = svg.selectAll(".type")
.data(data)
.enter()
.append('g')
.attr('class', 'type')
.attr('transform', function (d) { return 'translate(' + x0(d.Type) + ',0)'; });
type.selectAll("rect")
.data(function (d) { return d.DataPoints; })
.enter()
.append('rect')
.attr('width', x1.rangeBand())
.attr('x', function (d) { return x1(d.xValue); })
.attr('y', function (d) { return y(d.Value); })
.attr('height', function (d) { return height - y(d.Value); })
.style('fill', function (d, i) { return color(d.xValue); });
}
else {
placeholder.append('p').text('No Data to Display').style('font-weight', 'bold');
}
这会产生以下结果:
有人知道为什么会这样吗?我认为这是因为它没有正确渲染x轴,但我无法理解为什么。
非常感谢任何帮助。
答案 0 :(得分:2)
您没有正确设置x0
和x1
个域名。应该是这样的:
// x0 is easy it's just the type
x0.domain(data.map(function(d) {
return d.Type
}));
// x1 is messy
// this reduces each DataPoints xValue into a single array
// and then creates a set from it to remove duplicates
x1.domain(
d3.set(data.reduce(function(previousValue, currentValue) {
return previousValue.concat(currentValue.DataPoints.map(function(d) {
return d.xValue
}))
}, [])).values()
).rangeRoundBands([0, x0.rangeBand()]);
工作代码:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<div id="placeholder"></div>
<script>
var placeholder = d3.select('#placeholder');
var color = d3.scale.category10();
var margin = {
top: 20,
right: 0,
bottom: 40,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
tooltipTextColour = "white";
var data = [{
"Type": "Email",
"DataPoints": [{
"xValue": 1,
"Value": 17
}, {
"xValue": 2,
"Value": 59
}]
}, {
"Type": "Phone",
"DataPoints": [{
"xValue": 1,
"Value": 1
},{
"xValue": 3,
"Value": 30
}]
}];
if (data.length > 0) {
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = placeholder.append("svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
x0.domain(data.map(function(d) {
return d.Type
}));
x1.domain(
d3.set(data.reduce(function(previousValue, currentValue) {
return previousValue.concat(currentValue.DataPoints.map(function(d) {
return d.xValue
}))
}, [])).values()
).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) {
return d3.max(d.DataPoints, function(d) {
return d.Value;
});
})]);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.append('text')
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Complaints");
var type = svg.selectAll(".type")
.data(data)
.enter()
.append('g')
.attr('class', 'type')
.attr('transform', function(d) {
return 'translate(' + x0(d.Type) + ',0)';
});
type.selectAll("rect")
.data(function(d) {
return d.DataPoints;
})
.enter()
.append('rect')
.attr('width', x1.rangeBand())
.attr('x', function(d) {
return x1(d.xValue);
})
.attr('y', function(d) {
return y(d.Value);
})
.attr('height', function(d) {
return height - y(d.Value);
})
.style('fill', function(d, i) {
return color(d.xValue);
});
} else {
placeholder.append('p').text('No Data to Display').style('font-weight', 'bold');
}
</script>
</body>
</html>