Safari doesn't emit pointer events on overflowing SVG contents
Asked Answered
S

2

16

I'm trying to add click events to an SVG Element which has visible overflow and a shape element(circle/path) inside it which overflows the SVG.

On Safari(9,10,11), click event doesn't work in the area where the shape element(circle/path) overflows while it works fine in the area present within the SVG.

var count = 0;

function clickMe() {
  console.log("in click func");
  count++;
  document.getElementById("counter").innerHTML = count;
}
#counter {
  font-size: 2em;
}

#starSvg {
  pointer-events: auto;
  overflow: visible;
  position: absolute;
  left: 200px;
  top: 250px;
  border: 1px solid red;
}

#starPolygon {
  overflow: visible;
  fill: rgba(0, 153, 219, 1);
  pointer-events: visiblePainted;
  stroke-width: 4;
  stroke-linecap: square;
  stroke-linejoin: round;
  stroke: rgba(219, 0, 153, 1);
  cursor: pointer;
  shape-rendering: geometricPrecision
}

p {
  margin: 10px 0;
}
<div>
  <p>Open this webpage on Chrome &amp; safari</p>
  <p>On Chrome: Click work on all four hands of the star.</p>
  <p>On Safari: Click works only on the hands inside the red area(SVG bounding Rect).</p>

  <p style="position: absolute; top: 100px; left: 200px;">Click Event Counter:
    <span id="counter">0</span>
  </p>
  <div class="containter">
    <svg onclick="clickMe()" id="starSvg" width="100%" height="100%">
          <g width="100%" height="100%" transform="" style="overflow: visible; transform: rotate(45deg) translate(0, 0);">
            <polygon id="starPolygon" shape-rendering="geometricPrecision" points="0 -90,15 -15,90 0,15 15,0 90,-15 15,-90 0,-15 -15"></polygon>
          </g>
        </svg>
  </div>
</div>

Is this also a bug in Safari? The click event works fine in all browsers including IE.

Sadesadella answered 1/2, 2018 at 15:30 Comment(16)
@Andreas I've added the code to the question. Thank you for correcting me.Sadesadella
id="starPolygon"="geometricPrecision" isn't this an error, if it is what should it beParamour
Can you try jsfiddle.net/bp1r597e on Safari? I can't test.Botanist
@Bart: It was a typo. Thanks for pointing it. The issue however is not related to the typo. :)Sadesadella
@Botanist I tested the jsfiddle you linked. The issue still persists. :(Sadesadella
I guess this is just how safari has implemented overflow, if you just want to place the star at the corner you can always put it on topMarilyn
Yes it's a bug, pretty easy to work around though, just make the SVG bigger so it doesn't overflow.Rani
@SriramR, by the way, may I know why do you want to set the listener on svg and not the polygon itself?Botanist
@Botanist that won't change anything, pointer-events are not passed outside of the svg box, even the cursor is not set, and click won't get registered either.Proletariat
Apparently the bug has been reported, even though I wasn't able to find the issue...Proletariat
@Botanist In our application, we get the svg posiiton(left, right) & path coordinates from an external service. We are building a generic SVG component which creates the html based on the received data. Hence, I'm not in a position to either move the click event or edit the path/origin coordinates of the polygon.Sadesadella
@SriramR, if you're not in a position to either move the click event or edit the path/origin coordinates of the polygon, could you please specify what you can change?Forlorn
@SriramR - Can you create a viewBox or clipPath at the provided position(left, right) rather than the SVG element? Isn't the use case goal to place the drawing in the correct place? I doubt anyone is telling you to place the drawing viewport exactly at that location...are they? The viewport is the issue here and the SVG creates that. Please have a look at my answer if there is any flexibility here at all.Forcefeed
I've amended my solution to help with your statement to karthinkaruna. The easiest solution is to create a wrapper SVG element that is used as the outer most SVG viewport that is large enough to encompass the SVG position(left, right) you must use. This allows the point events to fire correctly in all browsers. Please see my answer.Forcefeed
@Botanist p.s your jsfiddle isn't working imgur.com/a/Uh4VMMoraine
@SriramR - have added Webkit bug report reference to my answer.Forcefeed
F
2

This mirrors Webkit bug report #140723 here: https://bugs.webkit.org/show_bug.cgi?id=140723

That bug report links to this codepen example reproducing the exact same results you've found: https://codepen.io/anon/pen/pvPQqY

And with the fix as I've described below applied here:

https://codepen.io/anon/pen/YeOmGW

===========

Edited for clarity: The evidence is clear that the initial clipping is taking effect at the outer most view port (svg) boundary, while at the same time the overflow property is allowing the visibility of the shape outside that clipped area. In effect rendering the pointer events void.

Said differently, evidence that clipping is applied IAW the first sentence here: http://w3.org/TR/SVG11/masking.html#AutoClipAtViewportNotViewBox , while at the same time conforming to the overflow rules (last three) here: http://w3.org/TR/SVG11/masking.html#OverflowAndClipProperties is the cause of this issue with Safari;

To overcome this issue, the OP must create a wrapper viewport to create a (workaround) solution to the dilemma created by the inconsistent implementations.

This is similar to adding any other HTML structure that might be required to wrap required content. (I'm really focused on helping solve the problem)

Hope this helps.

var count = 0;
document.querySelector('svg').addEventListener('click',clickMe);

function clickMe(e) {
  console.log("clicked on: " + e.target.id);
  count++;
  document.getElementById("counter").innerHTML = count;
}
#counter {
  font-size: 2em;
}

#starSvg {
  pointer-events: auto;
  position: absolute;
  width: 100%;
  height: 100%;
  left:0;
  top:0;
}

