This example demonstrates how to use the getTotalLength and getPointAtLength methods on SVG path elements to interpolate a point along a Catmull–Rom spline.
A related technique is stroke dash interpolation.
forked from mbostock's block: Point-Along-Path Interpolation
forked from antonyross's block: Point-Along-Path Interpolation
forked from antonyross's block: Point-Along-Path Interpolation
forked from antonyross's block: Point-Along-Path Interpolation
forked from antonyross's block: Point-Along-Path Interpolation
forked from antonyross's block: Point-Along-Path Interpolation
forked from antonyross's block: Point-Along-Path Interpolation
forked from antonyross's block: Point-Along-Path Interpolation
xxxxxxxxxx
<meta charset="utf-8">
<body>
<style>
path {
fill: none;
stroke: #000;
stroke-width: 3px;
}
circle {
/*fill: steelblue; */
stroke: #fff;
stroke-width: 3px;
}
</style>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var points = [
[200, 200],
[500, 200],
[500, 400],
[200, 400],
];
var points2 = [
[100, 200],
[400, 200],
[400, 400],
[100, 400],
];
var w = 960;
var h = 500;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
// Text to show "stopwatch"
svg.append("text").text("hey").attr("x", 700).attr("y", 50)
/////////////// VECTOR ///////////////////////
class Vector
{
constructor(x,y)
{
this.x = x;
this.y = y;
}
limit(max)
{
var magnitude = this.magnitude();
if(magnitude > max)
{
this.normalize();
this.multiply(max);
}
}
normalize()
{
var magnitude = this.magnitude();
this.x/= magnitude;
this.y/= magnitude;
}
multiply(n)
{
this.x *= n;
this.y *= n;
}
add(v)
{
this.x += v.x;
this.y += v.y;
}
magnitude()
{
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
}
}
/////////////// RUNNER ///////////////////////
class Runner
{
constructor(r, color, path, coordinates)
{
this.r = r;
this.color = color;
this.path = path;
this.location = new Vector(coordinates[0], coordinates[1]);
this.velocity = new Vector(0, 0);//Math.random() * 5;
this.acceleration = new Vector(-.001, .01);
this.topspeed = 10;
}
get_random_color()
{
var colors = ["red", "green", "blue", "orange"]
var random_color = Math.floor(Math.random()*colors.length);
return colors[random_color];
}
checkEdges()
{
if(this.location.x > w)
{
this.location.x = 0;
}
else if(this.location.x < 0)
{
this.location.x = w;
}
if(this.location.y > h)
{
this.location.y = 0;
}
else if(this.location.y < 0)
{
this.location.y = h;
}
}
update()
{
this.velocity.add(this.acceleration);
this.velocity.limit(this.topspeed);
this.location.add(this.velocity);
}
}
///////////////////////////////////////////////
var dataset = [];
var path = svg.append("path")
.data([points])
.attr("d", d3.svg.line()
.tension(0) // Catmull–Rom
.interpolate("cardinal-closed"));
var path2 = svg.append("path")
.data([points2])
.attr("d", d3.svg.line()
.tension(0) // Catmull–Rom
.interpolate("cardinal-closed"));
d3.select("svg").on("click", function()
{
// get the mouse position coordinates
var coordinates = [0, 0];
coordinates = d3.mouse(this);
dataset.push(new Runners(15, "blue", 1, coordinates));
var circles = svg.selectAll("circle") //Select all circles
.data(dataset);
circles.enter()
.append("circle")
.attr({cx:0, cy:0, fill: function(d){return d.get_random_color()}})
.attr("r", function(d){return d.r})
//.transition()
//.duration(2000)
//.attr("transform", translator()); //"translate(" + points[0] + ")")
//.each("end", transition);
transition();
function transition()
{
circles.transition()
.duration(10000)
//.attrTween("transform", translateAlong(path.node(),path2.node()))
.attrTween("transform", mover())
.each("end", transition);
}
/*
// Returns an attrTween for translating along the specified path element.
function translateAlong(path1, path2)
{
var length_1 = path1.getTotalLength();
var length_2 = path2.getTotalLength();
return function(d, i, a)
{
return function(t)
{
var p1 = path1.getPointAtLength(t * length_1);
var p2 = path2.getPointAtLength(t * length_2);
svg.select("text").text(Math.floor(t * 100))
if (t < .3)
{
p = p2
}
else
{
p = p1
}
return "translate(" + p.x + "," + p.y + ")";
};
};
}
*/
function mover()
{
return function(d, i, a)
{
return function(t)
{
svg.select("text").text(Math.floor(t * 100))
d.checkEdges(); // make sure objects remain on screen; bounce back
d.update(); // update the object's position
// return the updated translated position
return "translate(" + d.location.x + "," + d.location.y + ")";
};
};
}
});
</script>
https://d3js.org/d3.v3.min.js