我只是从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 = [];
剩下的步骤将在“类型”函数中(或同时)解析完数据后执行。在传递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]};
}
不幸的是,这将返回未定义的变量,因此,如果您控制台记录emptyData [0] .value(请注意:数据是对象的数组,而不仅仅是数组。这就是csv的解释方式,因此这就是我们构建代码的方式)空数组),您将获得“未定义”。为了解决这个问题,您必须传递一个if语句,该语句将所有“未定义”都转换为0。该代码如下所示:
for(i = 0;i<emptyData.length;i++){
if(emptyData[i].value === undefined){
emptyData[i].value = 0;
}
}
如果按顺序完成,您将拥有一个EmptyData集(其中所有值均为0),与初始导入的csv数据集一样长。
现在您拥有一组空数据,您可以告诉D3根据空白数据创建条形图。要伪造此问题的“ onload”部分,您可以通过在文档的整个主体上设置on“ mouseover”事件,来设置第二个实际数据以加载正确的图表。从这个意义上讲,从技术上讲没有onload设置,但是就像图表随着页面加载而转变一样会出现。
为此,首先使用现有代码创建图表,然后传递emptyData:
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数据)创建mouseover事件。看起来像这样:
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事件。希望对您有用。要使其正常工作,可能需要一些技巧。重要的是要记住如何传递空数据。使它在我端发挥作用仅是成功的一半。