簡體   English   中英

不正確 SVG 掩碼 Position 使用相對位置時加載(Chrome)

[英]Incorrect SVG Mask Position On Load When Using Relative Positions (Chrome)

我正在做一個項目,我想在其中顯示圖像(模糊)並將“放大鏡”(帶有非模糊圖像的圓圈)放在感興趣的位置,用戶可以與之交互: 在此處輸入圖像描述

因此,圖像與 svg 元素一起放置在包裝器中。 該圖像應驅動 svg 的大小,因此我沒有使用view-box屬性。 SVG 絕對定位並覆蓋整個包裝器。 現在我可以使用相對定位在 svg 上放置元素。 然后我在 position 處放置一個圓圈,我希望放大鏡成為(仍然工作正常)。 作為蒙版,我在相同的 position(在蒙版元素內)創建了另一個圓圈,並在未模糊的圖像上使用了 css蒙版(#id)

這在 Firefox 上運行良好,但在 Chrome 上不會顯示掩碼。

在此處輸入圖像描述

只是,當我調整 window 的大小時,遮罩出現並且一切正常。

似乎掩碼元素未正確計算到其父元素。 面具放在左上角。 調整 window 的大小可修復此行為。

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 的渲染引擎無法正確推斷自動調整大小的視圖框的尺寸。 如果您檢查<mask>元素中的<circle>元素和 hover 元素,您會發現它計算的尺寸不正確,而在其他瀏覽器中它解析為正確的像素值。

更簡單的方法是在加載<img>元素時簡單地使用 JS 手動設置viewBox屬性,以強制 Chrome 根據顯式 viewbox 值正確地重新呈現 SVG。

 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

強制重新繪制蒙版將解決此問題。

這可以通過在頁面加載時進行簡單的 class 設置來實現,該設置將強制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, 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> <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 實現同樣的破解。
例如,在<mask>中為<use>href值設置動畫似乎可以做到這一點:

 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> <circle r="20%" cx="43%" cy="20%" id="circle"/> <mask id="mask"> <use x="0" href="#circle" fill="white"> <.-- Chrome hack around bug 330815 --> <animate attributeName="href" to="#circle" begin="0" dur="0s"/> </use> </mask> </defs> <.-- The stroke of the masked cicle. --> <use href="#circle" fill="transparent" stroke="white"/> <!-- The Element we want to mask. --> <image mask="url(#mask)" href="https://source.unsplash.com/2Ts5HnA67k8/400x200"></image> </svg> </div> </div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM