Calculate SVG path length to a specified point
Answer to SO question: http://stackoverflow.com/questions/28797761/in-d3-js-is-there-any-way-to-get-the-path-length-at-particular-point
We draw a new sub-path to calculate the length to a point part way along the full path
HTML
<div id="canvas"></div>
CSS
.fullpath {
stroke: black;
stroke-width: 1;
fill: none;
}
.subpath {
stroke: red;
stroke-width: 4;
fill: none;
opacity:0.5;
}
body {
font: 12px Arial;
fill: black;
}
JavaScript
var w = 900,
h = 400;
var svg = d3.select("#canvas")
.append("svg")
.attr("width", w)
.attr("height", h)
.attr("id", "visualization");
var subPathData = [
[]
];
var pathData = [
[{
"x": 0,
"y": 0
}, {
"x": 100,
"y": 150
}, {
"x": 200,
"y": 70
}, {
"x": 300,
"y": 90
}, {
"x": 450,
"y": 200
}]
];
var textData = [{
"pathlength": 0,
"x": 0,
"y": 0
}];
var line = d3.svg.line()
.x(function(d) {
return d.x;
})
.y(function(d) {
return d.y;
})
//.interpolate("monotone");
.interpolate("none");
var group = svg.append("g");
updateSubPath(subPathData);
group.selectAll(".fullpath")
.data(pathData)
.enter()
.append("path")
.attr("d", line)
.attr("class", "fullpath")
.on("mousemove", mousemoved);
updateText(textData);
// On mousemove, get the mouseover point coords, and then draw an new path (sub-path)
// that follows the existing path (full path) up to and including the new point
function mousemoved() {
var m = d3.mouse(this);
mouse_coord = {
"x": m[0],
"y": m[1]
}
subPathData = [
[]
];
for (var i = 0; i < pathData[0].length; i++) {
var coord = pathData[0][i];
if ((coord.x <= mouse_coord.x)) {
subPathData[0].push(coord);
}
}
subPathData[0].push(mouse_coord);
updateSubPath(subPathData);
// Calculate the length of the subpath - this will be line length
// up to the point we're mouseover-ing
subpath_length = d3.select(".subpath")[0][0].getTotalLength();
// Calculate the new info for text fields
textData = [{
"pathlength": subpath_length,
"x": mouse_coord.x,
"y": mouse_coord.y
}];
updateText(textData);
};
function updateSubPath(data) {
// JOIN
var subpathselect = group.selectAll(".subpath")
...