SVG 签名动画初探

发现 Anthony Fu 写的这篇 Animated SVG Logo,可以通过 SVG 和 CSS 动画实现动态的签名效果;后来又看到了 Innei/Shiro 主题用了这样的签名效果来在版权卡片上面签名,感觉很有意思,于是自己把两者结合,用 Anthony 的方法制作了图标,实现了 Innei 中图标的功能……

这篇文章是个简单的教程/记录,希望能帮助到你。

目前你可以在本站每篇文章尾部的 Copyright 卡片上看到这个动态签名。

Tip

如果你正在 RSS 阅读器中阅读这篇文章,可能无法看到上面图标的动态效果(甚至只能看见一片白),建议在浏览器中查看。

原理简析

假设现在我们有一个“一笔画成”的 SVG 文件,我们可以通过控制这“一笔”显示的部分有多长来实现动画效果,而 CSS 的 stroke-dasharray 属性正好可以做到这一点。

但是,很多名字是不能“一笔画成”的,这也是不少人放弃这个方法的原因,但是从 Anthony 的文章中我们得到一个新方法:使用一个遮罩来遮住多余的部分。他在文中使用这个方法是为了笔画的粗细变化,但是只要把遮罩的形状设置得合适,我们也可以用这个方法来实现“一笔画成”的效果。

更具体的细节,可以前往 Anthony 的文章 查看。

至于 Innei/Shiro 主题中的效果,其实并不像签名,而是“逐渐显示”。 这个制作起来会方便很多,如果你只想要一个简单的动画效果,而不是一定要“签名”动画,可以查看制作一个好看的动态签名🖋️ - 柃夏chapu

实现步骤

画图标

  1. 在 Google Fonts 中选一个自己喜欢的字体;
  2. https://danmarshall.github.io/google-font-to-svg-path/ 中下载为 SVG 文件
  3. 将 SVG 文件导入 Figma
  4. 用钢笔工具跟着线路“一笔画”画出签名(中间不连续的地方可以先直接连上,比如下图 i 的竖杠和圆点之间) 一笔画

    Tip

    这步应该是最难最烦的,尤其是对于不熟悉 Figma 的人,可以自行搜索怎么用 Figma 的钢笔工具
    也可以尝试把我画好的签名导入 Figma,看一看是怎么操作的。

  5. 画一个可以遮住多余部分的图形(如果需要) 画遮罩
  6. 将遮挡图形设置为 Mask 设置 Mask
  7. 想要线条粗细变化?方法是加遮罩,和上文提到的遮住多余部分一个道理,把粗的线遮细点……
  8. 导出这个 SVG 文件

放入项目

  1. 导入你的项目中,不同框架导入方式不同,比如我用 Astro,可以这样:

    // signature.astro
    ---
    import Sign from "@assets/signature-yunfi.svg?raw";
    ---
    <div class="float-right signature-wrapper">
      <Fragment set:html={Sign} />
    </div>
    
  2. 设置 CSS,可以参考 antfu 文章 中的写法

    • 最好去 SVG 文件里给主要的 path 加上 id(我加的是 main-stroke),方便 CSS 进行 query
    • --signature-length 属性是主要笔画的长度,最好通过二分法试一试,如何太大,动画看上去会很快,如果太小动画会从笔画上的好几个地方一起开始播放。
    /* 使用了带有 nested 支持的 Tailwind CSS,如果你没用的话,需要自己写 */
    .signature-wrapper {
      --signature-length: 2550px;
    }
    /* https://antfu.me/posts/animated-svg-logo */
    .signature-wrapper #main-stroke {
      @apply stroke-black dark:stroke-white opacity-100;
      stroke-dashoffset: 1px;
      stroke-dasharray: var(--signature-length) 0;
      animation: grow 7s ease-out forwards infinite;
      transform-origin: center;
      animation-delay: 0s;
    }
    @media (prefers-reduced-motion) {
      path {
        animation: none !important;
        stroke-dasharray: unset !important;
      }
    }
    @keyframes grow {
      0% {
        stroke-dashoffset: 1px;
        stroke-dasharray: 0 var(--signature-length);
        opacity: 0;
      }
      10% {
        opacity: 1;
      }
      45% {
        stroke-dasharray: var(--signature-length) 0;
      }
      /* Moving back */
      65% {
        stroke-dasharray: var(--signature-length) 0;
      }
      95%,
      to {
        stroke-dasharray: 0 var(--signature-length);
      }
    }
    
  3. 大功告成!

参考

本文使用“署名-非商业性使用-相同方式共享 4.0 国际(CC BY-NC-SA 4.0)”进行许可。

商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接。 如果您再混合、转换或者基于本作品进行创作,您必须基于相同的协议分发您贡献的作品。

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.3.0
2023-2024 Yunfi. | Source Code RSS | Site Map Powered by Astro. See all Credits.