如何在图像加载前显示 SVG 填充?

How can I display an SVG fill before image loads?

我目前有一个工作示例,但我想知道是否有比我更了解 SVG 的人可以压缩代码并使其更优雅。

我想做什么:

  1. 页面加载后在自定义路径(形状)内显示图像(“延迟加载”)
  2. 直到页面加载(最重要的是在较慢的设备上)显示填充作为背景。

在此处查看 fiddle 和代码:

https://jsfiddle.net/k2o9L6dg/

复制问题

如您所见,一切正常,但我想删除 <g> 标签。 如果删除此标签,形状为 transparent/white 直到图像加载。您可以在“网络”选项卡下节流以查看此用户体验。我想在图像加载之前使用灰色填充,以便文本可以显示在形状内。

我觉得应该可以完成这项工作,而不必两次定义“路径”。每当我将蒙版路径上的填充更改为白色以外的其他内容时,什么也没有出现(不知道为什么会这样)。

我希望能够将代码压缩成这样:

<div class="vector">
    <svg xmlns="http://www.w3.org/2000/svg" image-rendering="optimizeQuality" viewBox="0 0 510 360" shape-rendering="geometricPrecision" fill-rule="evenodd">
                                
        <defs>
            <mask id="bg-c" maskContentUnits="objectBoundingBox">
                <path fill="white" transform="scale(0.001965, 0.002800)" d="M148.500 3.099 C 113.488 6.747,84.700 13.892,62.351 24.482 C 43.108 33.600,33.681 41.189,22.444 56.609 C 7.759 76.760,4.338 86.781,5.282 106.890 C 5.880 119.655,7.968 128.762,13.637 143.340 C 23.834 169.561,23.443 167.883,23.464 185.500 C 23.479 197.898,23.041 203.414,21.520 210.000 C 18.603 222.635,18.745 240.097,21.847 249.975 C 30.657 278.033,52.991 299.700,93.500 319.490 C 109.905 327.505,121.171 331.756,142.440 337.958 C 190.118 351.861,258.762 358.886,289.318 352.989 C 307.253 349.528,331.710 340.925,364.262 326.626 C 392.030 314.428,408.965 308.298,425.480 304.468 C 451.051 298.538,471.322 283.403,481.509 262.633 C 487.363 250.696,489.054 243.962,489.701 230.000 C 490.547 211.754,486.958 197.061,477.358 179.483 C 469.662 165.389,471.689 154.395,491.588 102.309 C 506.590 63.041,509.743 48.582,505.331 39.285 C 501.149 30.471,482.609 22.301,459.167 18.940 C 445.334 16.957,405.463 18.286,371.500 21.862 C 319.125 27.376,299.077 27.919,277.500 24.407 C 270.080 23.199,265.779 21.647,253.000 15.566 C 234.292 6.663,230.109 5.365,214.006 3.470 C 200.434 1.873,162.341 1.658,148.500 3.099">
                </path>
            </mask>
        </defs>
        <image loading="lazy" data-href="https://images.pexels.com/photos/910411/pexels-photo-910411.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1" alt="" width="100%" height="100%" mask="url(#bg-c)" preserveAspectRatio="xMidYMid slice">    
        </image>
    </svg>
</div>

您可以通过在 <defs> 中创建可重复使用的定义来避免重复的 <path> 元素。

<defs>
   <path id="maskPath" d="..." />
</defs>

注意:您的可重用路径定义不得包含任何填充 属性 如果您需要为不同的实例更改它的填充(例如蒙版和背景形状)

你的面具看起来像这样:

  <mask id="bg-c" >
    <use href="#maskPath" fill="white" />
  </mask>

例子

//emulate loading by setTimeout delay
emulateLazyLoad();

function emulateLazyLoad() {
  let lazyImages = document.querySelectorAll('[loading="lazy"]');
  lazyImages.forEach(function(lazy) {
    let imgHref = lazy.dataset.href;
    setTimeout(function() {
      if (lazy.nodeName.toLowerCase() == "image") {
        lazy.setAttribute("href", imgHref);
      } else {
        lazy.src = imgHref;
      }
      lazy.classList.replace("loading", "loaded");
    }, 1000);
  });
}
svg {
  width: 50%;
  display: inline-block;
}

.image {
  transition: 0.3s opacity;
}

.loading {
  opacity: 0;
}

.loaded {
  opacity: 1;
}
<div class="vector">
  <svg xmlns="http://www.w3.org/2000/svg" image-rendering="optimizeQuality" viewBox="0 0 510 360" shape-rendering="geometricPrecision" fill-rule="evenodd">
    <defs>
      <path id="maskPath" d="M148.500 3.099 C113.488 6.747,84.700 13.892,62.351 24.482 C 43.108 33.600,33.681 41.189,22.444 56.609 C 7.759 76.760,4.338 86.781,5.282 106.890 C 5.880 119.655,7.968 128.762,13.637 143.340 C 23.834 169.561,23.443 167.883,23.464 185.500 C23.479 197.898,23.041 203.414,21.520 210.000 C 18.603 222.635,18.745 240.097,21.847 249.975 C 30.657 278.033,52.991 299.700,93.500 319.490 C109.905 327.505,121.171 331.756,142.440 337.958 C 190.118 351.861,258.762 358.886,289.318 352.989 C 307.253 349.528,331.710 340.925,364.262 326.626 C392.030 314.428,408.965 308.298,425.480 304.468 C 451.051 298.538,471.322 283.403,481.509 262.633 C 487.363 250.696,489.054 243.962,489.701 230.000 C490.547 211.754,486.958 197.061,477.358 179.483 C 469.662 165.389,471.689 154.395,491.588 102.309 C 506.590 63.041,509.743 48.582,505.331 39.285 C501.149 30.471,482.609 22.301,459.167 18.940 C 445.334 16.957,405.463 18.286,371.500 21.862 C 319.125 27.376,299.077 27.919,277.500 24.407 C 270.080 23.199,265.779 21.647,253.000 15.566 C 234.292 6.663,230.109 5.365,214.006 3.470 C 200.434 1.873,162.341 1.658,148.500 3.099" />
      <mask id="bg-c">
        <use href="#maskPath" fill="white" />
      </mask>
    </defs>
    <use id="bgShape" href="#maskPath" fill="gray" />
    <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle">Loading ...</text>
    <image class="image loading" loading="lazy" data-href="https://images.pexels.com/photos/910411/pexels-photo-910411.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1" alt="" width="100%" height="100%" mask="url(#bg-c)" preserveAspectRatio="xMidYMid slice" />
   
  </svg>
</div>

放置另一个 <use>blob 形状的实例来创建背景元素,如下所示:

<use id="bgShape" href="#maskPath" fill="gray" />
<text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle">Loading ...</text>
<image class="image loading" loading="lazy" data-href="https://images.pexels.com/photos/910411/pexels-photo-910411.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1" alt="" width="100%" height="100%" mask="url(#bg-c)" preserveAspectRatio="xMidYMid slice" />