简体   繁体   中英

How to animate multiple circles on a path in d3.js?

Im trying to take this as reference https://bl.ocks.org/mbostock/1705868 .

I want to rotate multiple circle as points instead of single circle rotating above infinitely.

          function translateAlong(path) {
            var l = path.getTotalLength();
            return function(i) {
              return function(t) {
                var p = path.getPointAtLength(t * l);
                return "translate(" + p.x + "," + p.y + ")";//Move marker
              }
            }
          }

I initially plotted all the required points on path as https://jsfiddle.net/tzbd9r1f/2/

Im facing two problems here :

1 : When I try to animate all the circles I see only one circle animating and not 5 circles as here https://jsfiddle.net/tzbd9r1f/1/ .

2 : If I try to call end transition for all 5 circle I get maximum stack error in case making this as infinitely rotating as here https://jsfiddle.net/tzbd9r1f/3/

Please guide.

The basic problem in your code is that you apply the same translation for all your points simultaneously. Actually all your circles are moving along the path, but they cover each other - so you've already done the major part of the task. However, if you would like different circles to be at different coordinates, you have to apply different tweens for them. That is, even if you calculated startPoints to be different for each circle, you don't use that later in the animation, so all the circles are moving together.

I solved this with adding the index of the point as a new parameter to the translateAlong function, and calculating the position of the circles with some basic math, so it becomes:

function translateAlong(path,ind) {
  var l = path.getTotalLength();
  return function(i) {
    return function(t) {
      var p = path.getPointAtLength(((t+ind/5)%1)* l);
      return "translate(" + p.x + "," + p.y + ")";//Move marker
    }
  }
}

Of course this also needs the function calls to be changed, and if you also want to circles to infinitely go along the path there is a small issue here, as when we pass the function as a parameter, it needs a partial function application .

All in all, transitionAll changes in the following way (I also added linear easing to have a more regular moving speed for the circles):

function transitionAll(marker,ind){
  console.log(marker);
  marker.transition()
    .duration(7500).ease("linear")
    .attrTween("transform", translateAlong(path.node(),ind))
    .each("end", partial(transitionAll,marker,ind));// infinite loop*/

And the new partial function is copied from the post I have linked:

function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
}              

Also don't forget to change the call of the transitionAll function in your forEach -loop over startPoints .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM