[英]D3.js bar chart - axis and labels not working / transitioning
第一次使用D3.js。 我被困在获取条形图以在条形图上显示值标签,并在刷新数据时转换x / y轴。 我没有错误,代码来自将几个示例放在一起。 代码在下面, 这里是jfiddle的工作示例。 在真实的代码中,我使用d3.json提取数据,在jsfiddle中,我使用静态vars fyi。 任何帮助表示赞赏。
代码如下:
var data;
var margin = {
top: 20,
right: 0,
bottom: 30,
left: 30
},
width = 838 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.05);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
var svg = d3.select("#daychart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("http://10.0.0.13/sma/sma-php/inverterdata.php?var=CDAY&id=C1200031", function (error, data) {
data.forEach(function (d) {
d.max_energy = +d.max_energy;
});
x.domain(data.map(function (d) {
return d.xaxis;
}));
y.domain([0, d3.max(data, function (d) {
return d.max_energy;
})]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("transform", "rotate(0)")
.attr("y", 23)
.attr("x", 340)
.attr("dy", ".71em")
.style("text-anchor", "bottom")
.text("Timeline");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(0)")
.attr("y", -15)
.attr("x", -25)
.attr("dy", ".71em")
.style("text-anchor", "top")
.text("Energy - KWh");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function (d) {
return x(d.xaxis);
})
.attr("width", x.rangeBand())
.attr("y", function (d) {
return y(d.max_energy);
})
.transition().delay(function (d, i) {
return i * 10;
}).duration(10)
.attr("height", function (d) {
return height - y(d.max_energy);
});
//Create labels
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function (d) {
return parseFloat(Math.round(d.max_energy * 100) / 100).toFixed(1);
})
.attr("x", function (d) {
return x(d.xaxis) + x.rangeBand() / 2;
})
.attr("y", function (d) {
return height - y(d.max_energy) + 14;
})
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "black");
//});
//On click, update with new data
d3.select("p").on("click", function () {
// Get the data again
d3.json("http://10.0.0.13/sma/sma-php/inverterdata.php?var=PDAY&id=P100023", function (error, data) {
data.forEach(function (d) {
d.max_energy = +d.max_energy;
});
// Scale the range of the data again
x.domain(data.map(function (d) {
return d.xaxis;
}));
y.domain([0, d3.max(data, function (d) {
return d.max_energy;
})]);
// Make the changes
svg.selectAll(".bar") // change the bar
.data(data) // Update the data within.
.transition().delay(function (d, i) {
return i / data.length * 1000;
})
.duration(500)
.attr("x", function (d) {
return x(d.xaxis);
})
.attr("y", function (d) {
return y(d.max_energy);
})
.attr("width", x.rangeBand())
.attr("height", function (d) {
return height - y(d.max_energy);
});
//Update all labels
svg.selectAll("text")
.data(data).transition()
.delay(function (d, i) {
return i / data.length * 1000;
})
.duration(500)
.text(function (d) {
return parseFloat(Math.round(d.max_energy * 100) / 100).toFixed(1);
})
.attr("x", function (d, i) {
return x(i) + x.rangeBand() / 2;
})
.attr("y", function (d) {
return height - y(d.max_energy) + 24;
});
});
});
HTML:
<p>CLICK ME</p>
<svg id="daychart"></svg>
对于问题的第二部分:
标签显示不正确,因为您只是使用selectAll("text")
来抓取它们。 这样做的问题是,轴上的刻度标签也是文本元素,因此它们被选中并分配了数据-但随后未包含在“输入”中。 这也是为什么在更新数据时轴标签会移出屏幕的原因(因为在这种情况下,您是在所有元素上设置属性,而不仅仅是新元素)。
解决方法:将一个类添加到条形标签,并使用它专门选择它们:
svg.selectAll("text.barLabels") //use this selector in your update as well
.data(data)
.enter()
.append("text")
.classed("barLabels", true) //remember to actually add the class!
现在应该都可以工作了...差不多。
您可能可以自己弄清楚这一点,但是标签的y定位功能没有考虑到您使用的是倒置比例尺这一事实,因此标签最终都处在怪异的位置。 您还需要更改
.attr("y", function (d) {
return height - y(d.max_energy) + 24;
});
至
.attr("y", function (d) {
return y(d.max_energy) + 24;
})
要么
.attr("y", function (d) {
return Math.min(y(d.max_energy) + 24, height);
})
这样“ 0.0”标签就不会超出轴线; 甚至
.attr("y", function (d,i) {
return Math.min(y(d.max_energy) + 24*(1+i%2), height);
})
因此,相邻标签如果对于条形而言太宽,则不会重叠。 ( i%2
仅对偶数返回0,对奇数返回1;取模运算符%
会从整数除法中返回“余数”。)
最后一个版本是我在此处实现的版本: http : //jsfiddle.net/h8Rsg/40/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.