我刚刚开始使用 D3,我正在尝试创建一个简单的条形图,该条形图在加载时会进行转换。我尝试在代码中的每个选择和属性更改之间添加 .transition() ,它使整个视觉效果消失。这是我的代码的全部内容:
<style>
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
<svg class="chart"></svg>
<script src="js/d3.min.js"></script>
<script>
var width = 1000,
barHeight = 20;
var x = d3.scale.linear()
.range([0, width]);
var chart = d3.select(".chart")
.attr("width", width);
d3.csv("data2.csv", type, function(error, data) {
x.domain([0, d3.max(data, function(d) { return d.value; })]);
chart.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("width", function(d) { return x(d.value); })
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) { return x(d.value) - 3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d.value; });
});
function type(d) {
d.value = +d.value; // coerce to number
return d;
}
</script>
不太确定这是否是我的代码的一个更根本的问题,但是我读过的每一个资源都使得添加 .transition() 看起来应该是一个容易进行的更改,而且我还没有发现这是最重要的案件。如有任何答案,我们将不胜感激。
最佳答案
我可能有一个解决方案。这可能更像是一种解决方法;我对此也很陌生,这只是一个对我有用的解决方案。
我找到的解决方案是拥有两组数据。您需要做的是创建一组空白数据 - 具有相同长度值的数据,但将它们全部设置为 0 - 首先渲染。因此创建一个全局变量,如下所示:
//create before passing data
var emptyVar = 0;
D3 以对象数组的形式返回数据。因此,您还需要创建一个空数组:
var emptyData = [];
一旦数据在“type”函数(或 while)中被解析,剩下的步骤就会发生。在传递 csv 的代码中,您必须使用空变量填充空数据集。为此,您将创建一个 for() 语句并将导入的数据作为emptyData 的长度传递。这样,您的emptyData将填充与导入数据中的变量一样多的emptyVar。你这样做:
d3.csv("data2.csv", type, function(error, data) {
x.domain([0, d3.max(data, function(d) { return d.value; })]);
for(var i = 0;i<data.length;i++){
emptyData[i] = {value:empty[i]};
}
不幸的是,这将返回 undefined variable ,因此如果您控制台记录emptyData[0].value(注意:数据是一个对象数组,而不仅仅是一个数组。这就是 csv 的解释方式,所以这就是我们的方式正在构建我们的空数组)你会得到“未定义”。为了解决这个问题,您必须传递一个 if 语句,将所有“未定义”转换为 0。该代码如下所示:
for(i = 0;i<emptyData.length;i++){
if(emptyData[i].value === undefined){
emptyData[i].value = 0;
}
}
如果按顺序完成,您将得到一个空数据集(其中所有值均为 0),该数据集与您初始导入的 csv 数据集一样长。
现在您有了一组空数据,您可以告诉 D3 根据空白数据创建条形图。要伪造此问题的“onload”部分,您可以通过为文档的整个正文设置“mouseover”事件来设置第二个实际数据来加载正确的图表。从这个意义上说,技术上没有加载集,但它看起来就像图表随着页面加载而转换一样。
为此,首先使用现有代码创建图表,但传递空数据:
chart.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(emptyData)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("width", function(d) { return x(d.value); })
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) { return x(d.value) - 3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d.value; });
这将根据您的空数据创建一个图表。现在,使用传递的实际数据(csv 数据)创建鼠标悬停事件。看起来像这样:
d3.select("body")
.on("mouseover",function (){
chart.selectAll(".bar")
.data(data)
.transition()
.duration(500)
.ease("linear")
//the attributes you'd like to change are listed below
.attr("fill","#5489c7")
.attr("width", function(d) { return x(d.value); })
.attr("height", barHeight - 1);
//change the text attributes as well within here
...
//close off the function when you're finished
});
应该是这样。它并不完全像您所要求的那样是一个 onload 事件,但它应该足以伪造它,使其看起来像一个 onload 事件。希望这对你有用。可能需要一些技巧才能让它发挥作用;重要的是记住如何传递空数据。让它在我这边工作就成功了一半。
关于javascript - 加载时 D3 中的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29978957/