SVG 描边动画实现

111 阅读1分钟

动画原理

CSS animation 关键帧动画

基础动画实现

<svg class="icon" width='200' height='200'>
  <line class="p" x1='0' y1='50%' x2='100%' y2='50%' />
</svg>
.p {
  stroke: #f40;
  /* 设置线宽为 10 */
  stroke-width: 10;
  /* 短划线和缺口的长度都为 200,也就是线的长度 */
  stroke-dasharray: 200, 200;
  /* 控制偏移为0 */
  stroke-dashoffset: 200;
  animation: stroke 2s forwards;
}

@keyframes stroke {
  to {
    stroke-dashoffset: 0;
  }
}

动态获取线的长度

<svg class="icon" width='200' height='200'>
  <line class="p" x1='0' y1='50%' x2='100%' y2='50%' />
</svg>
.p {
  stroke: #f40;
  stroke-width: 10;
  /* 设置为200,让虚线和实线的长度相等 */
  stroke-dasharray: var(--l);
  /* 控制偏移为0 */
  stroke-dashoffset: var(--l);
  animation: stroke 2s forwards;
}

@keyframes stroke {
  to {
    stroke-dashoffset: 0;
  }
}
const paths = document.querySelectorAll('.icon .p')
paths.forEach((path) => {
  // getTotalLength 获取路径的长度
  const len = path.getTotalLength()
  path.style.setProperty('--l', len)
})

再加一个圆形

<svg class="icon" width='200' height='200'>
  <line class="p" x1='0' y1='50%' x2='100%' y2='50%' />
  <circle class="p" cx='50%' cy='50%' r='30%' />
</svg>
.p {
  stroke: #f40;
  stroke-width: 10;
  /* 设置为200,让虚线和实线的长度相等 */
  stroke-dasharray: var(--l);
  /* 控制偏移为0 */
  stroke-dashoffset: var(--l);
  animation: stroke 2s forwards;

  /* 设置圆形的填充 */
  /* fill: none; */
  stroke-linecap: round;
}

@keyframes stroke {
  to {
    stroke-dashoffset: 0;
  }
}
const paths = document.querySelectorAll('.icon .p')
paths.forEach((path) => {
  // getTotalLength 获取路径的长度
  // +1 为了让圆形封闭起来
  const len = path.getTotalLength() + 1
  path.style.setProperty('--l', len)
})

实现动态图标

图标来源:iconpark

<svg width="200" height="200" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path class="p"
    d="M6 9.25564L24.0086 4L42 9.25564V20.0337C42 31.3622 34.7502 41.4194 24.0026 45.0005C13.2521 41.4195 6 31.36 6 20.0287V9.25564Z"
    fill="none" stroke="#54D281" stroke-width="4" stroke-linejoin="round" />
  <path class="p" d="M15 23L22 30L34 18" stroke="#54D281" stroke-width="4" stroke-linecap="round"
    stroke-linejoin="round" />
</svg>
.p {
  stroke-dasharray: var(--l);
  /* 控制偏移为0 */
  stroke-dashoffset: var(--l);
  animation: stroke 2s forwards;
  stroke-linecap: round;
}

@keyframes stroke {
  to {
    stroke-dashoffset: 0;
  }
}
const paths = document.querySelectorAll('.p')
paths.forEach((path) => {
  // getTotalLength 获取路径的长度
  // +1 为了让圆形封闭起来
  const len = path.getTotalLength() + 1
  path.style.setProperty('--l', len)
})