SVG齿轮动画在鼠标离开时

huangapple go评论59阅读模式
英文:

SVG gear animation on mouse leave

问题

我有关于SVG图标动画的问题。

目前,在悬停鼠标时,齿轮开始旋转。然而,我需要它们在鼠标不再悬停时继续旋转,并且齿轮会在1秒内逐渐减速停止。

我尝试了各种方法,但不幸的是,我没有找到解决方案。有人能帮我吗?

此外,有人知道如何在SVG中增加特定路径的宽度而不影响其高度吗?当使用 transform: scale 时,它也会缩放高度,但我只需要缩放长度。

HTML:

<div class="container">
  <svg width='130' height='144' viewBox='0 0 130 144' fill='none' class="svg" xmlns='http://www.w3.org/2000/svg'>
    <g clipPath='url(#clip0_297_2779)'>
      <!-- 其他路径 -->
    </g>
    <defs>
      <clipPath id='clip0_297_2779'>
        <rect width='129.52' height='143.09' fill='white' />
      </clipPath>
    </defs>
  </svg>
</div>

CSS:

.container {
  margin: 20px;
}

svg * {
  transform-box: fill-box;
}

svg:hover .gear,
svg:hover .bigGear {
  animation: stoneAn 2s infinite linear;
}

.gear,
.bigGear {
  transform-origin: center;
}

@keyframes stoneAn {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(90deg);
  }
}

/* 其他动画 */

(注意:由于篇幅所限,这里只提供了部分HTML和CSS的翻译,具体部分请查看原文)

英文:

I have problem with svg icon animation.

Currently, upon hovering the cursor, the gears start rotating. However, I need them to continue rotating after the cursor is no longer hovering, and gears will gradually slow down to a stop over a period of 1 second.

I've tried various approaches, but unfortunately, I haven't come up with a solution. Can someone help me?

Additionally, does anyone know how to increase the width of a specific path in the SVG without affecting its height? When using a transform: scale, it also scales the height, but I only need to scale the length.

HTML:

