使用 SVG 实现签名动画效果并适配 vuepress

原文链接:dribble-njr.github.io/blog/fronte…

在阅读 antfu 大佬的 Animated SVG Logo 时,发现了一个很有意思的动画效果,最终实现的效果如下。

使用 SVG 实现签名动画效果并适配 vuepress

其中原理可以参考下面两篇文章:

下面以内马尔签名为例,介绍一下如何实现这个效果。

签名文件处理

谷歌上搜索内马尔签名,找到 原始 SVG 文件

使用 SVG 实现签名动画效果并适配 vuepress

源文件为 fill 填充,而只有 stroke 才能实现此动画效果,所以需要使用 Adobe Illustration 或 Figma 或 Motiff 处理。

先将填充取消,并进行描边处理,最后使用钢笔工具在填充中间增加路径。

使用 AI 软件处理后,得到下面文件,再导出为 SVG 格式。由于技术不过关,少了很多细节处理,但是不影响效果。

使用 SVG 实现签名动画效果并适配 vuepress

实现动画

得到 stroke 文件后,就可以使用 stroke-dasharraystroke-dashoffset 属性实现动画效果。

由于这里的有四条路径,因此需要分别设置四个动画。

这里先获得四条路径的总长度。

const path1 = document.getElementById('path1')
const path2 = document.getElementById('path2')
const path3 = document.getElementById('path3')
const path4 = document.getElementById('path4')
console.log(path1.getTotalLength())
console.log(path2.getTotalLength())
console.log(path3.getTotalLength())
console.log(path4.getTotalLength())

获取完长度后,因为需要依次出现每个路径,所以需要设置动画延迟时间,这样就能保证每个路径依次出现,最终就能得到上述的效果了。

:root {
  --dash-array-1: 1722px;
  --dash-array-2: 633px;
  --dash-array-3: 436px;
  --dash-array-4: 1386px;
}

@media (prefers-reduced-motion) {
  path {
    animation: none !important;
    stroke-dasharray: unset !important;
  }
}

@keyframes draw {
  0% {
    stroke-dashoffset: var(--dash-array);
    opacity: 0;
  }
  100% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
}

path:nth-child(1) {
  --dash-array: var(--dash-array-1);
  animation: draw 1s ease forwards 0s;
}

path:nth-child(2) {
  --dash-array: var(--dash-array-2);
  animation: draw 0.7s ease forwards 1s;
}

path:nth-child(3) {
  --dash-array: var(--dash-array-3);
  animation: draw 0.5s ease forwards 2s;
}

path:nth-child(4) {
  --dash-array: var(--dash-array-4);
  animation: draw 1s ease forwards 3s;
}

path {
  stroke-dashoffset: 1px;
  stroke-dasharray: var(--dash-array);
  transform-origin: center;
  stroke: #303030;
  opacity: 0;
}

适配 vuepress

这里使用的是 vuepress-theme-hope 主题,参考 替换主题组件 中通过导航栏组件别名替换了默认的导航栏组件。

alias: {
  '@theme-hope/modules/navbar/components/NavbarBrand': path.resolve(
    __dirname,
    './components/NavLogo.vue'
  )
}

适配深色主题

vuepress 并未提供是否为深色主题的接口,需要监听 data-theme 属性变化,来判断是否为深色主题。

import { onUnmounted, onMounted, ref } from 'vue'

const isDarkMode = ref(false)

onMounted(() => {
  const html = document.documentElement

  console.log(html, '===')

  isDarkMode.value = html.dataset.theme === 'dark'

  // watch theme change
  const observer = new MutationObserver(() => {
    isDarkMode.value = html.dataset.theme === 'dark'
    console.log(isDarkMode.value, '---')
  })

  observer.observe(html, {
    attributeFilter: ['data-theme'],
    attributes: true
  })

  onUnmounted(() => {
    observer.disconnect()
  })
})

console.log(isDarkMode.value, '---')

原文链接:https://juejin.cn/post/7323271686034489354 作者:我在云上啊

(0)
上一篇 2024年1月13日 下午4:53
下一篇 2024年1月14日 上午10:05

相关推荐

发表回复

登录后才能评论