#starPolygon {
  transform: translate(50%, 50%) rotate(45deg);
  fill: rgba(0, 153, 219, 1);
  stroke-width: 4;
  stroke-linecap: square;
  stroke-linejoin: round;
  stroke: rgba(219, 0, 153, 1);
  cursor: pointer;
  shape-rendering: geometricPrecision
}
#starClip {
  width: 100%;
  height: 100%;
  stroke-width: 1;
  stroke: red;
  fill: transparent;
}

p {
  margin: 10px 0;
}
<div>
  <p>Open this webpage on Chrome &amp; safari</p>
  <p>On Chrome: Click work on all four hands of the star.</p>
  <p>On Safari: Click works only on the hands inside the red area(SVG bounding Rect).</p>

  <p style="position: absolute; top: 100px; left: 200px;">Click Event Counter:
    <span id="counter">0</span>
  </p>
  <div class="containter">
    <svg id="starSvg">
          <rect id="starClip" x="50%" y="50%"></rect>
          <g>
            <polygon id="starPolygon" x="0" y="0" points="0 -90,15 -15,90 0,15 15,0 90,-15 15,-90 0,-15 -15"></polygon>
          </g>
        </svg>
  </div>
</div>
Forcefeed answered 24/2, 2018 at 3:15 Comment(4)
It's not ambiguous, it's clearly defined in the SVG specification what the default CSS overflow value is.Rani
I'll defer to your expertise. The evidence is clear that the initial clipping is taking effect at the outer most view port (svg) boundary, while at the same time the overflow property is allowing the visibility of the shape outside that clipped area. In effect rendering the pointer events void.Forcefeed
Said differently, evidence that clipping is applied IAW the first sentence here: w3.org/TR/SVG11/masking.html#AutoClipAtViewportNotViewBox , while at the same time conforming to the overflow rules (last three) here: w3.org/TR/SVG11/masking.html#OverflowAndClipProperties ; to overcome this issue, the OP must create a new embedded viewport to create a (workaround) solution to the dilemma created by the inconsistent implementations. @Robert Longson: Is that a better explanation?Forcefeed
according to my comments, the <rect> could just as easily be an SVG element. Hence, the outer element would simply be required structure that allows the creation of the SVG element as specified in the stated requirements. Just like any other HTML structure that might be required to solve a problem. (I'm really focused on helping solve the problem)Forcefeed
F
1

Seems to be fixed in version 11.1 of Safari.

Fascine answered 1/10, 2018 at 16:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.