使用相对位置Chrome时,加载时SVG蒙版位置不正确

问题描述

我正在一个项目中,我要显示图像(模糊)并将“放大镜”(带有非模糊图像的圆圈)放在感兴趣的位置,用户可以与以下位置进行交互:

enter image description here

因此,图像被放置在svg元素旁边的包装器内。该图像应驱动svg的大小,因此我不使用 view-box 属性。 SVG定位绝对,并覆盖整个包装纸。现在,我可以使用相对定位将元素放置在svg上。然后,在希望放大镜的位置放置一个圆圈(仍然可以正常工作)。作为蒙版,我在同一位置(蒙版元素内部)创建了另一个圆,并在未模糊的图像上使用css mask(#id)

这在Firefox上可以正常使用,但在Chrome上不会显示遮罩。

enter image description here

只有当我调整窗口大小时,才会显示蒙版,并且一切都会按预期进行。

似乎mask元素的父元素计算不正确。并将遮罩放置在左上角。调整窗口大小可以解决此问题。

HTML

<div class="container">
  <img src="https://source.unsplash.com/2Ts5HnA67k8/400x200">
  <!-- SVG (purple) -->
  <!-- Setting a viewbox can solve the Issue,but I would prefer  not to. -->
  <div class="wrapper">
    <svg>
      <!-- Define the Mask -->
      <defs>

      </defs>

      <mask id="mask">
        <circle r="20%" cx="43%" cy="20%" fill="white"></circle>
      </mask>

      <!-- The stroke of the masked cicle. -->
      <circle r="20%" cx="43%" cy="20%" stroke="white" fill="transparent"></circle>

      <!-- The Element we want to mask. -->
      <image href="https://source.unsplash.com/2Ts5HnA67k8/400x200"></image>
    </svg>
  </div>
</div>

CSS

img {
  filter: blur(4px);
}

image {
  mask: url(#mask);
}


svg {
  position: absolute;
  left:0;
  top:0;
  width:100%;
  height:100%;

如何在启动时修复Chrome的这种行为? 或者是否有解决方法,例如手动触发遮罩层的重新计算?

我在这里创建了一个工作示例: https://codepen.io/Ukmasmu/pen/NWNrGoW

任何帮助将不胜感激! 在此先感谢:)

解决方法

我认为问题出在Chrome的渲染引擎无法正确推断自动调整大小的视图框的尺寸。如果检查该元素并将鼠标悬停在<circle>元素中的<mask>元素上,您将意识到它的尺寸计算不正确,而在其他浏览器中,它将解析为正确的像素值。

更简单的方法是,在加载viewBox元素时,简单地使用JS手动设置<img>属性,以强制Chrome根据显式的viewbox值正确地重新渲染SVG。 / p>

const img = document.querySelector('img');
const svg = document.querySelector('svg');

img.addEventListener('load',(e) => {
  svg.setAttribute('viewBox',`0 0 ${img.clientWidth} ${img.clientHeight}`)
});
img {
  filter: blur(4px);
}

image {
  mask: url(#mask);
}

svg {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(138,43,226,0.2);
}

.container {
  background-color: gray;
  position: relative;
}

html,body {
  width: 100%;
  height: 100%;
  margin: 0;
}

body {
  background-color: #111;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="container">
  <img src="https://source.unsplash.com/2Ts5HnA67k8/400x200">
  <!-- SVG (purple) -->
  <!-- Setting a viewbox can solve the Issue,but I would prefer  not to. -->
  <div class="wrapper">
    <svg>
      <!-- Define the Mask -->
      <defs>

      </defs>

      <mask id="mask">
        <circle r="20%" cx="43%" cy="20%" fill="white"></circle>
      </mask>

      <!-- The stroke of the masked cicle. -->
      <circle r="20%" cx="43%" cy="20%" stroke="white" fill="transparent"></circle>

      <!-- The Element we want to mask. -->
      <image href="https://source.unsplash.com/2Ts5HnA67k8/400x200"></image>
    </svg>
  </div>

</div>

,

那绝对是一个错误,可能是bug=330815

强制重涂面具将解决此问题。

这可以通过在页面加载时进行简单的类设置来实现,该类设置将强制进行displayposition之类的更改:

onload = evt => document.body.classList.add('loaded');
/* Chrome hack around bug 330815 */
.loaded mask {
  display: block;
}
img {
  filter: blur(4px);
}

image {
  mask: url("#mask");
}

svg {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(138,but I would prefer  not to. -->
  <div class="wrapper">
    <svg>
      <!-- Define the Mask -->
      <defs>
        <mask id="mask">
          <circle r="20%" cx="43%" cy="20%" fill="white"/>
        </mask>
      </defs>


      <!-- The stroke of the masked cicle. -->
      <circle r="20%" cx="43%" cy="20%" stroke="white" fill="none"/>

      <!-- The Element we want to mask. -->
      <image mask="url(#mask)" href="https://source.unsplash.com/2Ts5HnA67k8/400x200"></image>
    </svg>
  </div>

</div>

如果您真的想要没有JS的东西,也可以通过SMIL实现相同的破解。
例如,对href内的<use>的{​​{1}}值进行动画处理似乎可以做到:

<mask>
img {
  filter: blur(4px);
}

image {
  mask: url("#mask");
}

svg {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(138,body {
  width: 100%;
  height: 100%;
  margin: 0;
}

body {
  background-color: #111;
  display: flex;
  justify-content: center;
  align-items: center;
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...