Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
106
rated 0 times [  107] [ 1]  / answers: 1 / hits: 23135  / 12 Years ago, fri, september 14, 2012, 12:00:00

I have a graph, and I want the line representing the graph to show a circle at the x coordinate when hovering on top of the svg area. This circle should follow the path of the line that represents the curve. The problem is that I don't know how to do this.



The code below shows how far I have succeded, and it indeed adds a circle to the document at the right x coordinate. Now, what do I replace the question mark with?



    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);
});

More From » svg

 Answers
65

SVG provides a native function called .getPointAtLength() which returns a the x and y values of a path at any length you pass at it.



You would need to iterate through the length of the line until you find the corresponding y position. Here is how you would do it 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);
});


You can see a demo here: http://bl.ocks.org/3824661


[#83078] Wednesday, September 12, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
adam

Total Points: 363
Total Questions: 102
Total Answers: 104

Location: Burkina Faso
Member since Thu, Dec 15, 2022
2 Years ago
;