使用 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, '---')
相关推荐
真的很上进33 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
sanguine__4 小时前
APIs-day2
javascript·css·css3
LUwantAC5 小时前
CSS(一):选择器
前端·css
Simaoya7 小时前
【vue】圆环呼吸灯闪烁效果(模拟扭蛋机出口处灯光)
javascript·css·vue.js
LOVE️YOU8 小时前
HTML&CSS&JavaScript&DOM 之间的关系?
前端·javascript·css·html
NoneCoder8 小时前
CSS系列(26)-- 动画性能优化详解
前端·css·性能优化
萧寂1739 小时前
ios底部小横条高度适配
css
机器视觉李小白12 小时前
使用 HTML 和 CSS 实现绚丽的节日烟花效果
css·html·烟花·节日·节日祝福
请叫我飞哥@19 小时前
HTML5 CSS 与样式详解
前端·css·html5