svg 绘制不规则形状展示图片

svg 持续绘制不规则形状展示图片

  • 准备一组从 a 形状变化至 b 形状至 c 形状 等 svg 集合
  • 利用 flubber 库生成从 a 形状变化至 b形状中间的过渡 svg 帧. 传送带 : https://github.com/veltman/flubber
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .d-block {
      display: block;
    }

    .w-full {
      width: 100%;
    }
  </style>
  <script src="https://unpkg.com/flubber@0.3.0"></script>
</head>

<body>
  <custom-svg-clipped-draw class="d-block">
    <svg viewBox="0 0 1920 1080" preserveAspectRatio="none">
      <defs>
        <clipPath id="wave-clip">
          <path id="animate" fill="black"
            d="M68,108c5.1-12.1,18-16.5,30.9-17.2,164.3-2.1,346.8,11.3,510.2,1.9,114.3-4.2,230.9-12.2,338.5-13.9,262.3,14.4,535.2,25.5,785-2.2,50.9-4,117.6-6,115.6,66.5-10.5,134.9-4.7,278.3,0,415.6,1.2,91-2.7,185.7,8.2,275.8,15.4,176-15,157.7-174.8,151.9-80.6-.5-177.3-3-260.4.2-150.3,7.2-298.9,25-448.2,15-179.2-10.1-354.6-7.9-532.9,1.7-99,8.2-192.4-15.6-290.5-14.9-24.7-.6-54.5,8.5-76.2-5.8-20.9-18.6-11.6-54.1-10-79.5,2.9-25.1,7.3-50.6,10-75.6,13.4-96.6-6.4-194.6-7.4-291.7-.7-131.4,17.1-263.3-1.8-393-.3-11.9-.6-24.1,3.9-34.7v-.2h0Z" />
        </clipPath>
      </defs>
      <foreignObject x="0" y="0" width="100%" height="100%" clip-path="url(#wave-clip)">
        <picture>
          <source media="(max-width: 900px)" srcset="./pics/wave.jpg">
          <img class="clipped-img" src="./pics/wave.jpg" />
        </picture>
      </foreignObject>
    </svg>

    <script class="as-svg-data" type="application/json">
      [
        "M68,108c5.1-12.1,18-16.5,30.9-17.2,164.3-2.1,346.8,11.3,510.2,1.9,114.3-4.2,230.9-12.2,338.5-13.9,262.3,14.4,535.2,25.5,785-2.2,50.9-4,117.6-6,115.6,66.5-10.5,134.9-4.7,278.3,0,415.6,1.2,91-2.7,185.7,8.2,275.8,15.4,176-15,157.7-174.8,151.9-80.6-.5-177.3-3-260.4.2-150.3,7.2-298.9,25-448.2,15-179.2-10.1-354.6-7.9-532.9,1.7-99,8.2-192.4-15.6-290.5-14.9-24.7-.6-54.5,8.5-76.2-5.8-20.9-18.6-11.6-54.1-10-79.5,2.9-25.1,7.3-50.6,10-75.6,13.4-96.6-6.4-194.6-7.4-291.7-.7-131.4,17.1-263.3-1.8-393-.3-11.9-.6-24.1,3.9-34.7v-.2h0Z",
        "M1729.6,983.7c-130.2-8.2-184.8,16.3-248.7,16.4-221.4,0-343-41.9-496,1.1-112.5,16.8-247.4-27.1-389.4-26.7-147.3-10.4-310.7,15-454.9,24.2-19.5.6-43.1,1.2-58.3-8.9-14.7-10.1-18.5-29.6-20-63.2-6-98.5,37-196.2,40.4-297.6,3.2-107.6-39.5-187.1-41.2-245.5-4.8-72.4,7.6-164.7,3.3-206.2-3.7-37.1-19.6-106.9,37.7-102,14.1.5,32,4,54,9,105.3,28.3,255.9-9.9,344-8,90.2.3,150.4,1.3,226.4,7.3,89.2,7.9,109.6,20.5,187.7,19.5,27.3,0,47.8-.3,72.7-1.1,116.9-1.3,152.2-24.3,283.6-25.7,90.6-2.5,218.7,59.2,344.6,18.6,49-10.5,104-14.7,152.7-17,31.4,0,83.3-10.1,89.4,28.9,11.9,61.8-24.5,121-32.9,178.3-13.6,103.3,37.5,215.4,32.8,377.5-1.7,54.1-15.3,74.7-12.1,151.1.6,14.6,2,32.7,3.6,47.9-.7,32.5,37,140.6-25.7,132.4,0,0-62.2-8.5-93.7-10.4h0Z",
        "M1818.9,991.5c-161.4-29.6-370.2,5.3-448.7,5.9-211,0-292.8-83.7-438.5-43.1-169.3,65.4-292.9,62.8-495.7,19.3-25.5-4.6-58.1-7.6-79.4-7.2-81.9,1.9-144.4,42.1-229.1,27.1-44.3-7.1-61.7-39.9-61.9-82.8-1.7-98,37.6-242.3,40.5-343.9.3-14.4-2.8-30.7-6.5-40.8-20.2-46.2-45.9-48.9-38.2-108.5,2.7-20.9,8.6-41.4,11.6-61.8,24.7-109.8-34.9-189.3,16.4-253.3,43.3-47.7,142.6-21.6,212.9-6.3,61.3,11.2,93.3-.5,142.2-9.4,65.1-9.1,145-2.1,199.7-2,122.1.9,212.9,24.8,323,24.3,32.4-.1,53.6-.6,82.8-2,91.7-2.5,101.2-23.5,216.7-24.5,62.7-4.8,103.4,29,175.8,32,18.2.6,38.5-1,61.7-5.8,65.5-18.6,198-21.7,264.7-24.9,27-.7,62.2-4.1,79,17.5,34.2,58.4-13.7,143.7-25.5,202.5-19.4,111.4,35.4,214.3,30.6,382.1-1.4,52.6-16.3,65.8-11.8,135.4.5,11.3,1.7,23,2.7,33.6,2.1,19.2,5.2,45.3,9.2,70.7,4.8,27.8,3.9,72.9-34.2,65.8h-.2.2Z",
        "M1857.8,973.5c-2.6,18.4-20.3,26.4-38,24.9-26.6-2.3-38.4-5.4-57.5-7.3-141.4-16-218,15.1-288.5,13.9-44-.3-86.1-3.7-125.1-13.9-71-18.9-71.6-48-166.9-24.6-130.5,36.1-491.7,35.5-859.8,38.2-81.2-.4-133.2-8.1-208.3-.5-31.6,3.2-47.4-16.5-50.4-31.6-15-74.8,26.4-483.2,21.7-594.3-2.5-107.8-21.7-171.6-21.6-263.5-.6-21.5,1.7-38.5,27.6-38.1,99.2,2.9,481.9-6,628.8,6.6,107.4,10.6,148.6,25.4,248.5,19.7,32.5-.7,73.8-2.6,102.6-5.8,213.8-37.5,529.1-14.8,757.5-20.6,6.2,0,14.8,1,20.5,5.4,4.1,2.7,6.7,8.6,7.7,14.5,2.2,66.9-.3,123.5-1.8,178.6-7.5,246.2-43.8,259.2-35.1,451.2,5.6,41.2,22.5,60.2,31.9,130,4.9,39.1,12.2,75.2,6.2,117.2h.1Z",
        "M1726.2,972.1c-39.2-11.9-80.1-14.2-116-10.3-41.3,6-78.8,19.9-134,24.2-50.7,5.9-101.3-4.6-132.4-14.7-21.5-6-40.6-10.6-63.9-10.5-18,0-35.9,3.6-53.7,3-67.1,1.1-92.9-35.1-133.6-40.1-109.8-12.5-174.6,100.3-259.4,64.5-101-27.4-119.3-106.8-186.6-77.3-28.2,12.5-61,26-88.3,34.2-65.9,19.1-75.7,2.1-166.4,10.2-63.3,1.8-167,52.3-226.3,49.6-30.7-2.1-69.8-10.5-88.1-39.5-30.6-48.5-17.9-146.9,12.6-231.1,6.8-23.9,11.9-50.1,13.6-73.6,1.8-28.4,1.4-54.4-6.2-78.8-34.3-76.3,28.5-151.4,18.3-211.1-3.1-15.4-7.9-30.5-12.7-46.6-9.6-32.2-22.4-65.6-29-97.2-7.9-49.7,3.7-125.2,64-142.8,34.8-11.9,72.6-10.1,109.2-6.4,128.1,19.4,258.3.9,386.4,17.2,94.5,11,184.1,38,279.9,36.8,103.6-1.4,132-26.4,229.1-30.1,118.3-5.9,218.9.6,362.9,10,81.1,15.1,330.5-75.3,351.9,19.8,3.2,13,3,27.4,1.3,40.1-8.2,53.2-7.4,107.3-5.8,161.4,2.4,73.5,5,151.7-9.9,226.8-12.4,63.2-31.6,121.1-18.5,183.3,11.2,70.8,43,174.9,25.6,221.8-10.8,29.1-41.8,32.1-123.9,7.1h0Z",
        "M1829.3,999.2c-32.2,2.6-93.4-8.8-149-10.8-314.5-11-790.8,25.2-934.2,12.8-86.9-5.3-158.6-38-194.7-35-85.5,12.5-97.1,36.5-196.3,36.7-87.9,2.3-72.4,2.1-183.4,2.1-99.1,0-116.1-27.4-118.7-53.3-6.8-66.8,20.3-105.4,23.7-160,2.8-67.2-13.7-124.9-10.4-157.4,20.1-201.8-16.3-285.1-5.6-533.2,1-22.1,9-25.7,29.2-25.7h64.8c104.7.2,235.3,0,343.6,0,332,0,552,37.9,983.9,25.2,123.5-4.6,287.6-28.2,344.6-25.2,12.9.7,27.9,7.8,30.1,21.6,14.6,89.4-38.7,505.4-38.9,593.2-1.5,56.7,16.5,93.7,28.6,153.2,7.2,34.3,17.8,100.8,11.4,130.4-2.7,12.5-14,24.3-28.6,25.5h0Z",
        "M67.6,104.3c6.2-14.4,20.7-18.9,36-17.3,308.2,32.6,470.9,4.9,810.8-11.5,211.6-7.8,485.2,78,723.4,50.8,53.2-7,100.6-37.3,141.6-44.5,15.6-2.8,30.9-2.2,45.4,3.9,34.4,12.8,15,52.6,7.7,81.7-41.9,114.9,9.8,245.7,14.5,364.6,2.1,42-22.7,44.5-38.8,75.1-4.6,10.3-5.8,22.2-4.8,33.1,5.7,50.6,46.2,142,52.9,188.7,38.2,266.1-226.5,114.6-365.1,86.7-22.8-5.1-43.4-8.7-66-9-119.6-2.9-250,107.9-382.7,97.6-41.1-2.5-84.3-10.4-123.5-21.6-12.9-3.9-27.7-9.2-39.4-14.4-52.5-20-74.2-61.4-133.1-55.6-39,5.8-82.4,19.6-118.3,26.7-219.7,51.4-333,46.6-454.2,40.3-41.4,0-118.2,25.4-113.7-42.8,5.1-42.1,62.8-110.8,71.9-153.7,3.8-16.7-2-35.2-11.8-47.5-13.7-17.8-35.7-35.5-45.4-60.2-33.1-95.6,53.9-339.4,29.4-437.9-10.8-39.7-33.4-49.7-39.8-87.3-3-15.3-2.7-32,3-46v-.2.2Z",
        "M67.7,107.8c6.6-15.9,26.4-17.8,42-17.5,111.4,1.2,228.2,19.6,340.1,27.4,35.4,2.4,69.2,4.3,104.2,3.2,132.1-6.1,277-47.2,409.8-41.8,124.5,2.4,220.6,37.4,348.3,31.4,146.8-4.2,290.7-19.3,414.2-33.7,21.2-1.9,48-3.5,71.9,1.4,11.8,2.5,21.9,6.5,30,14.1,10.6,10.7,12.6,26.8,13.4,48.5-.5,59.8-15.9,126-16.3,188.2-1.8,72.9,15,118.9,19.2,198.2,4.8,60.9-12.6,128.6-13.6,191.6,1.9,48,10.5,60.8,24.9,143,11.8,67.3,2.5,137.2-85,131.7-95-1.9-198.3-23.3-313.2-27.8-95,1.2-164.9,35.3-258,39.2-50.3,1.5-132.9-14.3-192.2-21.6-91.6-13.7-177.3,5.9-266.7,16.7-115,18.2-225.9-20.2-340-24.9-72-.3-155.8,13.5-225,12.4-15.9-.4-32.3.2-48.1,1.2-18.1.9-39.2,4.2-54.8-6.8-36.3-35.3,15.8-112.5,16.3-204.1.7-10.4.8-19.5.9-29.7,2.8-68.7-26.5-111.4-23.3-185.3-.2-26.9,1.3-55.5,3.4-81,5.3-62.5,18.7-80,19.4-157.1,2.4-56.9-15.8-107.4-23.9-162.2-2.1-17.8-4.3-37.4,2-54.4v-.2h.1Z",
        "M68,108c5.1-12.1,18-16.5,30.9-17.2,164.3-2.1,346.8,11.3,510.2,1.9,114.3-4.2,230.9-12.2,338.5-13.9,262.3,14.4,535.2,25.5,785-2.2,50.9-4,117.6-6,115.6,66.5-10.5,134.9-4.7,278.3,0,415.6,1.2,91-2.7,185.7,8.2,275.8,15.4,176-15,157.7-174.8,151.9-80.6-.5-177.3-3-260.4.2-150.3,7.2-298.9,25-448.2,15-179.2-10.1-354.6-7.9-532.9,1.7-99,8.2-192.4-15.6-290.5-14.9-24.7-.6-54.5,8.5-76.2-5.8-20.9-18.6-11.6-54.1-10-79.5,2.9-25.1,7.3-50.6,10-75.6,13.4-96.6-6.4-194.6-7.4-291.7-.7-131.4,17.1-263.3-1.8-393-.3-11.9-.6-24.1,3.9-34.7v-.2h0Z"
      ]
    </script>
  </custom-svg-clipped-draw>

  <script>
    class CustomSvgClippedDraw extends HTMLElement {
      constructor() {
        super()
        this.getSvgPaths()
        if (!this.pathList.length) return
        this.handleScrollPreload()
      }

      getSvgPaths() {
        const $data = this.querySelector('.as-svg-data')
        if ($data !== null) {
          this.pathList = JSON.parse($data.textContent ?? '[]')
        }
      }

      handleScrollPreload() {
        const observer = new IntersectionObserver(entries => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              this.handleGeneratePath()
              this.hendleOperationAnimation()
              observer.unobserve(entry.target)
            }
          })
        }, {
          rootMargin: '500px 0px 500px 0px',
          threshold: 0
        })
        observer.observe(this)
      }

      handleGeneratePath() {
        let newPathList = [],
          pathList = this.pathList
        for (let i = 0; i < pathList.length - 1; i++) {
          const flubberRes = flubber.interpolate(pathList[i], pathList[i + 1], {
            maxSegmentLength: 10
          })
          for (let time = 0; time <= 1; time += 0.01) {
            newPathList.push(flubberRes(time.toFixed(2)))
          }
        }
        this.newPathList = newPathList
      }

      hendleOperationAnimation() {
        let pathIndex = 0
        let lastTime = performance.now()
        const targetDelay = 16

        const changePath = () => {
          const currentTime = performance.now()
          const elapsedTime = currentTime - lastTime
          // 如果经过的时间大于等于目标延迟时间,则执行下一帧
          if (elapsedTime >= targetDelay) {
            if (pathIndex + 1 >= this.newPathList.length) {
              pathIndex = 0
            } else {
              pathIndex++
            }
            this.querySelector('#animate')?.setAttribute('d', this.newPathList[pathIndex])
            lastTime = currentTime;
          }
          requestAnimationFrame(changePath)
        }
        requestAnimationFrame(changePath)
      }
    }

    if (customElements.get('custom-svg-clipped-draw') === undefined) {
      customElements.define('custom-svg-clipped-draw', CustomSvgClippedDraw)
    }
  </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值