Magnus Mudrack
Magnus Mudrack

Reputation: 43

Generate multiple random paths and animate circles along paths

I am attempting to animate 3 circles along 3 paths, these paths are randomly generated.Only two paths are generating and only one circle is animating along its allocated path. I have tried pairing the dataset and circle, this has no effect.

One of the paths seems to be blending two dataset's to generate a monster path. How do i stop this? How do i get each circle to its allocated path?

There is probably a more elegant way to do this.

var w = 2000, h = 2000;

var dataset1 = [] ;                        
    for (var i = 0; i < 5; i++) {            
          var x = Math.floor((Math.random()*900)+1); 
          var y = Math.floor((Math.random()*900)+1);  
          dataset1.push({"x":x, "y":y});
    };

var dataset2 = []  ;                       
    for (var i = 0; i < 4; i++) {            
          var x = Math.floor((Math.random()*700)+1); 
          var y = Math.floor((Math.random()*600)+1);  
          dataset2.push({"x":x, "y":y});
    };

var dataset3 = []  ;                       
    for (var i = 0; i < 3; i++) {            
          var x = Math.floor((Math.random()*800)+1); 
          var y = Math.floor((Math.random()*400)+1);  
          dataset2.push({"x":x, "y":y});
    };

var lineFunction = d3.svg.line()
        .x(function(d) { return d.x; })
        .y(function(d) { return d.y; })
        .interpolate  ("cardinal-closed")
        .tension(0)
        ;

var svg = d3.select("body").append("svg")
        .attr("width", w)
        .attr("height", h)
        ;


var path1 = svg.append("path")
        .datum( dataset1 )
        .attr("d", lineFunction)
        .attr("stroke", "black")
        .attr("stroke-width", 3)
        .attr("fill", "none")
        ;
var circle1 = svg.append("circle")
    .attr("r", 130)
    .attr("transform", "translate(" + [0] + ")")
    ;


var path2 = svg.append("path")
        .datum( dataset2 )
        .attr("d", lineFunction)
        .attr("stroke", "black")
        .attr("stroke-width", 3)
        .attr("fill", "none")
        ;

var circle2 = svg.append("circle")
    .attr("r", 30)
    .attr("transform", "translate(" + [0] + ")")
    ;

var path3 = svg.append("path")
        .datum( dataset2 )
        .attr("d", lineFunction)
        .attr("stroke", "black")
        .attr("stroke-width", 3)
        .attr("fill", "none")
        ;

var circle3 = svg.append("circle")
    .attr("r", 10)
    .attr("transform", "translate(" + [0] + ")")
    ;

transition();
function transition() {
  circle1.transition()
      .duration(10000)
      .attrTween("transform", translateAlong(path1.node()))
      .each("end", transition);
}


transition();
function transition() {
  circle2.transition()
      .duration(10000)
      .attrTween("transform", translateAlong(path2.node()))
      
}

transition();
function transition() {
  circle3.transition()
      .duration(10000)
      .attrTween("transform", translateAlong(path3.node()))
      
}

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

function translateAlong(path) {
  var l = path.getTotalLength();
  return function(d, i, a) {
    return function(t) {
      var p = path.getPointAtLength(t * l);
      return "translate(" + p.x + "," + p.y + ")";
    };
  };
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<style>

path {
  fill: none;
  stroke: red;
  stroke-width: 3px;
}

circle {
  fill: red;
  stroke: #fff;
  stroke-width: 3px;
  opacity: 0.7;

}

</style>

<script src="https://d3js.org/d3.v3.min.js"></script>

Upvotes: 3

Views: 968

Answers (2)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

You had 3 problems with your code:

  1. You were pushing dataset3 values into dataset2 array.
  2. You were using dataset2 array for painting path3 element.
  3. This is the most important problem: you had 3 functions with the same name. The last one simply overwrites the other ones. They should have different names. Alternatively, for DRY, write a general function and pass both the circle and the path as arguments.

Here is your code with those changes.

var w = 2000,
  h = 2000;

var dataset1 = [];
for (var i = 0; i < 5; i++) {
  var x = Math.floor((Math.random() * 900) + 1);
  var y = Math.floor((Math.random() * 900) + 1);
  dataset1.push({
    "x": x,
    "y": y
  });
};

var dataset2 = [];
for (var i = 0; i < 4; i++) {
  var x = Math.floor((Math.random() * 700) + 1);
  var y = Math.floor((Math.random() * 600) + 1);
  dataset2.push({
    "x": x,
    "y": y
  });
};

var dataset3 = [];
for (var i = 0; i < 3; i++) {
  var x = Math.floor((Math.random() * 800) + 1);
  var y = Math.floor((Math.random() * 400) + 1);
  dataset3.push({
    "x": x,
    "y": y
  });
};

var lineFunction = d3.svg.line()
  .x(function(d) {
    return d.x;
  })
  .y(function(d) {
    return d.y;
  })
  .interpolate("cardinal-closed")
  .tension(0);

var svg = d3.select("body").append("svg")
  .attr("width", w)
  .attr("height", h);


var path1 = svg.append("path")
  .datum(dataset1)
  .attr("d", lineFunction)
  .attr("stroke", "black")
  .attr("stroke-width", 3)
  .attr("fill", "none");
var circle1 = svg.append("circle")
  .attr("r", 130)
  .attr("transform", "translate(" + [0] + ")");


var path2 = svg.append("path")
  .datum(dataset2)
  .attr("d", lineFunction)
  .attr("stroke", "black")
  .attr("stroke-width", 3)
  .attr("fill", "none");

var circle2 = svg.append("circle")
  .attr("r", 30)
  .attr("transform", "translate(" + [0] + ")");

var path3 = svg.append("path")
  .datum(dataset3)
  .attr("d", lineFunction)
  .attr("stroke", "black")
  .attr("stroke-width", 3)
  .attr("fill", "none");

var circle3 = svg.append("circle")
  .attr("r", 10)
  .attr("fill", "blue")
  .attr("transform", "translate(" + [0] + ")");

transition();

function transition() {
  circle1.transition()
    .duration(10000)
    .attrTween("transform", translateAlong(path1.node()))
    .each("end", transition);
}


transition2();

function transition2() {
  circle2.transition()
    .duration(10000)
    .attrTween("transform", translateAlong(path2.node()))
    .each("end", transition2);

}

transition3();

function transition3() {
  circle3.transition()
    .duration(10000)
    .attrTween("transform", translateAlong(path3.node()))
    .each("end", transition3);

}

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

function translateAlong(path) {
  var l = path.getTotalLength();
  return function(d, i, a) {
    return function(t) {
      var p = path.getPointAtLength(t * l);
      return "translate(" + p.x + "," + p.y + ")";
    };
  };
}
path {
  fill: none;
  stroke: red;
  stroke-width: 3px;
}

circle {
  fill: red;
  stroke: #fff;
  stroke-width: 3px;
  opacity: 0.7;
}
<script src="https://d3js.org/d3.v3.min.js"></script>

Upvotes: 2

th3n3wguy
th3n3wguy

Reputation: 3737

First and foremost, you are likely having a problem with the code because you are redefining the same function. You have 3 different definitions for the transition() function (one for each of the circles). Once that code is fixed, then we can move on to the next problem.

Upvotes: 0

Related Questions