使用 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, '---')
相关推荐
RFCEO3 小时前
前端编程 课程十三、:CSS核心基础1:CSS选择器
前端·css·css基础选择器详细教程·css类选择器使用方法·css类选择器命名规范·css后代选择器·精准选中嵌套元素
肖。354878709411 小时前
html选择页最简模板源码,用于集合很多网页!游戏大全数字导航页面,数字选择页制作灵感,已经压缩到最小,现代,讲解。
android·java·javascript·css·html
共享家952719 小时前
搭建 AI 聊天机器人:”我的人生我做主“
前端·javascript·css·python·pycharm·html·状态模式
搬砖的阿wei1 天前
CSS常用选择器总结
前端·css
RFCEO1 天前
前端编程 课程十二、:CSS 基础应用 Flex 布局
前端·css·flex 布局·css3原生自带的布局模块·flexible box·弹性盒布局·垂直居中困难
ziblog1 天前
HTML5 Canvas梦幻背景动画特效
前端·css
weixin_456907412 天前
2026+:html+css 生态的成型之年与平台化跃迁
前端·css·html
2301_780669862 天前
HTML-CSS-常见标签和样式(标题的排版、标题的样式、选择器、正文的排版、正文的样式、整体布局、盒子模型)
前端·css·html·javaweb
weixin_456907412 天前
CSS DSF.soolCXZ LsoolbDSF:html 中 doos() 的 Copy-goos-Prite 实现实验笔记
css·笔记·html
咕噜咕噜啦啦2 天前
CSS3基础
前端·css·css3