15

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.

Brett DeWoody
  • 59,771
  • 29
  • 135
  • 184
Sriram R
  • 300
  • 2
  • 15
  • @Andreas I've added the code to the question. Thank you for correcting me. – Sriram R Feb 01 '18 at 15:47
  • id="starPolygon"="geometricPrecision" isn't this an error, if it is what should it be – Bart Feb 05 '18 at 12:45
  • Can you try http://jsfiddle.net/bp1r597e/ on Safari? I can't test. – karthikaruna Feb 05 '18 at 13:41
  • @Bart: It was a typo. Thanks for pointing it. The issue however is not related to the typo. :) – Sriram R Feb 05 '18 at 17:59
  • @karthikaruna I tested the jsfiddle you linked. The issue still persists. :( – Sriram R Feb 05 '18 at 18:01
  • 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 top – Huangism Feb 05 '18 at 18:16
  • 2
    Yes it's a bug, pretty easy to work around though, just make the SVG bigger so it doesn't overflow. – Robert Longson Feb 05 '18 at 19:21
  • @SriramR, by the way, may I know why do you want to set the listener on `svg` and not the `polygon` itself? – karthikaruna Feb 06 '18 at 05:56
  • @karthikaruna 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. – Kaiido Feb 06 '18 at 06:32
  • Apparently the bug [has been reported](https://stackoverflow.com/questions/40587203/safari-os-x-doesnt-emit-pointer-events-on-overflowing-svg-contents), even though I wasn't able to find the issue... – Kaiido Feb 06 '18 at 06:46
  • @karthikaruna 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. – Sriram R Feb 07 '18 at 17:49
  • 1
    @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**? – Kosh Feb 21 '18 at 16:28
  • @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. – Randy Casburn Feb 24 '18 at 03:32
  • 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. – Randy Casburn Feb 24 '18 at 16:07
  • @karthikaruna p.s your jsfiddle isn't working https://imgur.com/a/Uh4VM –  Feb 25 '18 at 16:11
  • @SriramR - have added Webkit bug report reference to my answer. – Randy Casburn Feb 25 '18 at 17:22

2 Answers2

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>
Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
  • It's not ambiguous, it's clearly defined in the SVG specification what the default CSS overflow value is. – Robert Longson Feb 24 '18 at 07:18
  • 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. – Randy Casburn Feb 24 '18 at 15:26
  • Said differently, evidence that clipping is applied IAW the first sentence here: https://www.w3.org/TR/SVG11/masking.html#AutoClipAtViewportNotViewBox , while at the same time conforming to the overflow rules (last three) here: https://www.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? – Randy Casburn Feb 24 '18 at 15:26
  • according to my comments, the `` 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) – Randy Casburn Feb 24 '18 at 15:31
1

Seems to be fixed in version 11.1 of Safari.

Djao
  • 21
  • 4