javascript - 递归函数和这个 D3.JS

标签 javascript d3.js recursion

我有一个包含 point={x,y,nextPoint} 的点数组。目的是在每个点之间画一条线并在其上移动一个圆圈。数组中最后一个点的 nextPoint 为 null。

我能够通过在点上调用 [number of points]-1 方法来移动圆圈。这一点都不灵活,我想递归地做。我正在创建一个这样的圆圈:

function addCercle() {
  var ret = svg.append("circle") //svg is declared before
    .attr("cx", points[0].x) // points = the array of points
    .attr("cy", points[0].y)
    .attr("r", "3%");
  return ret;
}

不起作用的函数是这样的:

function move(p) {
  for (var i = 0; i < points.length-1; i++) {
    p = d3.select(this)
      .transition()
      .duration(speed) //
      .attr("cx", points[i].x)
      .attr("cy", points[i].y);
  }
}

我想这样调用它以使圆在所有线上运行:

var test = addCercle();
console.log(test);
move(test);

有人可以解释一下我在函数移动中必须更改的内容吗?还是在通话中?

最佳答案

如果你想让你的move函数递归,你需要从它自身内部调用它。一如既往,有很多方法可以做到这一点,但如果你有一个点数组,你可以传入点数组,或者传入点数组中的当前位置。以下是您传入点数组的示例:

// p is the element being moved, points is the array of points
function move(p, points) {
  if (points.length > 0) { // one point or more in the array => move the element
    p.transition()
      .duration(speed) //
      .attr("cx", points[0].x)
      .attr("cy", points[0].y)
      // when the transition ends, call this function with the array of points minus the first point
      .on('end', () => move(p, points.slice(1)));
  }
}

const arrayOfPoints = [{x: 100, y: 200},{x: 200, y: 200}, {x: 300, y: 300}]
// call the function
move(circle, arrayOfPoints);

工作示例,我生成了一个点数组,然后沿着这些点描述的路径移动了一个圆:

var svg = d3.select('svg'),
radius = 100,
pts = d3.range(0, 2 * Math.PI, 0.01 * Math.PI) // NOTE: this produces an array
        .map( d => d3.pointRadial(d, radius) ),// of arrays; slightly different
                                               // to your data structure
speed = 50

function addCercle(points) {
  var ret = svg
    .append('g')
    .attr('transform', 'translate(150,150)')
    .append("circle") //svg is declared before
    .attr("cx", points[0][0]) // points = the array of points
    .attr("cy", points[0][1])
    .attr("r", "3%");
  return ret;
}

function move(p, points) {
  if (points.length > 0) {
    p.transition()
      .duration(speed) //
      .attr("cx", points[0][0])
      .attr("cy", points[0][1])
      .on('end', () => move(p, points.slice(1)));
  }
}

var test = addCercle(pts);
move(test, pts);
<script type="text/javascript" src="http://d3js.org/d3.v5.js"></script>
<svg width="960" height="960"></svg>

您可以通过补间过渡产生更平滑的路径和动画。

这是一个略有改动的示例,它遵循相同的原则,但使用您在问题中描述的数据结构;所有改变的是函数设置 cxcy 值的方式,以及它如何决定是否有更多的点要显示。

var svg = d3.select('svg'),
radius = 300,
pts = d3.range(0, 2 * Math.PI, 0.01 * Math.PI).map( d => d3.pointRadial(d, radius) ),
speed = 50

function makeWeirdDataStructure ( pts ) {
  return {
    x: pts[0][0],
    y: pts[0][1],
    nextPt: pts.length > 1 ? makeWeirdDataStructure( pts.slice(1) ) : null
  }
}

function addCercle(points) {
  var ret = svg
    .append('g')
    .attr('transform', 'translate(400,400)')
    .append("circle") //svg is declared before
    .attr("cx", points.x) // points = the array of points
    .attr("cy", points.y)
    .attr("r", "3%");
  return ret;
}

function move(p, points) {
  if ( points !== null ) {
    p.transition()
      .duration(speed) //
      .attr("cx", points.x)
      .attr("cy", points.y)
      .on('end', () => move(p, points.nextPt));
  }
}

var wds = makeWeirdDataStructure(pts)
var test = addCercle(wds);
move(test, wds);
<script type="text/javascript" src="http://d3js.org/d3.v5.js"></script>
<svg width="960" height="960"></svg>

关于javascript - 递归函数和这个 D3.JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52891619/

相关文章:

javascript - 使用 Node JS 调度应用程序

javascript - D3 中的饼图( donut )图段顺序

c++ - 迭代深化搜索应该那么慢吗?

c - 如何在递归中传递前一个参数

javascript - Typescript - 不同文件中的模块函数引用 - "could not find symbol"

javascript - jQuery 重新加载 MySQL 输出(浏览器问题)

javascript - 将垂直线添加到 d3js 条形图

r - 检测递归函数 (R) 中的无限循环

javascript - 删除div标签+ jquery下的类属性

javascript - 在旧图表上方添加新的 D3 图表