&lt;div class=&quot;container&quot;&gt;
  &lt;svg width=&#39;130&#39; height=&#39;144&#39; viewBox=&#39;0 0 130 144&#39; fill=&#39;none&#39; class=&quot;svg&quot; xmlns=&#39;http://www.w3.org/2000/svg&#39;&gt;
    &lt;g clipPath=&#39;url(#clip0_297_2779)&#39;&gt;
      &lt;path d=&#39;M70.6202 42.33L70.2802 51.97C72.0402 53.68 72.9302 54.54 74.7002 56.25L84.3202 55.61C85.3535 57.9966 86.3869 60.3866 87.4202 62.78L80.3702 69.35L80.4702 75.5L87.7302 81.85L84.8602 89.11L75.2202 88.77L70.9402 93.19L71.5802 102.81L64.4102 105.91L57.8402 98.86C55.3802 98.9 54.1402 98.92 51.6902 98.96L45.3402 106.22L38.0802 103.35L38.4202 93.71L34.0002 89.43L24.3802 90.07L21.2802 82.9L28.3302 76.33L28.2302 70.18L20.9702 63.83L23.8402 56.57L33.4802 56.91L37.7602 52.49L37.1202 42.87C39.5069 41.8366 41.8969 40.8033 44.2902 39.77L50.8602 46.82L57.0102 46.72L63.3602 39.46L70.6202 42.33Z&#39; class=&#39;bigGear&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M24.26 75.98C11.71 75.98 1.5 65.77 1.5 53.22C1.5 40.67 11.71 30.46 24.26 30.46C24.83 30.46 25.45 30.49 26.14 30.54L27.4 30.64L27.71 29.42C31.95 12.98 46.78 1.5 63.78 1.5C76.85 1.5 88.74 8.17 95.57 19.34L96.06 20.15L97 20.05C98 19.94 99 19.89 99.97 19.89C115.43 19.89 128.01 32.47 128.01 47.93C128.01 63.39 115.43 75.97 99.97 75.97H24.26V75.98Z&#39; fill=&#39;white&#39; /&gt;
      &lt;path d=&#39;M63.78 3C76.33 3 87.73 9.4 94.29 20.12L95.28 21.74L97.16 21.54C98.1 21.44 99.05 21.39 99.97 21.39C114.61 21.39 126.51 33.3 126.51 47.93C126.51 62.56 114.6 74.47 99.97 74.47H24.26C12.54 74.47 3 64.93 3 53.21C3 41.49 12.54 31.95 24.26 31.95C24.8 31.95 25.37 31.98 26.02 32.03L28.54 32.24L29.17 29.79C33.24 14.02 47.47 3 63.78 3ZM63.78 0C45.73 0 30.57 12.34 26.27 29.05C25.61 29 24.94 28.96 24.26 28.96C10.86 28.96 0 39.82 0 53.22C0 66.62 10.86 77.48 24.26 77.48H99.98C116.3 77.48 129.52 64.25 129.52 47.94C129.52 31.63 116.29 18.4 99.98 18.4C98.92 18.4 97.88 18.46 96.85 18.57C90.05 7.43 77.78 0 63.78 0Z&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M63.5201 0C63.5201 0 63.4301 0 63.3901 0V3C63.3901 3 63.4801 3 63.5201 3C83.2301 3 99.2601 19.03 99.2601 38.74C99.2601 58.45 83.2301 74.48 63.5201 74.48C63.4801 74.48 63.4301 74.48 63.3901 74.48V77.48C63.3901 77.48 63.4801 77.48 63.5201 77.48C84.9201 77.48 102.26 60.14 102.26 38.74C102.26 17.34 84.9201 0 63.5201 0Z&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M95.3602 141.59L92.8602 134.55L87.0002 132.12L80.2502 135.33L77.2502 132.33L80.4502 125.58L78.0302 119.72L70.9902 117.22V112.97L78.0302 110.47L80.4502 104.6L77.2502 97.86L80.2502 94.86L87.0002 98.06L92.8602 95.63L95.3602 88.6H99.6102L102.11 95.63L107.97 98.06L114.72 94.86L117.72 97.86L114.52 104.6L116.94 110.47L123.98 112.97V117.22L116.94 119.72L114.52 125.58L117.72 132.33L114.72 135.33L107.97 132.12L102.11 134.55L99.6102 141.59H95.3602Z&#39; fill=&#39;white&#39; /&gt;
      &lt;path d=&#39;M98.5498 90.1L100.47 95.51L100.92 96.77L102.15 97.28L104.61 98.3L106.79 99.2L108.02 99.71L109.22 99.14L114.4 96.68L115.48 97.76L115.9 98.18L113.44 103.36L112.87 104.56L113.38 105.79L114.39 108.23L115.3 110.42L115.81 111.65L117.07 112.1L122.48 114.02V116.15L117.07 118.07L115.81 118.52L115.3 119.75L114.56 121.55L113.39 124.39L112.88 125.62L113.45 126.82L115.91 132L115.49 132.42L114.41 133.5L109.23 131.04L108.03 130.47L106.8 130.98L105.59 131.48L102.16 132.9L100.93 133.41L100.48 134.67L98.5598 140.08H96.4298L94.5098 134.67L94.0598 133.41L92.8298 132.9L89.3998 131.48L88.1898 130.98L86.9598 130.47L85.7598 131.04L80.5798 133.5L79.0698 131.99L81.5298 126.81L82.0998 125.61L81.5898 124.38L80.3198 121.31L79.6698 119.75L79.1598 118.52L77.8998 118.07L72.4898 116.15V114.02L77.8998 112.1L79.1598 111.65L79.6698 110.42L80.5498 108.3L81.5898 105.79L82.0998 104.56L81.5298 103.36L79.0698 98.18L80.5798 96.67L85.7598 99.13L86.9598 99.7L88.1898 99.19L90.3698 98.29L92.8298 97.27L94.0598 96.76L94.5098 95.5L96.4298 90.09H98.5598M100.68 87.09H94.3198L91.6898 94.49C89.8398 95.26 88.9098 95.64 87.0598 96.41L79.9598 93.04L75.4598 97.54L78.8298 104.64C78.0598 106.49 77.6798 107.42 76.9098 109.27L69.5098 111.9V118.26L76.9098 120.89C77.6798 122.74 78.0598 123.67 78.8298 125.52L75.4598 132.62L79.9598 137.12L87.0598 133.75C88.9098 134.52 89.8398 134.9 91.6898 135.67L94.3198 143.07H100.68L103.31 135.67C105.16 134.9 106.09 134.52 107.94 133.75L115.04 137.12C116.54 135.62 118.04 134.12 119.54 132.62L116.17 125.52C116.94 123.67 117.32 122.74 118.09 120.89L125.49 118.26V111.9L118.09 109.27C117.32 107.42 116.94 106.49 116.17 104.64L119.54 97.54C118.04 96.04 116.54 94.54 115.04 93.04L107.94 96.41C106.09 95.64 105.16 95.26 103.31 94.49L100.68 87.09Z&#39; fill=&#39;black&#39; class=&#39;gear&#39; /&gt;
      &lt;path d=&#39;M97.4801 126.26C103.649 126.26 108.65 121.259 108.65 115.09C108.65 108.921 103.649 103.92 97.4801 103.92C91.311 103.92 86.3101 108.921 86.3101 115.09C86.3101 121.259 91.311 126.26 97.4801 126.26Z&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M62.7402 76.78C84.1402 76.78 101.48 59.44 101.48 38.04C101.48 31.46 99.8302 25.26 96.9402 19.84C105 26.94 110.09 37.33 110.09 48.91C110.09 60.49 105.24 70.39 97.5102 77.48H63.9802L62.7402 76.78Z&#39; fill=&#39;black&#39; /&gt;
    &lt;/g&gt;
    &lt;defs&gt;
      &lt;clipPath id=&#39;clip0_297_2779&#39;&gt;
        &lt;rect width=&#39;129.52&#39; height=&#39;143.09&#39; fill=&#39;white&#39; /&gt;
      &lt;/clipPath&gt;
    &lt;/defs&gt;
  &lt;/svg&gt;

