【问题标题】:clip-path svg works on image, but not on divclip-path svg 适用于图像,但不适用于 div
【发布时间】:2020-03-19 18:22:48
【问题描述】:

在 MDN 上有一个关于如何在图像上使用剪辑路径 svg 的示例。相同的剪辑路径似乎不适用于div 元素。有人可以澄清一下:

  • 为什么此代码不能按预期工作
  • 一种使 svg 剪辑路径在 div 上工作的方法

剪切图像的示例代码 (based on MDN docs)

#clipped {
  clip-path: url(#cross);
}
<img id="clipped" src="https://mdn.mozillademos.org/files/12668/MDN.svg"
    alt="MDN logo">
<svg height="0" width="0">
  <defs>
    <clipPath id="cross">
      <rect y="110" x="137" width="90" height="90"/>
      <rect x="0" y="110" width="90" height="90"/>
      <rect x="137" y="0" width="90" height="90"/>
      <rect x="0" y="0" width="90" height="90"/>
    </clipPath>
  </defs>
</svg>

div 上的相同剪辑路径(似乎不起作用)

#clipped {
  width: 100px;
  height: 100px;
  background: black;
  clip-path: url(#cross);
}
<div id="clipped"></div>
<svg height="0" width="0">
  <defs>
    <clipPath id="cross">
      <rect y="110" x="137" width="90" height="90"/>
      <rect x="0" y="110" width="90" height="90"/>
      <rect x="137" y="0" width="90" height="90"/>
      <rect x="0" y="0" width="90" height="90"/>
    </clipPath>
  </defs>
</svg>

【问题讨论】:

  • Browser compatibility 该页面下方的部分列出了“在 HTML 元素上”在几个非 MS 浏览器中的工作 - 但也将其标记为“实验性。预计未来行为会发生变化。” // caniuse.com/#feat=css-clip-path 进一步说明了不同浏览器的支持级别。
  • @04FS Firefox 70 根据 caniuse 表应该有完全支持。该示例在那里也不起作用。关于实验阶段的公平点。如果一致认为这是一个(部分)未实​​现/未记录的功能,我会在 MDN 上留下一条注释。
  • Firefox 确实支持使用 SVG clipPath 剪切 div
  • 请将div的大小改为width: 300px; height: 300px;
  • @enxaneta 很好。像素大小似乎与 svg 中的一个单位相关 :)。如果您发布答案,我可以接受并关闭问题;)。

标签: css svg clip-path


【解决方案1】:

您的问题的解决方案是使用 clipPathUnits="objectBoundingBox" 并构建大小在 0 和 1 之间的剪切路径,如下所示:

#clipped {
  margin:1em;
  width: 100px;
  height: 100px;
  background: black;
  display:inline-block;
  clip-path: url(#cross);
}
#clipped.big{
  width: 200px;
  height: 200px;
}
<div id="clipped"></div>
<div id="clipped" class="big"></div>
<svg viewBox="0 0 1 1">
  
    <clipPath id="cross" clipPathUnits="objectBoundingBox">
       <rect y="0" x="0" width=".4" height=".4"/>
       <rect y="0.6" x="0" width=".4" height=".4"/>
       <rect y="0" x="0.6" width=".4" height=".4"/>
       <rect y="0.6" x="0.6" width=".4" height=".4"/>
    </clipPath>
  
</svg>

【讨论】:

  • 相反的效果呢?有什么方法可以应用 magic 属性来隐藏十字架并通过保持剪辑路径像这个一样简单来显示另一部分?
  • 我想我们必须定义 4 个矩形然后:jsfiddle.net/umd5vLn2?
  • 好吧,你可以保留两者。我只是想知道是否有一种方法可以保持相同并能够获得相反的效果(例如我们可以反转白色和透明的蒙版)
  • 这个答案和 Temani Afif 的答案似乎都是正确的。如果您正在处理具有相同高宽比的图像,objectBoundingBox 解决方案非常棒。否则存在剪切路径失真的风险。 Temani Afif 的回答指出,当您不使用objectBoundingBox 时,图像的大小很重要。 svg 中的单位与该场景中 div/图像中的像素相关。
【解决方案2】:

正如@enxaneta 所指出的,这完全是大小问题。如果你增加 div 的大小,你会看到效果:

#clipped {
  width: 300px;
  height: 200px;
  background: black;
  clip-path: url(#cross);
}
<div id="clipped"></div>
<svg height="0" width="0">
  <defs>
    <clipPath id="cross">
      <rect y="110" x="137" width="90" height="90"/>
      <rect x="0" y="110" width="90" height="90"/>
      <rect x="137" y="0" width="90" height="90"/>
      <rect x="0" y="0" width="90" height="90"/>
    </clipPath>
  </defs>
</svg>

或者您可以使用mask 来获得动态。每个角落有 4 个白色矩形和白色意味着 让它可见

.box {
  width: 100px;
  height: 100px;
  margin:5px;
  background: linear-gradient(red,blue);
  -webkit-mask:
    linear-gradient(white,white) top left,
    linear-gradient(white,white) top right,
    linear-gradient(white,white) bottom left,
    linear-gradient(white,white) bottom right;
  -webkit-mask-size:40% 40%;
  -webkit-mask-repeat:no-repeat;
  -mask:
    linear-gradient(white,white) top left,
    linear-gradient(white,white) top right,
    linear-gradient(white,white) bottom left,
    linear-gradient(white,white) bottom right;
  mask-size:40% 40%;
  mask-repeat:no-repeat;
}
<div class="box"></div>

<div class="box" style="width:200px;height:200px;"></div>

【讨论】:

    【解决方案3】:

    Clip-path 没有被继承。 Establishing a new clipping path: the ‘clipPath’ elementW3C

    因此,我们不会通过将clip-path 应用于父块来剪切子元素

    使用 svg &lt;image&gt; 标签而不是 &lt;img&gt; 并应用 clip-path 可能会更好

    使用 div 作为自适应容器

    .wrapped {
    width:25%;
    height:25%;
    }
    #img1 {
    clip-path:url(#cross);
    }
    <div class="wrapped">
    <svg  viewBox="0 0 250 250">
      <defs>
        <clipPath id="cross">
          <rect y="110" x="137" width="90" height="90"/>
          <rect x="0" y="110" width="90" height="90"/>
          <rect x="137" y="0" width="90" height="90"/>
          <rect x="0" y="0" width="90" height="90"/>
        </clipPath>
      </defs> 
    
    <image id="img1" width="100%" height="100%" xlink:href="https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg"/>
    
    </svg> 
    
    </div>

    【讨论】:

    • 你能详细说明你在说什么父块和子元素。这些是svg中的元素吗?在那种情况下,我会怀疑 svg 有问题,因为相同的 svg clipPath 对图像起作用。
    • @RMo
      - 父块 SVG - 在你的第二个例子中的子元素
    • 这里没有继承的部分?我们没有任何亲子关系还是我错过了什么?
    • @Temani Afif 在我指出的指向 w3C 的链接中,它是明确写的 clip-path: inherit NO 正如我从示例中了解到的那样,OP 想将 clip-path 应用于图像所在的 div定位也许我急着预测OP的意愿:)
    • 我猜继承是在解释另一件事,因为剪辑路径会影响元素的所有内容:jsfiddle.net/89r5t630 ...也许孩子没有继承该值,但他们受那个影响他们的父母(如不透明度,显示等)
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签