I have a line chart with current year and comparison year / previous period. I would like to show a tooltip on hover, so it will display the current tick's value for both current's years and the comparing year. However, I've noticed that the total value returned doesn't match the amount on the y-axis (please see screenshot below).
As per image above the value should be between 30M - 40M but its showing as 56150248.2.
// tooltip on x axis
d3.selectAll(".xAxis > .tick")
.style("color", "#65757E")
.on("mouseover", function (d) {
console.log("data");
const mousePosition = d3.pointer(d);
const data = yScale.invert(mousePosition[0]);
console.log("pos", mousePosition);
console.log("data", data);
})
.on("mouseout", (d) => {
console.log("test");
});
What happens is the following:
d3.selectAll(".xAxis > .tick")
.on("mouseover", function (d) {
the argument d
refers to the event beeing passed. I recommend
calling it event
instead of d
otherwise it confusingSee: d3.pointer(event[, target])
Returns a two-element array of numbers [x, y] representing the coordinates of the specified event relative to the specified target. event can be a MouseEvent, a PointerEvent, a Touch, or a custom event holding a UIEvent as event.sourceEvent.
If target is not specified, it defaults to the source event’s currentTarget property, if available. If the target is an SVG element, the event’s coordinates are transformed using the inverse of the screen coordinate transformation matrix. If the target is an HTML element, the event’s coordinates are translated relative to the top-left corner of the target’s bounding client rectangle. (As such, the coordinate system can only be translated relative to the client coordinates. See also GeometryUtils.) Otherwise, [event.pageX, event.pageY] is returned.
const data = yScale.invert(mousePosition[0]);
you refer to the x position with mousePosition[0], you probably meant mousePosition[1]To use coordinates which you invert with the yscale you want the coordinates to be relative to the translated g directly under the svg. You have the selection of that element already referenced by the variable svg.
// tooltip on the g child of the svg
svg
.style("color", "#65757E")
.on("mouseover", function (event) {
console.log("data");
const mousePosition = d3.pointer(event);
const data = yScale.invert(mousePosition[1]);
console.log("pos", mousePosition);
console.log("data", data);
})
.on("mouseout", (event) => {
console.log("test");
});
Update 06/13/2021 based on the comments below: You may want to do something like this (not sure if I reference the right data, but you can work from this:
d3.selectAll(".xAxis > .tick")
.style("color", "#65757E")
.on("mousemove", function (event) {
const mousePosition = d3.pointer(event, svg.node()); // gets [x,y]
console.log("mouse position:", mousePosition);
const currentDate = xScale.invert(mousePosition[0]); // converts x to date
console.log("date at position:", currentDate);
const bisect = d3.bisector(d => new Date(d.date)) // create a bisector
const index_currentData = bisect.right(lineChartData.values[0].dataset, currentDate);
if (index_currentData < lineChartData.values[0].dataset.length) {
console.log(`Current data at index[${index_currentData}]: ${lineChartData.values[0].dataset[index_currentData].value}`);
}
const index_comparisonData = bisect.right(comparisonData.values[0].dataset, currentDate);
if (index_comparisonData < comparisonData.values[0].dataset.length) {
console.log(`Comparison data at index[${index_comparisonData}]: ${comparisonData.values[0].dataset[index_comparisonData].value}`);
}
})