&lt;/div&gt;

CSS:

.container {
margin: 20px;
}

svg \* {
transform-box: fill-box;
}

svg:hover {
.gear {
animation: stoneAn 2s infinite linear;
}

.bigGear {
animation: stoneAn 2s infinite linear;
}
}

.gear,
.bigGear {
transform-origin: center; /\* transform: rotate(180deg); \*/
}

@keyframes stoneAn {
from {
transform: rotate(0);
}

to {
transform: rotate(90deg);
}
}

@keyframes sssads {
to {
transform: rotate(0deg);
}
}

答案1

得分: 0

不使用CSS动画,您可以使用Web Animations API。一般来说,这样更容易控制动画,因为可以使用函数来启动、停止等动画,并且可以在运行过程中修改它们。

这里我在mouseenter事件上启动动画,并让它运行1次。在动画的finish事件上,我检测鼠标是否仍然悬停在SVG上(使用SVG元素上的自定义属性hover)。如果是这样,我会再次播放动画。如果不是,我会修改动画的时间,然后再次播放它。

您希望在结束时减速。我明白了,但是使用ease-out时间函数,动画在开始时加速。我尝试将持续时间更改为3000毫秒,但至少在Firefox中,这会破坏动画。

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->
const svg = document.querySelector('svg.svg');
const gear = document.querySelector('svg.svg .gear');
const biggear = document.querySelector('svg.svg .bigGear');

