我有一个包含 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>
您可以通过补间过渡产生更平滑的路径和动画。
这是一个略有改动的示例,它遵循相同的原则,但使用您在问题中描述的数据结构;所有改变的是函数设置 cx
和 cy
值的方式,以及它如何决定是否有更多的点要显示。
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/