Come posso restituire la coordinata di un percorso in d3.js?

Ho un grafico e voglio che la linea che rappresenta il grafico mostri un cerchio alla coordinata x quando passi sopra l’area svg. Questo cerchio dovrebbe seguire il percorso della linea che rappresenta la curva. Il problema è che non so come farlo.

Il codice seguente mostra fino a che punto sono riuscito e aggiunge effettivamente un cerchio al documento con la coordinata x corretta. Ora, con cosa sostituisco il punto interrogativo?

svg.on("mousemove", function() { d3.select("path.line") .style("stroke-width", "2.5px"); svg.append("svg:circle") .attr("cx", Math.floor(event.offsetX-m[1])) .attr("cy", ?) .attr("r", "10") .attr("fill", "red"); }); 

SVG fornisce una funzione nativa chiamata .getPointAtLength() che restituisce i valori xey di un percorso a qualsiasi lunghezza passata.

Dovresti scorrere la lunghezza della linea fino a trovare la posizione y corrispondente. Ecco come lo faresti in 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); }); 

Puoi vedere una demo qui: http://bl.ocks.org/3824661