使用计时器更新d3生成的圆圈的位置

时间:2017-05-28 17:16:46

标签: javascript asp.net-mvc d3.js

我是d3的新手并且对javascript很新,遇到了一个我无法用现有知识解释的错误......

我使用2d数组(成功)生成了6个圆圈,并创建了一个函数来调用计时器,以便在每次调用时将x和y位置递增1。目前我的代码生成了6个圆圈但是计时器无限创建了更多的“NaN”圆圈,而不是更新了初始6的位置。我的代码在下面;

<body>
    <div id="svgDiv"></div>

    <script src="~/scripts/d3/d3.min.js"></script>
    <script src="~/scripts/App/test.js"></script>

</body>

和js;

var windowWidth = window.innerWidth;
var windowLength = window.innerHeight;

var pos =
    [[50, 40],
    [100, 80],
    [150, 120],
    [200, 160],
    [250, 200],
    [300, 240]];

var base = d3.select("#svgDiv").append("svg")
  .attr("width", windowWidth)
  .attr("height", windowLength);

function initSetup() {

    windowWidth = window.innerWidth;;
    windowLength = window.innerHeight;

    base.attr("width", windowWidth)
        .attr("height", windowLength);

    document.body.style.overflow = 'hidden';
}
window.onload = initSetup;

function windowResize() {

    windowWidth = window.innerWidth;;
    windowLength = window.innerHeight;
    base.attr("width", windowWidth)
       .attr("height", windowLength);

};
window.addEventListener("resize", windowResize);

function svgDivClick() {

    base.selectAll("circle")
        .data(pos) // .data(pos, function (d) { return d; })
        .enter()
        .append("circle")
        .attr("cx", function (d, i) {
            return pos[i][0];
        })
        .attr("cy", function (d, i) {
            return pos[i][1];
        })
        .attr("r", 0)
        .style("fill", "00ACCD")
        .transition()
        .attr("r", 20)
        .style("fill", "00ACCD")
        .duration(500);

    base.exit().transition()
        .attr("r", 0)
        .remove();

    console.log("click works");
    d3.timer(animate);
};
document.getElementById("svgDiv").addEventListener("click", svgDivClick);

function animate() {

    base.selectAll("circle")
        .data("circle", function (d) { return d; })
        .enter()
        .append("circle")
        .attr("cx", function (d, i) {
            return d.cx + 1;
        })
        .attr("cy", function (d, i) {
            return d.cy + 1;
    });

    base.exit().transition()
        .attr("r", 0)
        .remove();
};

最终目标是让圈子随机漂浮,但此时我只是试图控制位置。编辑:动画功能发生错误。

任何见解都会很棒,提前谢谢!

1 个答案:

答案 0 :(得分:2)

这里有一些问题。主要的一点是你每秒60次将相同的数据绑定到DOM元素,这没有任何意义。第二个是你不是增加位置,而只是重置它们。第三个是数据中没有cxcy属性。最后一个是你没有声明你的圈子的选择。

我做了一个简单的演示,向您展示如何使用d3.timer。检查如何检索和更改位置。此外,请记住,在此示例中,我删除了所有转换:混合转换和计时器很复杂,而且通常是不必要的。

以下是演示:

var windowWidth = 500;
var windowLength = 300;

var pos = [
  [50, 40],
  [100, 80],
  [150, 120],
  [200, 160],
  [250, 200],
  [300, 240]
];

var base = d3.select("body").append("svg")
  .attr("width", windowWidth)
  .attr("height", windowLength);

var circles = base.selectAll("charlesDarwin")
  .data(pos)
  .enter()
  .append("circle")
  .attr("cx", function(d, i) {
    return pos[i][0];
  })
  .attr("cy", function(d, i) {
    return pos[i][1];
  })
  .attr("r", 20)
  .style("fill", "00ACCD");

var timer = d3.timer(animate);

function animate() {

  circles.attr("cx", function() {
    if (+d3.select(this).attr("cx") > 500) {
      timer.stop()
    }
    return +d3.select(this).attr("cx") + 1
  });
};
<script src="https://d3js.org/d3.v4.min.js"></script>