制作d3图表反应(v5)



我是d3.js的新手,正试图在UIKIT容器中基于此示例制作一个反应图。我试着用调整容器的宽度

d3.select("#chart").node().getBoundingClientRect().width

并使用调整svg的viewBox纵横比

<div id="chart" class="uk-block-muted uk-margin-top"><svg width="960" height="500" viewBox="0 0 960 500" preserveAspectRatio="xMidYMid meet"></div>

然而,它不起作用,而且总是偏离图表。我哪里错了?最好的方法是什么?

</head>
<body>
<div id="chart" class=class="uk-block-muted uk-margin-top"> <svg class="chart"></svg> </div>
<script>
var data = {
labels: [
'Cornwall & Iles of Scilly', 'Isle of Wight', 'Cumbria',
'Dorset', 'Norfolk', 'Devon', 'Bournemouth'
],
series: [
{
label: 'Week ending 5 July',
values: [1.4, 2.1, 3.6, 1.1, 1.6, 0.4, 1]
},
{
label: 'Week ending 2 August',
values: [3.3, 0, 8.2, 0.8, 2.1, 1.5, 2]
},
]
};
var chartWidth       = d3.select("#chart").node().getBoundingClientRect().width,
barHeight        = 20,
groupHeight      = barHeight * data.series.length,
gapBetweenGroups = 10,
spaceForLabels   = 150,
spaceForLegend   = 180;
// Zip the series data together (first values, second values, etc.)
var zippedData = [];
for (var i=0; i<data.labels.length; i++) {
for (var j=0; j<data.series.length; j++) {
zippedData.push(data.series[j].values[i]);
}
}
console.log(zippedData);
// Color scale
var color = d3.scaleOrdinal()
.range(["#16A085", "#33435C"]);
var chartHeight = barHeight * zippedData.length + gapBetweenGroups * data.labels.length;
var x = d3.scaleLinear()
.domain([0, d3.max(zippedData)])
.range([0, chartWidth]);
var y = d3.scaleLinear()
.range([chartHeight + gapBetweenGroups, 0]);
var yAxis = d3.axisLeft()
.scale(y)
.tickFormat('')
.tickSize(0);
var xAxis = d3.axisBottom(x).tickFormat(function(d){
return d;
});
// Specify the chart area and dimensions
var chart = d3.select(".chart")
.attr("width", spaceForLabels + chartWidth + spaceForLegend)
.attr("height", chartHeight +30);
// console.log(chartHeight);
// Create bars
var bar = chart.selectAll("g")
.data(zippedData)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" + spaceForLabels + "," + (i * barHeight + gapBetweenGroups * (0.5 + Math.floor(i/data.series.length))) + ")";
});
// Create rectangles of the correct width
bar.append("rect")
.attr("fill", function(d,i) { return color(i % data.series.length); })
.attr("class", "bar")
.attr("width", x)
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) { return d; });
// Draw labels
bar.append("text")
.attr("class", "label")
.attr("x", function(d) { return - 10; })
.attr("y", groupHeight / 2)
.attr("dy", ".35em")
.text(function(d,i) {
if (i % data.series.length === 0)
return data.labels[Math.floor(i/data.series.length)];
else
return ""});
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + spaceForLabels + ", " + -gapBetweenGroups/2 + ")")
.call(yAxis);
chart.append("g")         // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(" + spaceForLabels + "," + chartHeight + ")")
.call(xAxis);
// Draw legend
var legendRectSize = 18,
legendSpacing  = 4;
var legend = chart.selectAll('.legend')
.data(data.series)
.enter()
.append('g')
.attr('transform', function (d, i) {
var height = legendRectSize + legendSpacing;
var offset = -gapBetweenGroups/2;
var horz = spaceForLabels + chartWidth + 40 - legendRectSize;
var vert = i * height - offset;
return 'translate(' + horz + ',' + vert + ')';
});
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', function (d, i) { return color(i); })
.style('stroke', function (d, i) { return color(i); });
legend.append('text')
.attr('class', 'legend')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function (d) { return d.label; });
</script>
</body>

您在设置数据范围时使用svg的全宽,然后不考虑图例和标签。我刚刚在JSFiddle中测试了这一点,在考虑这两个变量时,条形图的大小似乎正确。

var x = d3.scaleLinear()
.domain([0, d3.max(zippedData)])
.range([0, chartWidth - spaceForLegend - spaceForLabels]);

最新更新