const gearKFE = new KeyframeEffect(
  gear, [{
      transform: 'rotate(0)'
    },
    {
      transform: 'rotate(90deg)'
    }
  ], {
    duration: 2000,
    iterations: 1,
    fill: 'forwards'
  }
);

const biggearKFE = new KeyframeEffect(
  biggear, [{
      transform: 'rotate(0)'
    },
    {
      transform: 'rotate(-90deg)'
    }
  ], {
    duration: 2000,
    iterations: 1,
    fill: 'forwards'
  }
);

var a1 = new Animation(gearKFE, document.timeline);
var a2 = new Animation(biggearKFE, document.timeline);

a1.addEventListener('finish', e => {
  let currentTiming = e.target.effect.getTiming();
  if (svg.hover) {
    e.target.effect.updateTiming({easing: 'linear'});
    e.target.play();
  } else {
    if (currentTiming.easing == 'linear') {
      e.target.effect.updateTiming({easing: 'ease-out'});
      e.target.play();
    }
  }
});

a2.addEventListener('finish', e => {
  let currentTiming = e.target.effect.getTiming();
  if (svg.hover) {
    e.target.effect.updateTiming({easing: 'linear'});
    e.target.play();
  } else {
    if (currentTiming.easing == 'linear') {
      e.target.effect.updateTiming({easing: 'ease-out'});
      e.target.play();
    }
  }
});

svg.addEventListener('mouseenter', e => {
  e.target.hover = true;
  a1.effect.updateTiming({easing: 'linear'});
  a2.effect.updateTiming({easing: 'linear'});
  a1.play();
  a2.play();
});

svg.addEventListener('mouseleave', e => {
  e.target.hover = false;
});

<!-- language: lang-css -->
.container {
  margin: 20px;
}

svg {
  pointer-events: all;
}

svg * {
  transform-box: fill-box;
}

.gear,
.bigGear {
  transform-origin: center;
}

<!-- language: lang-html -->
<div class="container">
  <svg width='130' height='144' viewBox='0 0 130 144' fill='none' class="svg" xmlns='http://www.w3.org/2000/svg'>
    <!-- ... (SVG内容) ... -->
  </svg>
</div>

<!-- end snippet -->

请注意,这是一段包含HTML、CSS和JavaScript的代码,用于在SVG上应用动画效果。如果您需要进一步的帮助,请告诉我。

英文:

Instead of using CSS animations you could use the Web Animations API. In general it is easier to control the animations, because there are functions for starting, stopping etc. animations and they can also be modified as you go.

Here I start the animations on mouseenter and let it run 1 iteration. On the finish event for the animation I test if the mouse is still over the SVG (using a custom property hover on the SVG element). If so, I play the animation again. If not, I modify the timing of the animation and play it one more time.

