问题
I am creating a line plot with tooltips appearing on hovering over the data points using d3. However, I added a few annotations to the plot and the callout circles now block the tooltips from appearing on the points overlapped by the annotations.
The following is a screenshot of the tooltip appearing on the points, but it doesn't appear on the point overlayed by the annotation circle (grey circle on the image).
The code used to generate the line plot, the points, tooltip and annotations are as follows
// Create Tooltip
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
// Annotations
const annotations = [
{
type: d3.annotationCalloutCircle,
note: {
label: "Label",
title: "Title",
wrap: 500 },
subject: { radius: 40 },
color: ["#bdbfbf"], x: 550, y: 100, dy: -50, dx: -120
}
]
// Add annotations to the plot
const makeAnnotations = d3.annotation()
.type(d3.annotationLabel)
.annotations(annotations)
d3.select("svg")
.append("g")
.call(makeAnnotations)
// Draw line
var line = d3.line()
.x(function(d) { return x(+d.hour); })
.y(function(d) { return y(+d.val); })
svg.selectAll(".line")
.data(groupeddata)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 1.5)
.attr("d", function (d){ return line(d.values)})
// Draw points and add tooltips
svg.selectAll(".dot")
.data(groupeddata)
.enter()
.append("g")
.style("fill", function(d){ return color(d.key) })
.selectAll(".points")
.data(function (d){return d.values})
.enter()
.append("circle")
.attr("cx", function(d) { return x(d.hour) } )
.attr("cy", function(d) { return y(d.val) } )
.attr("r", 5)
.attr("stroke", "white")
.on("mouseover", function(d){
return tooltip.style("visibility", "visible")
.html("<b>" + d.day + " " + d.hour + "00h" + "</b>" + "<br/>"
+ "Average Pedestrian Count : " + parseFloat(d.val).toFixed(2))})
.on("mousemove", function(){
return tooltip.style("top",(d3.event.pageY-10)+"px")
.style("left",(d3.event.pageX+10)+"px")})
.on("mouseout", function(){
return tooltip.style("visibility", "hidden")})
回答1:
In contrast to HTML, SVG doesn't work with z-index
, but just with the order of the elements in the HTML. Later nodes overlap any earlier nodes. One way to fix your issue would be to call .raise() on all circles, so they are above the annotations and can thus be interacted with.
Another option is to check whether the annotation circle has fill: none
. The following snippet shows how the first circle passes hovers to the rect behind it, while the second one doesn't. This is because fill: none
literally removes the hitbox, while fill:transparent
does not.
A final option is to add pointer-events: none
to the annotation. That way, all events (hover, click, touch, drag, etc.) just pass through it as if it were a ghost.
Hover over the following nodes and see how they do or do not trigger a message in the console.
d3.selectAll("rect")
.on("mouseover", () => {
console.log("HOVER");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<rect x="5" y="5" height="10" width="10"></rect>
<circle cx="10" cy="10" r="10" stroke="black" fill="none"></circle>
<rect x="45" y="5" height="10" width="10"></rect>
<circle cx="50" cy="10" r="10" stroke="blue" fill="transparent"></circle>
<rect x="85" y="5" height="10" width="10"></rect>
<circle cx="90" cy="10" r="10" stroke="red" fill="transparent" style="pointer-events: none;"></circle>
</svg>
来源:https://stackoverflow.com/questions/64536153/annotation-connectors-blocking-tooltips