Quantcast
Viewing all articles
Browse latest Browse all 42

Answer by i alarmed alien for Recursive function and this D3.JS

If you want to make your move function recursive, you need to call it from within itself. As always, there are numerous ways to do it, but if you have an array of points, you could either pass in the array of points, or pass in the current position in the array of points. Here is an example where you pass in an array of points:

// p is the element being moved, points is the array of pointsfunction 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 functionmove(circle, arrayOfPoints);

Working example where I've generated an array of points and then moved a circle along the path described by those points:

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 structurespeed = 50function 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>

You can produce smoother paths and animations by tweening the transitions.

Here's a slightly altered example that follows the same principles but uses the data structure you describe in your question; all that has changed is the way that the function sets the cx and cy values and how it decides whether or not there are more points to display.

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 = 50function 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>

Viewing all articles
Browse latest Browse all 42

Trending Articles