仅单击 svg 蒙版中的孔

ars*_*ist 4 javascript css svg click pointer-events

我有 svg 蒙版,它确定矩形中的孔。在 svg mask 后面我有一些可点击的元素,我想将事件传递给它们,但只能通过孔。我已经尝试过pointer-events值,但我只能使用整个掩码来传递事件或使用整个掩码来捕获它们。对于一个孔,可以使用剪切路径简单地完成,只需确定孔的外部部分,但多个孔会使事情变得更加困难。是否有可能避免使用剪辑路径?我也尝试pointer-events: visiblePaintedpointer-events: painted,但没有成功。

.background {
  width: 400px;
  height: 400px;
  background: red;
  cursor: pointer;
}

.svg {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}
Run Code Online (Sandbox Code Playgroud)
<button class="background">
</button>
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" class="svg">
  <defs>
     <mask id="mask">
       <rect
         x="0"
         y="0"
         width="400"
         height="400"
         fill="white"
       />  
       <rect
          x="20"
          y="20"
          width="40"
          height="40"
          fill="black"
       />
       <rect
          x="290"
          y="290"
          width="40"
          height="40"
          fill="black"
       />  
     </mask>
  </defs>   
  <rect
    x="0"
    y="0"
    width="400"
    height="400"
    fill="black"
    opacity="0.5"
    mask="url(#mask)"
    pointer-events="auto"
   />
</svg>
Run Code Online (Sandbox Code Playgroud)

ccp*_*rog 7

这个问题有几个方面。首先,你是对的,蒙版和剪辑路径的行为与命中测试不同。

剪切路径是一个几何边界,并且给定点显然位于该边界内部或外部;因此,指针事件必须在剪切元素的渲染区域上正常捕获,但不得在剪切区域上捕获...相比之下,掩码不是二进制转换,而是像素操作,并且完全不同的行为透明和几乎但不完全透明可能是任意的、令人困惑的;因此,对于应用了蒙版的元素,即使在蒙版不透明度为零的区域中,仍然必须捕获指针事件。

其次,剪辑路径是一种几何形状,但就像所有路径一样,它可能包含孔。<rect>您可以使用具有三个子路径的一个,而不是<path>三个,只要clip-rule确保内部的子路径从周围的形状中切掉即可。

第三,如果该pointer-events属性应用于<svg>HTML 上下文中的元素,它的行为就会变得……奇怪。pointer-events: none元素上的任何其他值<svg>都会导致整个边界框接收事件 - 这是为 HTML 元素提议的行为,但目前不属于任何规范的一部分。

pointer-events: none这里的解决方案是在元素上设置,然后在子元素上<svg>反转。 pointer-events: painted<rect>

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;
}
Run Code Online (Sandbox Code Playgroud)
<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 40 40 v 40 h 40 v -40 z
          M 200 290 v 40 h 40 v -40 z" />
   </clipPath>
 </defs>
 <rect y="0" x="0" height="400" width="400" class="over" />
</svg>
Run Code Online (Sandbox Code Playgroud)