Skip to content Skip to sidebar Skip to footer

Click Only Through Holes In Svg Mask

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 experime

Solution 1:

There are several aspects to this problem. First, you are right the behavior of masks and clip-paths is different in relation to hit-testing.

A clip path is a geometric boundary, and a given point is clearly either inside or outside that boundary; thus, pointer events must be captured normally over the rendered areas of a clipped element, but must not be captured over the clipped areas... By contrast, a mask is not a binary transition, but a pixel operation, and different behavior for fully transparent and almost-but-not-fully-transparent may be confusingly arbitrary; as a consequence, for elements with a mask applied, pointer events must still be captured even in areas where the mask goes to zero opacity.

Second, a clip-path is a geometric shape, but just like all paths, it might contain holes. Instead of three <rect>s, you can use one <path> with three subpaths, as long as the clip-rule makes sure the subpaths inside get cut out of the surrounding shape.

Third, if the pointer-events property is applied to an <svg> element in a HTML context, its behavior becomes...strange. Any other value than pointer-events: none on the <svg> element lead to the whole bounding box receiving events - a behavior proposed for HTML elements, but currently not part of any spec.

The solution here is to set pointer-events: none on the <svg> element, and then to reverse that with pointer-events: painted on the child <rect> element.

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><svgxmlns="http://www.w3.org/2000/svg"height="400"width="400"><defs><clipPathid="clip"clip-rule="evenodd"><pathd="M 20 20 h 360 v 360 h -360 z
          M 40 40 v 40 h 40 v -40 z
          M 200 290 v 40 h 40 v -40 z" /></clipPath></defs><recty="0"x="0"height="400"width="400"class="over" /></svg>

Solution 2:

Clip masks are useful for cropping parts out of complicated objects, but if you're just working with blocks of solid colour then maybe it would be just as easy to create shapes that already have holes in them.

I've added an example below. Does this help?

<svgwidth="400"heoght="200"viewBox="0 0 400 200"><textx="100"y="100"text-anchor="middle"alignment-baseline="middle"onclick="alert('Hello!')"style="cursor:pointer">Click me</text><textx="300"y="100"text-anchor="middle"alignment-baseline="middle"onclick="alert('Hello?')"style="cursor:pointer">Not me</text><pathd="M20 20 180 20 180 180 20 180ZM60 60 60 140 140
    140 140 60Z"fill="#3a6"fill-opacity="0.7"fill-rule="nonzero"/><pathd="M220 20 380 20 380 180 220 180Z"fill="#f20"fill-opacity="0.7"/></svg>

Post a Comment for "Click Only Through Holes In Svg Mask"