在动画中保持 SVG 图案的填充

问题描述 投票:0回答:1

我有一个以原点为中心的动画 SVG。有以原点为中心的 256x256 路径。这条路径有一个填充,它是一个同样为 256x256 的渐变矩形图案。路径动画扩展到视图框的整个宽度和高度。理想情况下,我希望路径的填充以原点为中心,但是,它位于路径的左上角,因此会随着动画移动。

我已经尝试对填充进行动画处理(

x
y
transform
属性)以假装填充保持居中,但这有跨浏览器问题。我尝试在 CSS 和普通 SVG 中对所有属性进行动画处理,并且每种方式都倾向于在一种浏览器而不是另一种浏览器上工作。例如,
animateTransform
样条缓动在 Chrome 上不起作用,但它们在 FireFox 上do。或者,CSS cubic-bezier 动画缓动在 Chrome 上有效,但在 FireFox 上。

这是当前的 SVG:

<svg
  width="1024"
  height="1024"
  viewBox="-512 -512 1024 1024"
  fill="none"
  overflow="hidden"
  xmlns="http://www.w3.org/2000/svg"
  preserveAspectRatio="xMinYMin meet"
>
  <style>
    #cube {
      transform-box: fill-box;
      transform: translate(-50%, -50%);
      z-index: 1;
    }

    #origin,
    #origin_label {
      fill: red;
      stroke: darkred;
      stroke-width: 0;
      font-family: sans-serif;
      font-size: 30px;
    }
  </style>

  <circle id="origin" cx="0" cy="0" r="10" />
  <text id="origin_label" x="15" y="30">(0, 0)</text>

  <use href="#cube" stroke-width="2">
    <animate
      attributeName="stroke"
      dur="6s"
      repeatCount="indefinite"
      values="#FF9AA2;#FFB7B2;#FFDAC1;#E2F0CB;#B5EAD7;#C7CEEA;#FF9AA2"
    />
  </use>

  <defs>
    <!-- EVERYTHING TOGETHER -->
    <g id="cube">
      <use
        href="#cube_outline"
        stroke-linejoin="round"
        stroke-width="16"
        fill="url(#sky_bg)"
      />
    </g>

    <!-- GRADIENT FILL -->
    <pattern
      id="sky_bg"
      x="0%"
      y="0%"
      width="100%"
      height="100%"
      patternUnits="userSpaceOnUse"
      patternContentUnits="userSpaceOnUse"
    >
      <rect
        width="256"
        height="256"
        x="0"
        y="0"
        fill="url(#sky)"
        id="starpat"
      ></rect>
    </pattern>

    <!-- THICK OUTER LINE-->
    <g id="cube_outline">
      <path>
        <animate
          attributeName="d"
          dur="3s"
          calcMode="spline"
          keyTimes="0;0.5;1"
          repeatCount="1"
          fill="freeze"
          keySplines="0.4 0 0.2 1;0.4 0 0.2 1"
          values="M 0 64 L 118 0 L 236 64 L 236 192 L 118 256 L 0 192 Z;
          M 0 0 L 236 0 L 236 0 L 236 256 L 0 256 L 0 256 Z;
          M 0 0 L 1010 0 L 1010 0 L 1010 1010 L 0 1010 L 0 1010 Z"
        />
      </path>
    </g>

    <linearGradient id="sky" gradientTransform="rotate(90)">
      <stop offset="0.5" stop-color="#141417" />
      <stop offset="1" stop-color="#40354a" />
    </linearGradient>
  </defs>
</svg>

我仅限于 CSS、HTML 和 SVG,因为任何 javascript 都将被清理掉。 是否可以使填充居中?或者我应该采取另一种方法吗?

css animation svg css-animations svg-animate
1个回答
0
投票

由于您将 svg 形状组合在一起,当 cube_outline 开始扩展时,<g> 标签的宽度和高度会发生变化。为了避免这种情况,我只使用了第二个 <use> 标签并删除了以避免分组并将矩形更改为路径以模仿大纲在展开之前所做的相同动画。希望这能解决您的问题。

    <svg
width="1024"
height="1024"
viewBox="-512 -512 1024 1024"
fill="none"
overflow="hidden"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMinYMin meet"
>
<style>
  #cube_outline,#starpat {
    transform-box: fill-box;
    transform: translate(-50%, -50%);
    z-index: 1;
  }
  
  #origin,
  #origin_label {
    fill: red;
    stroke: darkred;
    stroke-width: 0;
    font-family: sans-serif;
    font-size: 30px;
  }
</style>
  
<circle id="origin" cx="0" cy="0" r="10" />
<text id="origin_label" x="15" y="30">(0, 0)</text>
  <use
    href="#cube_outline"
    stroke-linejoin="round"
    stroke-width="16"
  />
  <use
    href="#starpat"
  />
<defs>
  <!-- EVERYTHING TOGETHER -->

  
  <!-- GRADIENT FILL -->
    <path
      width="256"
      height="256"
      x="0"
      y="0"
      fill="url(#sky)"
      id="starpat"
    >
      <animate
        attributeName="d"
        dur="1.5s"
        calcMode="spline"
        keyTimes="0;1"
        repeatCount="1"
        fill="freeze"
        keySplines="0.4 0 0.2 1"
        values="M 0 64 L 113 0 L 226 64 L 226 187 L 113 246 L 0 182 Z;
        M 0 0 L 226 0 L 226 0 L 226 246 L 0 246 L 0 246 Z;"
      />
  </path>
  
  <!-- THICK OUTER LINE-->
  <g id="cube_outline">
    <path>
      <animate
        attributeName="d"
        dur="3s"
        calcMode="spline"
        keyTimes="0;0.5;1"
        repeatCount="1"
        fill="freeze"
        keySplines="0.4 0 0.2 1;0.4 0 0.2 1"
        values="M 0 64 L 118 0 L 236 64 L 236 192 L 118 256 L 0 192 Z;
        M 0 0 L 236 0 L 236 0 L 236 256 L 0 256 L 0 256 Z;
        M 0 0 L 1010 0 L 1010 0 L 1010 1010 L 0 1010 L 0 1010 Z"
      />
      <animate
        attributeName="stroke"
        dur="6s"
        repeatCount="indefinite"
        values="#FF9AA2;#FFB7B2;#FFDAC1;#E2F0CB;#B5EAD7;#C7CEEA;#FF9AA2"
      />
    </path>
  </g>
  
  <linearGradient id="sky" gradientTransform="rotate(90)">
    <stop offset="0.5" stop-color="#141417" />
    <stop offset="1" stop-color="#40354a" />
  </linearGradient>
</defs>
  </svg>

© www.soinside.com 2019 - 2024. All rights reserved.