Vertical line and tooltip wherever the line hits a data point

all of that becomes just
VertLine

(Technically, the Y values and the Stroke wont change, so you dont need to set them again, but shrug)

That works.

Replace that with VertLine.

Now the tooltip function doesn’t work anymore when I go over the data and the mousemove function is needed, without it the whole thing doesn’t work.

But I guess it is incomplete since it only includes one dataset and not all three.

Does the mousemove override the mouseover?

Now I would like to have the tooltip appear whenever VertLine hits a data point, so there could be several tooltip shown at once.

Well, yes and no - the mouseover isn’t being “overridden”, but because you add the line after you add the circles, its on top of the circles, and you never mouse over a circle, because your mouse is over the line instead.

There’s a couple of ways of handling that - notably, you could find the nearest point to the mouse by using a couple of bisectors, for example.

I created VertLine very early in the program, now it is behind the data points and it works.

Is this function correct or does it need improvement?

var bisect = d3.bisector(function(d) { return d.x; }).left;

        function 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("x1", xScale(selectedData1.xScale))
              .attr("y1", yScale(selectedData1.yScale))
        }

Cause it needs to work for every data and it is on different scales as you know and it can be zoomed in and out. I remember the code for the first tooltip was quite complicated.

Well remember your data isnt an object, it’s a 2 dimensional array. So you can’t tell it to return d.x, because .x isnt a property of the array. You’d need to tell it to return d[0] for the X coordinate.

My guess is that most of the code that displays the first tooltip stays the same. The only difference is that the mouse doesn’t have to hit the actual data point on x and y coordinates but only on the x coordinate. The height doesn’t matter and then it should display all the tooltips of all three curves.
It is not so much about the line hitting it, that is just to show it, right?

So if your goal is to show 3 tooltips, one for each line, and have it based on the mouse’s position, then you’ll put the tooltip moving code into the mouse move;

You’ve got the three dataset points already from your bisects, so you should be able to fill out the tooltip; for positioning the tooltip, you’ll need to run each of the X and Y values through their scales.

Note that it’s not a question of “hitting” the data point - bisect will find the closest data point to the chosen side of the mouse point; you created your bisector as a left, so bisect will find the closest data point that is left of the mouse pointer. This is less relevant in this particular dataset, because the x values are very close together, but in sets with gaps, that may be noteworthy.

I only have this:

        function 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("x1", xScale(selectedData1.xScale))
              .attr("y1", yScale(selectedData1.yScale))
        }

Do I need to add

              .attr("x2", xScale(selectedData2.xScale))
              .attr("y2", yScale(selectedData2.yScale))

and same for three?

This is the movetooltip function:

        function movetooltip(d,i) {

            let circle = d3.select(this);
            tooltip.select("rect")
            .attr("stroke", circle.style("fill"))

            if(this.classList.contains("blau")) {
            
                tooltip.attr("transform","translate("+(110+newX(d[0]))+","+(70+newZ(d[1]))+")")
                    .style("visibility","visible")

                var select = document.getElementById('changeAxisYLabel');
                var option = select.options[select.selectedIndex];

                let vv = option.value;

                const maxval = d3.max(dataset3, x => x[1]);

                tooltip.select("text")
                .text((vv == "percentage") ? d[0] + " : "+ Math.round(d[1]*100/maxval) + "%" : d[0] + " : "+ d[1])

            } else {

                tooltip.attr("transform","translate("+(110+newX(d[0]))+","+(70+newY(d[1]))+")")
                    .style("visibility","visible")

                var select = document.getElementById('changeAxisYLabel');
                var option = select.options[select.selectedIndex];

                let vv = option.value;

                const maxval = d3.max(dataset1, x => x[1]);

                tooltip.select("text")
                .text((vv == "percentage") ? d[0] + " : "+ Math.round(d[1]*100/maxval) + "%" : d[0] + " : "+ d[1])
                }
           }

So that goes into the mousemove with a few tweaks.

Is there also right and center/middle or can I remove left? I copied that code.

You’ll only move VertLine once - you should be moving both X values of the line, and leaving the Y values alone.

The tooltip code is currently set to only move one tooltip, so you’ll need to fiddle to add all three (though you can condense the code a bit, because you now KNOW when you’re going to be moving a blue tooltip…)

There is a right, but not a “center” per-se - Bisect says “If I was going to insert this new value into the sorted set, what index would it go into?”

The problem with that question is this: If I have an array
[0,1,2,3,4]
and try to insert 3.5, the answer is easy - insert it at position 4 (and bump the 4 out to position 5).

What if i tried to insert 3? Does it go before the current 3 ? or after it?
This is where left and right come into play - left says you’d insert it before, right says you’d insert it after. And thats why “center” doesnt make any sense. I believe the default is right if unspecified, but i could be wrong on that.

This code is similar, will try it out:

Do I need this focus tracking code? I repeatedly see that. Focus is g append g which is not displayed, then attributes are connected to it, and these are selected in the actual mousemove function to find out the position.

I dont know. You keep pulling random bits of code and putting it into your project. I’m not the one suggesting or doing that, so I dont know what you need or dont need.

x is not a function, it is a variable, I tried to do it like in the example:

I thought this would be easier since the mouse doesn’t have to be right on the graph (x and y or x and z) but just on x.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.