You would like it to slow down in the end. I get that, but with the ease-out timing the animation speeds up in the beginning. I tried changing the duration (to 3000ms) as well, but in Firefox at least this messes up the animation.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const svg = document.querySelector(&#39;svg.svg&#39;);
const gear = document.querySelector(&#39;svg.svg .gear&#39;);
const biggear = document.querySelector(&#39;svg.svg .bigGear&#39;);
const gearKFE = new KeyframeEffect(
gear, [{
transform: &#39;rotate(0)&#39;
},
{
transform: &#39;rotate(90deg)&#39;
}
], {
duration: 2000,
iterations: 1,
fill: &#39;forwards&#39;
}
);
const biggearKFE = new KeyframeEffect(
biggear, [{
transform: &#39;rotate(0)&#39;
},
{
transform: &#39;rotate(-90deg)&#39;
}
], {
duration: 2000,
iterations: 1,
fill: &#39;forwards&#39;
}
);
var a1 = new Animation(gearKFE, document.timeline);
var a2 = new Animation(biggearKFE, document.timeline);
a1.addEventListener(&#39;finish&#39;, e =&gt; {
let currentTiming = e.target.effect.getTiming();
if (svg.hover) {
e.target.effect.updateTiming({easing: &#39;linear&#39;});
e.target.play();
} else {
if (currentTiming.easing == &#39;linear&#39;) {
e.target.effect.updateTiming({easing: &#39;ease-out&#39;});
e.target.play();
}
}
});
a2.addEventListener(&#39;finish&#39;, e =&gt; {
let currentTiming = e.target.effect.getTiming();
if (svg.hover) {
e.target.effect.updateTiming({easing: &#39;linear&#39;});
e.target.play();
} else {
if (currentTiming.easing == &#39;linear&#39;) {
e.target.effect.updateTiming({easing: &#39;ease-out&#39;});
e.target.play();
}
}
});
svg.addEventListener(&#39;mouseenter&#39;, e =&gt; {
e.target.hover = true;
a1.effect.updateTiming({easing: &#39;linear&#39;});
a2.effect.updateTiming({easing: &#39;linear&#39;});
a1.play();
a2.play();
});
svg.addEventListener(&#39;mouseleave&#39;, e =&gt; {
e.target.hover = false;
});

<!-- language: lang-css -->

.container {
margin: 20px;
}
svg {
pointer-events: all;
}
svg * {
transform-box: fill-box;
}
.gear,
.bigGear {
transform-origin: center;
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;svg width=&#39;130&#39; height=&#39;144&#39; viewBox=&#39;0 0 130 144&#39; fill=&#39;none&#39; class=&quot;svg&quot; xmlns=&#39;http://www.w3.org/2000/svg&#39;&gt;
    &lt;g clipPath=&#39;url(#clip0_297_2779)&#39;&gt;
      &lt;path d=&#39;M70.6202 42.33L70.2802 51.97C72.0402 53.68 72.9302 54.54 74.7002 56.25L84.3202 55.61C85.3535 57.9966 86.3869 60.3866 87.4202 62.78L80.3702 69.35L80.4702 75.5L87.7302 81.85L84.8602 89.11L75.2202 88.77L70.9402 93.19L71.5802 102.81L64.4102 105.91L57.8402 98.86C55.3802 98.9 54.1402 98.92 51.6902 98.96L45.3402 106.22L38.0802 103.35L38.4202 93.71L34.0002 89.43L24.3802 90.07L21.2802 82.9L28.3302 76.33L28.2302 70.18L20.9702 63.83L23.8402 56.57L33.4802 56.91L37.7602 52.49L37.1202 42.87C39.5069 41.8366 41.8969 40.8033 44.2902 39.77L50.8602 46.82L57.0102 46.72L63.3602 39.46L70.6202 42.33Z&#39; class=&#39;bigGear&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M24.26 75.98C11.71 75.98 1.5 65.77 1.5 53.22C1.5 40.67 11.71 30.46 24.26 30.46C24.83 30.46 25.45 30.49 26.14 30.54L27.4 30.64L27.71 29.42C31.95 12.98 46.78 1.5 63.78 1.5C76.85 1.5 88.74 8.17 95.57 19.34L96.06 20.15L97 20.05C98 19.94 99 19.89 99.97 19.89C115.43 19.89 128.01 32.47 128.01 47.93C128.01 63.39 115.43 75.97 99.97 75.97H24.26V75.98Z&#39; fill=&#39;white&#39; /&gt;
      &lt;path d=&#39;M63.78 3C76.33 3 87.73 9.4 94.29 20.12L95.28 21.74L97.16 21.54C98.1 21.44 99.05 21.39 99.97 21.39C114.61 21.39 126.51 33.3 126.51 47.93C126.51 62.56 114.6 74.47 99.97 74.47H24.26C12.54 74.47 3 64.93 3 53.21C3 41.49 12.54 31.95 24.26 31.95C24.8 31.95 25.37 31.98 26.02 32.03L28.54 32.24L29.17 29.79C33.24 14.02 47.47 3 63.78 3ZM63.78 0C45.73 0 30.57 12.34 26.27 29.05C25.61 29 24.94 28.96 24.26 28.96C10.86 28.96 0 39.82 0 53.22C0 66.62 10.86 77.48 24.26 77.48H99.98C116.3 77.48 129.52 64.25 129.52 47.94C129.52 31.63 116.29 18.4 99.98 18.4C98.92 18.4 97.88 18.46 96.85 18.57C90.05 7.43 77.78 0 63.78 0Z&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M63.5201 0C63.5201 0 63.4301 0 63.3901 0V3C63.3901 3 63.4801 3 63.5201 3C83.2301 3 99.2601 19.03 99.2601 38.74C99.2601 58.45 83.2301 74.48 63.5201 74.48C63.4801 74.48 63.4301 74.48 63.3901 74.48V77.48C63.3901 77.48 63.4801 77.48 63.5201 77.48C84.9201 77.48 102.26 60.14 102.26 38.74C102.26 17.34 84.9201 0 63.5201 0Z&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M95.3602 141.59L92.8602 134.55L87.0002 132.12L80.2502 135.33L77.2502 132.33L80.4502 125.58L78.0302 119.72L70.9902 117.22V112.97L78.0302 110.47L80.4502 104.6L77.2502 97.86L80.2502 94.86L87.0002 98.06L92.8602 95.63L95.3602 88.6H99.6102L102.11 95.63L107.97 98.06L114.72 94.86L117.72 97.86L114.52 104.6L116.94 110.47L123.98 112.97V117.22L116.94 119.72L114.52 125.58L117.72 132.33L114.72 135.33L107.97 132.12L102.11 134.55L99.6102 141.59H95.3602Z&#39; fill=&#39;white&#39; /&gt;
      &lt;path d=&#39;M98.5498 90.1L100.47 95.51L100.92 96.77L102.15 97.28L104.61 98.3L106.79 99.2L108.02 99.71L109.22 99.14L114.4 96.68L115.48 97.76L115.9 98.18L113.44 103.36L112.87 104.56L113.38 105.79L114.39 108.23L115.3 110.42L115.81 111.65L117.07 112.1L122.48 114.02V116.15L117.07 118.07L115.81 118.52L115.3 119.75L114.56 121.55L113.39 124.39L112.88 125.62L113.45 126.82L115.91 132L115.49 132.42L114.41 133.5L109.23 131.04L108.03 130.47L106.8 130.98L105.59 131.48L102.16 132.9L100.93 133.41L100.48 134.67L98.5598 140.08H96.4298L94.5098 134.67L94.0598 133.41L92.8298 132.9L89.3998 131.48L88.1898 130.98L86.9598 130.47L85.7598 131.04L80.5798 133.5L79.0698 131.99L81.5298 126.81L82.0998 125.61L81.5898 124.38L80.3198 121.31L79.6698 119.75L79.1598 118.52L77.8998 118.07L72.4898 116.15V114.02L77.8998 112.1L79.1598 111.65L79.6698 110.42L80.5498 108.3L81.5898 105.79L82.0998 104.56L81.5298 103.36L79.0698 98.18L80.5798 96.67L85.7598 99.13L86.9598 99.7L88.1898 99.19L90.3698 98.29L92.8298 97.27L94.0598 96.76L94.5098 95.5L96.4298 90.09H98.5598M100.68 87.09H94.3198L91.6898 94.49C89.8398 95.26 88.9098 95.64 87.0598 96.41L79.9598 93.04L75.4598 97.54L78.8298 104.64C78.0598 106.49 77.6798 107.42 76.9098 109.27L69.5098 111.9V118.26L76.9098 120.89C77.6798 122.74 78.0598 123.67 78.8298 125.52L75.4598 132.62L79.9598 137.12L87.0598 133.75C88.9098 134.52 89.8398 134.9 91.6898 135.67L94.3198 143.07H100.68L103.31 135.67C105.16 134.9 106.09 134.52 107.94 133.75L115.04 137.12C116.54 135.62 118.04 134.12 119.54 132.62L116.17 125.52C116.94 123.67 117.32 122.74 118.09 120.89L125.49 118.26V111.9L118.09 109.27C117.32 107.42 116.94 106.49 116.17 104.64L119.54 97.54C118.04 96.04 116.54 94.54 115.04 93.04L107.94 96.41C106.09 95.64 105.16 95.26 103.31 94.49L100.68 87.09Z&#39; fill=&#39;black&#39; class=&#39;gear&#39; /&gt;
      &lt;path d=&#39;M97.4801 126.26C103.649 126.26 108.65 121.259 108.65 115.09C108.65 108.921 103.649 103.92 97.4801 103.92C91.311 103.92 86.3101 108.921 86.3101 115.09C86.3101 121.259 91.311 126.26 97.4801 126.26Z&#39; fill=&#39;black&#39; /&gt;
      &lt;path d=&#39;M62.7402 76.78C84.1402 76.78 101.48 59.44 101.48 38.04C101.48 31.46 99.8302 25.26 96.9402 19.84C105 26.94 110.09 37.33 110.09 48.91C110.09 60.49 105.24 70.39 97.5102 77.48H63.9802L62.7402 76.78Z&#39; fill=&#39;black&#39; /&gt;
    &lt;/g&gt;
    &lt;defs&gt;
      &lt;clipPath id=&#39;clip0_297_2779&#39;&gt;
        &lt;rect width=&#39;129.52&#39; height=&#39;143.09&#39; fill=&#39;white&#39; /&gt;
      &lt;/clipPath&gt;
    &lt;/defs&gt;
  &lt;/svg&gt;

&lt;/div&gt;

<!-- end snippet -->

Bonus Snippet

Here I made a version of the SVG without all the long path values. It makes the code easier to maintain.

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

const svg = document.querySelector(&#39;svg&#39;);
const gear = document.querySelector(&#39;svg .gear&#39;);
const biggear = document.querySelector(&#39;svg .bigGear&#39;);
const gearKFE = new KeyframeEffect(
gear, [{
transform: &#39;rotate(0)&#39;
},
{
transform: &#39;rotate(90deg)&#39;
}
], {
duration: 2000,
iterations: 1,
fill: &#39;forwards&#39;
}
);
const biggearKFE = new KeyframeEffect(
biggear, [{
transform: &#39;rotate(0)&#39;
},
{
transform: &#39;rotate(-90deg)&#39;
}
], {
duration: 2000,
iterations: 1,
fill: &#39;forwards&#39;
}
);
var a1 = new Animation(gearKFE, document.timeline);
var a2 = new Animation(biggearKFE, document.timeline);
a1.addEventListener(&#39;finish&#39;, e =&gt; {
let currentTiming = e.target.effect.getTiming();
if (svg.hover) {
e.target.effect.updateTiming({easing: &#39;linear&#39;});
e.target.play();
} else {
if (currentTiming.easing == &#39;linear&#39;) {
e.target.effect.updateTiming({easing: &#39;ease-out&#39;});
e.target.play();
}
}
});
a2.addEventListener(&#39;finish&#39;, e =&gt; {
let currentTiming = e.target.effect.getTiming();
if (svg.hover) {
e.target.effect.updateTiming({easing: &#39;linear&#39;});
e.target.play();
} else {
if (currentTiming.easing == &#39;linear&#39;) {
e.target.effect.updateTiming({easing: &#39;ease-out&#39;});
e.target.play();
}
}
});
svg.addEventListener(&#39;mouseenter&#39;, e =&gt; {
e.target.hover = true;
a1.effect.updateTiming({easing: &#39;linear&#39;});
a2.effect.updateTiming({easing: &#39;linear&#39;});
a1.play();
a2.play();
});
svg.addEventListener(&#39;mouseleave&#39;, e =&gt; {
e.target.hover = false;
});

<!-- language: lang-css -->

body {
margin: 10px;
}
svg {
height: calc(100vh - 20px);
pointer-events: all;
}

<!-- language: lang-html -->

&lt;svg viewBox=&quot;0 0 220 220&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
&lt;defs&gt;
&lt;mask id=&quot;mask1&quot;&gt;
&lt;path d=&quot;M0 0A50 50 90 10-1 0Z&quot; stroke=&quot;white&quot;
stroke-width=&quot;4&quot; transform=&quot;translate(150 122)&quot; /&gt;
&lt;g transform=&quot;translate(110 130)&quot; fill=&quot;white&quot;&gt;
&lt;g class=&quot;bigGear&quot;&gt;
&lt;circle r=&quot;30&quot;/&gt;
&lt;path id=&quot;p1&quot; d=&quot;M -20 0 L -5 37 L 5 37 L 20 0 L 5 -37 L -5 -37 Z&quot;/&gt;
&lt;use href=&quot;#p1&quot; transform=&quot;rotate(45)&quot;/&gt;
&lt;use href=&quot;#p1&quot; transform=&quot;rotate(90)&quot;/&gt;
&lt;use href=&quot;#p1&quot; transform=&quot;rotate(135)&quot;/&gt;
&lt;/g&gt;
&lt;/g&gt;
&lt;g transform=&quot;translate(160 180) rotate(22.5)&quot;
fill=&quot;none&quot; stroke=&quot;white&quot; stroke-width=&quot;4&quot;&gt;
&lt;g class=&quot;gear&quot;&gt;
&lt;circle id=&quot;c1&quot; r=&quot;30&quot; fill=&quot;none&quot; stroke=&quot;white&quot; pathLength=&quot;360&quot;
stroke-dasharray=&quot;22.5 22.5&quot; transform=&quot;rotate(11)&quot; /&gt;
&lt;path id=&quot;p2&quot; d=&quot;M -7 28 L -5 37 L 5 37 L 7 28&quot;/&gt;
&lt;use href=&quot;#p2&quot; transform=&quot;rotate(45)&quot;/&gt;
&lt;use href=&quot;#p2&quot; transform=&quot;rotate(90)&quot;/&gt;
&lt;use href=&quot;#p2&quot; transform=&quot;rotate(135)&quot;/&gt;
&lt;use href=&quot;#p2&quot; transform=&quot;rotate(180)&quot;/&gt;
&lt;use href=&quot;#p2&quot; transform=&quot;rotate(225)&quot;/&gt;
&lt;use href=&quot;#p2&quot; transform=&quot;rotate(270)&quot;/&gt;
&lt;use href=&quot;#p2&quot; transform=&quot;rotate(315)&quot;/&gt;
&lt;circle r=&quot;12&quot; fill=&quot;white&quot; stroke=&quot;none&quot;/&gt;
&lt;/g&gt;
&lt;/g&gt;
&lt;g transform=&quot;translate(92 122)&quot;&gt;
&lt;path d=&quot;M-60 0 0 0C5 0 27-45-10-90&quot; fill=&quot;white&quot; stroke=&quot;white&quot;
stroke-width=&quot;4&quot; transform=&quot;translate(60 0)&quot; /&gt;
&lt;path d=&quot;M0 0A60 60 90 000-120 60 60 90 00-60-60 4 4 90 00-60 0Z&quot;
fill=&quot;black&quot; stroke=&quot;white&quot; stroke-width=&quot;4&quot; /&gt;
&lt;/g&gt;
&lt;/mask&gt;
&lt;/defs&gt;
&lt;rect width=&quot;220&quot; height=&quot;220&quot; fill=&quot;black&quot; mask=&quot;url(#mask1)&quot;/&gt;
&lt;/svg&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月18日 03:49:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定