TransWikia.com

Click only through holes in svg mask: case with intersecting holes

Stack Overflow Asked by arsonist on November 29, 2021

I have svg mask which determines holes in rectangular. Behind svg mask I have some clickable elements and I would like to pass events to them, but only through holes.

I’ve already asked this question here and got an answer, which worked perfectly for me until I’ve run into a case with intersecting rectangulars
Click only through holes in svg mask

Is there any simple solution to got area around rectangulars clipped out but not area in intersections? It would be perfect to have something like globalCompositeOperation='destination-out' and I’ve started to think of how to use canvas instead of svg for my problem, but pointer-events which I use for svg are not yet designed to work correct with canvas as far as I know.

button, svg {
  position:absolute;
  width:400px;
  height:400px
}
button {
  background: #0000ff;
  cursor: pointer; 
}
button:hover {
  background: #008800; 
}
svg {
  pointer-events: none;
}
.over {
  fill: #000;
  clip-path: url(#clip);
  pointer-events: painted;
}
<button></button>
<svg xmlns="http://www.w3.org/2000/svg" height="400" width="400">
 <defs>
   <clipPath id="clip" clip-rule="evenodd">
 <path d="M 20 20 h 360 v 360 h -360 z
          M 90 100 v 240 h 140 v -240 z
          M 200 290 v 80 h 80 v -80 z" />
   </clipPath>
 </defs>
 <rect y="0" x="0" height="400" width="400" class="over" />
</svg>

One Answer

In my view, this is a problem of convenience. You would like to be able to use separate paths and treat them the same way whether they interact or not. Unfortunately, because of some limitations in the system, I do not think it is possible to achieve this convenience. However, your quetion itself is easy to answer.

First, a word about what is going on in your example. Your clipPath has a large "outer" path that is drawn clockwise (right, down, left, up). Then you have two "inner" paths drawn counterclockwise (down, right, up, left). The clip works according to what is considered inside and outside the path. The problem is that the intersection is considered outside (see link).

The straightforward solution is to use a single path for every shape, even if it is not a simple rectangle:

button, svg {
  position:absolute;
  width:400px;
  height:400px
}
button {
  background: #0000ff;
  cursor: pointer; 
}
button:hover {
  background: #008800; 
}
svg {
  pointer-events: none;
}
.over {
  fill: #000;
  clip-path: url(#clip);
  pointer-events: painted;
}
<button></button>
<svg xmlns="http://www.w3.org/2000/svg" height="400" width="400">
 <defs>
   <clipPath id="clip" clip-rule="evenodd">
 <path d="M 20 20 h 360 v 360 h -360 z
          M 90 100 v 240 h 110 v 30 h 80 v -80 h -50 v -190 z" />
   </clipPath>
 </defs>
 <rect y="0" x="0" height="400" width="400" class="over" />
</svg>

Answered by vqf on November 29, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP