Wednesday, February 28, 2018

Safari doesn't emit pointer events on overflowing SVG contents

Leave a Comment

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.

1 Answers

Answers 1

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>

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment