Hey, I’m again after an extended illness.
My subsequent process is to attract a vertical line wherever the mouse is, when this line hits a knowledge level of a graph it reveals the tooltip. I already found that it’s important to use bisector for that, so will attempt one thing and get again to this subject if I’m caught.
So I’m making an attempt so as to add a line that strikes with the mouse and improve the tooltip.
Utilizing code from right here:
https://vizartpandey.com/line-chart-how-to-show-data-on-mouseover-using-d3-js/
Have to make use of invert and bisect in some way, my case is extra difficult than these examples given.
I assumed I’ve outlined circle but it surely says circle not outlined.
A bit like right here:
https://stackoverflow.com/questions/53595181/how-do-i-have-a-line-follow-the-mouse-on-hover-but-also-have-zoom-in-chart
https://jsfiddle.net/zkdxrtuc/8/
I copied this code 1:1 into my editor (upgraded to d3.v5) and each packages give me error messages.
Uncaught TypeError: Can’t learn properties of undefined (studying ‘scale’) at Bisect.html:45:22
Bisect2.html:100 Uncaught TypeError: Can’t learn properties of undefined (studying ‘x’)
at SVGRectElement.mousemove (Bisect2.html:100:38)
at SVGRectElement. (d3.v5.js:1526:16)
My intention was to edit these first to incorporate a line as a substitute of a circle after which put it into my program proven in Codepen.
So proper now, your mousemove
code is searching for one thing known as circle
, however that’s not outlined. (It was solely outlined by way of the movetooltip
perform, as a result of that perform wanted to know what “circle” was being hovered over.
Even when it did resolve the reference to circle, it will then complain that it cant resolve a perform known as x, as a result of that must be your scale. It might additionally complain that your information doesn’t include an x property (as a result of your information isnt an object, its a 2 dimensional array).
I’m… considerably unclear what you’re particularly making an attempt to do at this actual second, however lets do this;
As a substitute of transferring the circle, inform your VertLine to maneuver itself on the x axis.
Issues I needed to do to get your code to work accurately: (No, i’m not supplying you with the code but, however pointers :P)
- The mousemove occasion ought to as a substitute by a pointermove occasion sure to the SVG itself.
- You’ll need a bisector with an accessor perform pointing on the x worth of the 2 dimensional information array.
- The mouse, now sure to the SVG, just isn’t translated; so that you’ll want to regulate the x-coordinate obtained from the mouse to compensate.
- As a result of the SVG is wider than your dataset, you will have to deal with the sting case that the bisector returns a worth that may be on the finish of the brand new array.
Bonus, which can be useful later:
- I used a
line
as a substitute of arect
. As a result of it’s a line.
My authentic code in Codepen or the copied code from these two examples? My one is extra essential.
The code that you just Codepenned in put up 2.
Most code I’ve seen place an invisible rect over the graph for all the flowery graphic actions.
Very first thing I wanna do is show a vertical line wherever the mouse is. Like right here:
You’ll be able to see in my end result that I added a static line.
No tooltip but.
Copied that a part of the code right here:
var mouseG = svg.append("g")
.attr("class", "mouse-over-effects");
mouseG.append("path") // that is the black vertical line to comply with mouse
.attr("class", "mouse-line")
.fashion("stroke", "black")
.fashion("stroke-width", "1px")
.fashion("opacity", "0");
var traces = focus.selectAll('path');
var mousePerLine = mouseG.selectAll('.mouse-per-line')
.information(d3.vary(traces.size))
.enter()
.append("g")
.attr("class", "mouse-per-line")
.attr('pointer-events', 'none');
// the circle
mousePerLine.append("circle")
.attr("r", 7)
.fashion("stroke", perform(d)
return 'pink';
)
.fashion("fill", "none")
.fashion("stroke-width", "1px")
.fashion("opacity", "0");
perform showLine()
d3.choose(".mouse-line")
.fashion("opacity", "0");
perform hideLine()
d3.choose(".mouse-line")
.fashion("opacity", "1");
svg.choose(".zoom")
.on('mouseenter', showLine)
.on('mouseleave', hideLine)
.on('mousemove', perform() { // mouse transferring over canvas
var mouse = d3.mouse(this);
//showLine();
// transfer the vertical line
d3.choose(".mouse-line")
.attr("d", perform()
var d = "M" + (mouse[0] + margin.left) + "," + (top + margin.prime);
d += " " + (mouse[0] + margin.left) + "," + margin.prime;
return d;
);
You are able to do it that means too, it was simply simpler out of your present graph building for me to bind it to the SVG as a complete. shrug both means works.
That JSFiddle instance code doesn’t work for me, there’s an error message within the D3.
I wanna add this line performance to the prevailing one, i.e. preserve the present tooltip code for now and solely take away it when the road model lastly works. Tried this now, no error messages however not working both:
let VertLine = svg.append('line')
.attr("remodel","translate(150,100)")
.fashion("stroke", "black")
.fashion("stroke-width", 2)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", top);
perform mousemove()
var x0 = xScale.invert(d3.mouse(this)[0]);
var i1 = bisect(dataset1, x0, 1);
var i2 = bisect(dataset2, x0, 1);
var i3 = bisect(dataset3, x0, 1);
selectedData1 = dataset1[i1]
selectedData2 = dataset1[i2]
selectedData3 = dataset1[i3]
VertLine
.attr("cx", xScale(selectedData1.xScale))
.attr("cy", yScale(selectedData1.yScale))
Properly for starters, a line
doesnt have a cx
or cy
…
Secondly, that code must be throwing an error, as a result of your datapoint doesnt have a “xScale” attribute.
x1 and y1, that code nonetheless references to a rectangle. The code the place I took it from makes use of x as a variable, I used xScale as a substitute.
var x = d3.scaleLinear()
.area([1,100])
.vary([ 0, width ]);
svg.append("g")
.attr("remodel", "translate(0," + top + ")")
.name(d3.axisBottom(x));
So… let’s deal with the factors that I laid out earlier than, one after the other.
Proper now, your code binds a perform on mousemove
, and tries to bind it to:
a nonexistant component class .zoom
,
every dot of the pink line,
every dot of the blue line,
and every dot of the inexperienced line.
As a substitute, you will have to bind a pointermove
occasion to an current component.