d3.js - 未捕获的类型错误:对象没有“exit”方法

3
我将尝试通过更改我提供给d3线函数的lineData数组,在每5秒钟之后绘制一系列线条:
以下是相关代码摘录:
var svg = d3.select("body").append("svg:svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .attr("id", "svgMain")
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .call(drag);

var lines = svg.append("g")
      .attr("id", "lines");

function changingLines() {
      lines.selectAll("line")
        .data(lineData)
        .enter().append("line")
        .attr("x1", function(d, i) { console.log(d[0][0]); return d[0][0];})
        .attr("y1", function(d, i) { console.log(d[0][1]); return d[0][1];})
        .attr("x2", function(d, i) { return d[1][0];})
        .attr("y2", function(d, i) { return d[1][1];})
        .style("stroke", "#000")
        .style("stroke-width", "0.5")
        .attr("class", "lines");

     lines.selectAll("line").exit().remove();
     setTimeout(changingLines, 2000);
 }

我每2秒钟使用不同的lineData数组值调用一次changingLines()函数。

我收到了错误信息:未捕获的类型错误:Object没有exit方法

我做错了什么?

1个回答

18

实际上,这段代码存在几个相关的问题。当你调用 changingLines 时,只有在 enter selection 中的元素才会更新其属性(调用 .enter() 将返回 enter selection)。

记住,默认情况下,.data() 仅在传递给它的数组中有新元素时将元素添加到 enter selection 中,例如:

// Old data array:
var data = [1, 2, 3, 4];

// New data array:
var newData = [5, 6, 7, 8, 9];

/*
The first 4 elements in newData will replace the first 4 elements of oldData.
The number of new elements (which will be in the enter() selection) is only 1.
*/
你需要做的是保存由data调用计算得出的 join,然后使用它来单独访问enterexitupdate选择。
var linesContainer = svg.append("g").attr("id", "lines");

function changingLines() {

    /* Compute the data join */
    var lines = linesContainer.selectAll("line").data(lineData);

    /* Enter */
    lines.enter().append("line");

    /* Exit */
    lines.exit().remove();

    /* Update */
    lines
         .attr("x1", function(d, i) { console.log(d[0][0]); return d[0][0];})
         .attr("y1", function(d, i) { console.log(d[0][1]); return d[0][1];})
         .attr("x2", function(d, i) { return d[1][0];})
         .attr("y2", function(d, i) { return d[1][1];})
         .style("stroke", "#000")
         .style("stroke-width", "0.5")
         .attr("class", "lines");

    setTimeout(changingLines, 2000);
}

在更新属性和样式之前,这将删除旧的line元素并添加新的line元素。

https://github.com/mbostock/d3/wiki/Selections#wiki-enter

当您附加或插入时,enter选择将合并到update选择中。这种方法减少了enter和update之间的代码重复。您现在可以将运算符应用于进入节点后的更新选择,而不是分别应用于enter和update选择。在极少数情况下,如果您只想在更新节点上运行运算符,则可以在输入新节点之前在更新选择上运行它们。

这也应该解决您无法调用exit()的问题。 当您第二次调用lines.selectAll("line")时,您正在创建一个新的选择,因此您将无法访问先前连接时计算的选择。

阅读并重新阅读本文:http://bost.ocks.org/mike/join/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接