openseadragon / svg-overlay

An OpenSeadragon plugin that adds SVG overlay capability.
BSD 3-Clause "New" or "Revised" License
58 stars 28 forks source link

d3 objects disappearing on zoom/move #20

Open travisdesell opened 7 years ago

travisdesell commented 7 years ago

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?

iangilman commented 7 years ago

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).

iangilman commented 7 years ago

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!

travisdesell commented 7 years ago

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?

iangilman commented 7 years ago

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!

mayakraft commented 1 year ago

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.

iangilman commented 1 year ago

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