D3更新模式两次绘制相同的元素

时间:2017-11-01 10:26:26

标签: javascript d3.js

我在D3中创建了一个折线图。为了确保线不与y轴重叠,我改变了x轴的范围。因此,x轴和y轴之间存在间隙,我试图用另一条线填充。

图表的其余部分使用D3更新模式。但是,当我尝试在这条简单的线条上使用图案时,会绘制两个路径元素(一个在另一个上面)。我已经尝试了许多解决方案来纠正这个问题,但我没有运气。有没有人有任何建议?

下面的代码是绘制两个相同的路径元素

var xAxisLineData = [
    { x: margins.left     , y: height - margins.bottom + 0.5 },
    { x: margins.left + 40, y: height - margins.bottom + 0.5 }];

var xAxisLine = d3.line()
                .x(function (d) { return d.x; })
                .y(function (d) { return d.y; });

    var update = vis.selectAll(".xAxisLine")
                 .data(xAxisLineData);

    var enter = update.enter()
                .append("path")
                .attr("d", xAxisLine(xAxisLineData))
                .attr("class", "xAxisLine")
                .attr("stroke", "black");

1 个答案:

答案 0 :(得分:1)

你的问题在这里:

var update = vis.selectAll(".xAxisLine")
             .data(xAxisLineData);

这是一个空选择,假设没有类xAxisLine的元素,这意味着使用.enter().append()将为xAxisLineData数组中的每个项附加一个元素。

您希望为表示一条线的每组点附加一条路径,而不是在表示一条线的一组点中为每条点添加一条路径。

你真的只想绘制一条线,所以你可以这样做:

.data([xAxisLineData]);

或者,在定义xAxisLineData

时将所有点放在数组中

现在您将数据数组传递给包含一个项目的选择:一个点数组 - 而不是代表各个点的许多项目。由于数据数组有一个项目,并且您的选择为空,因此使用.enter().append()将附加一个元素:



var svg = d3.select("body").append("svg").attr("width",500).attr("height",400);

var lineData = [{x:100,y:100},{x:200,y:200}]

var xAxisLine = d3.line()
                .x(function (d) { return d.x; })
                .y(function (d) { return d.y; });
                
var colors = ["steelblue","orange"];
  
var line = svg.selectAll(null)
  .data([lineData])
  .enter()
  .append("path")
  .attr("d", xAxisLine(lineData))
  .attr("class", "xAxisLine")
  .attr("stroke-width", function(d,i) { return (1-i) * 10 + 10; })
  .attr("stroke", function(d,i) { return colors[i]; });

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
&#13;
&#13;
&#13;

比较而不使用数组来保存所有数据点:

&#13;
&#13;
var svg = d3.select("body").append("svg").attr("width",500).attr("height",400);

var lineData = [{x:100,y:100},{x:200,y:200}]

var xAxisLine = d3.line()
                .x(function (d) { return d.x; })
                .y(function (d) { return d.y; });
                
var colors = ["steelblue","orange"];
  
var line = svg.selectAll(null)
  .data(lineData)
  .enter()
  .append("path")
  .attr("d", xAxisLine(lineData))
  .attr("class", "xAxisLine")
  .attr("stroke-width", function(d,i) { return (1-i) * 10 + 10; })
  .attr("stroke", function(d,i) { return colors[i]; });
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
&#13;
&#13;
&#13;

但是,我们可以做出最后的改变。由于数据数组中的每个项都绑定到元素,因此我们可以引用数据,而不是数据数组xAxisLineData,这将使得添加多行变得更加容易:

.attr("d", function(d) { return xAxisLine(d) })

请注意,在下面的演示中,变量xAxisLineData被定义为点数组数组或多行数组。

&#13;
&#13;
var svg = d3.select("body").append("svg").attr("width",500).attr("height",400);

var lineData = [[{x:100,y:100},{x:200,y:200}],[{x:150,y:150},{x:260,y:150}]]

var xAxisLine = d3.line()
                .x(function (d) { return d.x; })
                .y(function (d) { return d.y; });
                
var colors = ["steelblue","orange"];
  
var line = svg.selectAll(null)
  .data(lineData)
  .enter()
  .append("path")
  .attr("d", function(d) { return xAxisLine(d) }) // use the element's datum 
  .attr("class", "xAxisLine")
  .attr("stroke-width", function(d,i) { return (1-i) * 10 + 10; })
  .attr("stroke", function(d,i) { return colors[i]; });
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
&#13;
&#13;
&#13;