第 25 天:如何将 SVG 图像分解为多个组件

如果你已经学到了这一步,那么请为自己鼓掌,因为你刚刚学习了 SVG 的基础知识和许多很酷的使用案例。

如果你继续写下去,开始写越来越复杂的 SVG,那么你可能会发现它们的代码开始有点失控。这时,你可以将它们分解成组件。这里我们再次使用 React,但同样的概念也适用于你可能使用的任何其他前端库。不过要注意的是,各组件根部只有一个 SVG 元素,因为仍然只有一张图片。子组件的内容都在组元素中。

function SnowGlobe() {
  return (
    <svg width="200" height="200" viewBox="-100 -100 200 200">
      <clipPath id="snow-globe">
        <circle cx="0" cy="0" r="80" />
      </clipPath>

      <g clip-path="url(#snow-globe)">
        <rect x="-100" y="-100" width="200" height="200" fill="#F1DBC3" />
        <circle cx="0" cy="380" r="350" fill="#F8F4E8" />

        <Threes />
        <Snow />
      </g>

      <circle cx="0" cy="0" r="80" fill="none" stroke="gray" stroke-width="2" />
    </svg>
  );
}

function Threes() {
  return (
    <g>
      <defs>
        <g id="tree">
          <polygon points="-10,0 10,0 0 -50" fill="#38755b" />
          <line x2="0" y2="10" stroke="#778074" stroke-width="2" />
        </g>
      </defs>

      <use href="#tree" x="-20" y="25" transform="scale(1.8)" />
      <use href="#tree" x="-10" y="40" transform="scale(1)" />
      <use href="#tree" x="30" y="40" transform="scale(0.8)" />
      <use href="#tree" x="40" y="30" transform="scale(1.2)" />
    </g>
  );
}

function Snow() {
  return (
    <g class="snowing">
      <defs>
        <circle id="big" cx="0" cy="0" r="5" fill="white" />
        <circle id="small" cx="0" cy="0" r="3" fill="white" />
      </defs>

      <use href="#big" x="0" y="0" class="flake fast" />
      <use href="#big" x="-50" y="-20" class="flake fast opaque" />
      <use href="#big" x="30" y="-40" class="flake fast" />
      <use href="#big" x="50" y="-20" class="flake fast opaque" />
      <use href="#big" x="30" y="50" class="flake slow" />
      <use href="#big" x="-70" y="-80" class="flake slow opaque" />
      <use href="#big" x="30" y="50" class="flake slow" />
      <use href="#big" x="90" y="-80" class="flake slow opaque" />
      <use href="#small" x="10" y="-50" class="flake slow" />
      <use href="#small" x="-50" y="-60" class="flake slow opaque" />
      <use href="#small" x="30" y="70" class="flake slow" />
      <use href="#small" x="10" y="-80" class="flake slow opaque" />
    </g>
  );
}
.flake {
  animation-duration: inherit;
  animation-name: snowing;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}

@keyframes snowing {
  from {
    transform: translate(0, -100px);
  }
  to {
    transform: translate(0, 100px);
  }
}

.flake.opaque {
  opacity: 0.7;
}

.flake.slow {
  animation-duration: 5s;
}

.flake.fast {
  animation-duration: 3s;
}
分享: