d3.js - 未捕获的TypeError:对象没有方法'exit'

时间:2012-12-12 04:10:23

标签: javascript d3.js

我试图通过更改我提供给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);
 }

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

我收到错误:未捕获TypeError:对象没有方法'退出

我做错了什么?

1 个答案:

答案 0 :(得分:18)

实际上,您遇到了与此代码相关的一些问题。当您致电changingLines时,唯一会更新其属性的元素是enter选项中的元素(调用.enter()会返回enter选项)。

请记住,默认情况下,如果您传入数组中的新元素,.data()只会向enter选项添加元素,例如。

// 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来电计算的联接,并使用它来单独访问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

  

在追加时,回车选择会合并到更新选择中   或者插入。这种方法减少了输入和输入之间的代码重复   更新。而不是将运算符应用于输入和更新   单独选择,您现在可以将它们应用于更新选择   进入节点后。在极少数情况下你想运行   只有更新节点上的运算符,您可以在更新时运行它们   在输入新节点之前进行选择。

这也应解决您无法拨打exit()的问题。当您第二次调用lines.selectAll("line")时,您创建了一个新选择,因此您无法访问上一次加入时计算的选择。

阅读并重读这篇文章:http://bost.ocks.org/mike/join/