openseadragon/svg-overlay

d3 objects disappearing on zoom/move

travisdesell opened this issue · 6 comments

I've added a number of d3 shapes (circles and rectagles) as an overlay to a rather large image (the original file was ~2GB) and when zooming or moving around some of them flicker and/or disappear. Is this a known issue?

I've observed it on some browsers; I think Firefox does this more than Chrome, for instance. At any rate, I think it has to do with the scale of the coordinate system you're using. Did you stick with the default OSD coordinate system where the width of your image is 1? You might try bumping that up to 1000 or something and see if that affects the issue (of course remember to update the coordinates for your d3 shapes).

I'm marking this as a bug, although I think it's more of a browser limitation... I'm not sure what we can do beyond recommending changing the coordinates for your project. I'd love to hear ideas though!

Yeah, I should have thought to try this it in a different browser. Chrome works perfecftly, so it's probably a Safari issue. I was using default OSD coordinates, nothing fancy:

        var overlay = viewer.svgOverlay();

        for (var i = 0; i < points.length; i++) {
            var d3Circle = d3.select(overlay.node()).append("circle")
                .style('fill', 'rgba(255,0,0,0.25)')
                .attr("id", "svg-circle-" + i)
                .attr("cx", (points[i][0] /width))
                .attr("cy", (points[i][1] / height))
                .attr("r", 0.005)
                .attr("class", "svg-circle")
        }   

        for (var i = 0; i < lines.length; i++) {
            var d3Line = d3.select(overlay.node()).append("line")
                .style('stroke', 'rgba(0,255,0,0.25)')
                .attr("id", "svg-line-" + i)
                .attr("x1", lines[i][0] / width)
                .attr("y1", lines[i][1] / height)
                .attr("x2", lines[i][2] / width)
                .attr("y2", lines[i][3] / height)
                .attr("stroke-width", 0.001)
                .attr("class", "svg-line")

        }   

Where width and height are the width/height of the full image in pixels and the point/line values are also in pixels. So that should scale everything between 0 and 1.

I even set up a toggle to show/hide the "svg-line" and "svg-circle" classes and this still wouldn't make them show up, so I'm thinking maybe the zIndex of the image tiles are somehow getting in front of the svgs?

The first thing to try is scaling up your coordinate system. When you open your image, give it a width of 1000 or something, and then scale your overlays as appropriate. My theory is that it has to do with rounding in the transform math.

That said, if you do find something related to z-index, I'd love to know about it!

I hope it's okay to comment on this many years later. I had this same issue, and there aren't many reports about it.
All browsers have a hard limit on rendering svgs very far zoomed-in. Chrome/Firefox that limit is around 1e-6 for things like stroke-width. On Safari, there is a hard limit for stroke-width at 0.001, below which the path just disappears.
I made a demo at https://codepen.io/robbykraft/pen/LYMJKmE and filed a report with Apple, it would be nice if they could match the 1e-6 limit.
So, it's not a bug in Safari, it's just Safari's limit. And the work around is as you mention @iangilman to enlarge the viewBox so you are not working with such small numbers. I'm bet you're correct about the rounding/transform math too.

@robbykraft Thank you for adding this additional detail! Always welcome ❤️