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

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

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

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

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

签名文件处理

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

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

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

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

实现动画

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

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

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

js 复制代码
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())

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

css 复制代码
: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 主题,参考 替换主题组件 中通过导航栏组件别名替换了默认的导航栏组件。

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

适配深色主题

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

js 复制代码
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, '---')
相关推荐
Au_ust32 分钟前
css:基础
前端·css
帅帅哥的兜兜32 分钟前
css基础:底部固定,导航栏浮动在顶部
前端·css·css3
就是个名称36 分钟前
购物车-多元素组合动画css
前端·css
并不会5 小时前
常见 CSS 选择器用法
前端·css·学习·html·前端开发·css选择器
悦涵仙子5 小时前
CSS中的变量应用——:root,Sass变量,JavaScript中使用Sass变量
javascript·css·sass
衣乌安、5 小时前
【CSS】居中样式
前端·css·css3
低代码布道师5 小时前
CSS的三个重点
前端·css
黎金安18 小时前
前端第二次作业
前端·css·css3
阳光开朗大男孩 = ̄ω ̄=19 小时前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
小马哥编程20 小时前
【前端基础】CSS基础
前端·css