グラフがあり、グラフを表す線に、svg領域の上にカーソルを置いたときに、x座標に円が表示されるようにしたいと思います。この円は、曲線を表す線のパスをたどる必要があります。問題は、これを行う方法がわからないことです。
以下のコードは、私がどれだけ成功したかを示しており、実際にドキュメントの右のx座標に円が追加されています。では、疑問符を何に置き換えればよいですか?
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は、.getPointAtLength()
と呼ばれるネイティブ関数を提供します。これは、パスのx値とy値を、渡された長さで返します。
対応するy位置が見つかるまで、線の長さを反復処理する必要があります。 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);
});
ここでデモを見ることができます: http://bl.ocks.org/3824661