I'm experiencing an issue with D3.js ribbons in Safari where certain SVG path elements don't respond to hover events for styling changes. The hover effect, such as changing the fill style, works perfectly in Chrome and Firefox. However, in Safari, some paths seem to completely ignore the hover interaction.
I've tried all possible pointer-events values (all, auto, visiblePainted, etc.), but it still doesn't work. Here's what I've already verified:
Here’s how I’m implementing the path drawing:
// Dimensions and container setup
const width = 600, height = 600;
const svg = d3.select("#circos-plot")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
// Updated data with new angles
const data = {
source: { radius: 200, startAngle: 0.10082134423424959, endAngle: 0.23383773956851167 },
target: { radius: 200, startAngle: 1.0174690537411528, endAngle: 1.0615254394569593 }
};
// Ribbon generator
const ribbon = d3.ribbon().radius(data.source.radius);
// Append ribbon with hover event
svg.append("path")
.datum(data)
.attr("d", ribbon)
.attr("fill", "steelblue")
.attr("class", "ribbon") // Add class for hover styling
.style("pointer-events", "visibleFill") // Ensure pointer events work
.on("mouseover", function(event, d) {
// Change color on hover
d3.select(this).transition().duration(300).attr("fill", "orange");
})
.on("mouseout", function(event) {
// Reset color when mouse leaves
d3.select(this).transition().duration(300).attr("fill", "steelblue");
});
Below is the complete working example:
https://codepen.io/joko3ono/pen/VYZPwWa
And here is the GIF showcasing the bug. gif
Is there any specific code or adjustments needed to make the SVG behave correctly in Safari, similar to how it works in other browsers?
// Dimensions and container setup
const width = 600, height = 600;
const svg = d3.select("#circos-plot")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
// Data for the ribbon
const data = {
source: { radius: 200, startAngle: 0.1, endAngle: 0.23 },
target: { radius: 200, startAngle: 1.01, endAngle: 1.06 }
};
// Ribbon generator
const ribbon = d3.ribbon().radius(data.source.radius);
// 1. Add the visible ribbon path
const ribbonPath = svg.append("path")
.datum(data)
.attr("d", ribbon)
.attr("fill", "steelblue")
.attr("class", "ribbon");
// 2. Add an invisible overlay path for hover interaction
const invisibleRibbonPath = svg.append("path")
.datum(data)
.attr("d", ribbon)
.attr("fill", "none") // No fill for the overlay
.attr("stroke", "transparent") // Invisible stroke
.attr("stroke-width", 20) // Expand the hoverable area
.style("pointer-events", "stroke") // Interact only with the stroke
.on("mouseover", function(event) {
ribbonPath.transition().duration(300).attr("fill", "orange");
})
.on("mouseout", function(event) {
ribbonPath.transition().duration(300).attr("fill", "steelblue");
});
.ribbon {
transition: fill 0.3s ease;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
<svg id="circos-plot"></svg>