SVG proporciona una función nativa llamada .getPointAtLength()
el que devuelve un valores X e Y de un camino en cualquier longitud que pasa en ella.
Debería iterar a lo largo de la línea hasta encontrar la posición y correspondiente. Esta es la manera que lo haría en D3:
var svg = d3.select("#line").append("svg")
var path =
svg.append("path")
.attr("d", "M0,168L28,95.99999999999997L56,192L84,71.99999999999997L112,120L140,192L168,240L196,168L224,48L252,24L280,192L308,120L336,24L364,168L392,95.99999999999997L420,168L448,95.99999999999997L476,192L504,71.99999999999997L532,120L560,192L588,216L616,168L644,48L672,24L700,192L728,120L756,24L784,192L812,71.99999999999997")
.attr("fill", "none")
.attr("stroke", "black");
var circle =
svg.append("circle")
.attr("cx", 100)
.attr("cy", 350)
.attr("r", 3)
.attr("fill", "red");
var pathEl = path.node();
var pathLength = pathEl.getTotalLength();
var BBox = pathEl.getBBox();
var scale = pathLength/BBox.width;
var offsetLeft = document.getElementById("line").offsetLeft;
var randomizeButton = d3.select("button");
svg.on("mousemove", function() {
var x = d3.event.pageX - offsetLeft;
var beginning = x, end = pathLength, target;
while (true) {
target = Math.floor((beginning + end)/2);
pos = pathEl.getPointAtLength(target);
if ((target === end || target === beginning) && pos.x !== x) {
break;
}
if (pos.x > x) end = target;
else if (pos.x < x) beginning = target;
else break; //position found
}
circle
.attr("opacity", 1)
.attr("cx", x)
.attr("cy", pos.y);
});
Se puede ver una demo aquí: http://bl.ocks.org/3824661
estoy bastante seguro de que esto no funcionará para las formas de trazado arbitrario de estilo línea de tiempo, por ejemplo, una línea con una punta muy filosa en un punto no permitirá una interpolación lineal entre la longitud del camino y la posición x. – nrabinowitz
@nrabinowitz es lo suficientemente simple para probar http://jsfiddle.net/FPfFJ/ y sí, no está del todo allí. – Duopixel
Sí, creo que la única forma de usar '.getPointAtLength()' para obtener un punto preciso en este caso es buscar a lo largo de la línea hasta que encuentre un punto con un valor 'x' próximo a' d3.event.pageX' . – nrabinowitz