跳至主要內容

使用 Lottie 动画装饰一下你的 404 页面

Bing🐣LottieVueLottie-WebLottieFiles大约 4 分钟

使用 Lottie 动画装饰一下你的 404 页面

自己博客的 404 页面太单调无趣了,由于之前项目使用过Lottie-Webopen in new window做过动画,想着给 404 页面加上一个有趣的动画。然后就去 LottieFilesopen in new window动画库搜索了下404,发现一个和谷歌浏览器断网小恐龙游戏类似的的 404 动画效果open in new window,感觉很有趣,那就用它了,最终的效果大家可以通过访问 404 页面open in new window查看。

下载动画 JSON

LottieFilesopen in new window上面能找到很多 404 页面的动画,可以挑一个你喜欢了。

image
image

这里就选择小恐龙的动画open in new window,点击右上角的Download按钮,选择Lottie JSON进行下载。

image
image

下载完成后会得到一个 json 文件。

修改默认颜色

由于动画内容的黑色和博客默认的黑色不太一样,所以还需要借助 LottieFiles 提供的编辑器open in new window修改下颜色。

image
image

上传刚刚下载的 json 文件,将Unique colors里面的黑色修改成想要的颜色。

image
image

点击Save按钮保存后就能在自己的项目open in new window中找到修改后的动画了。

image
image

同样是下载 Lottie JSON 文件。

image
image

动画组件

Lottie Webopen in new window 的动画使用很简单,只需要传入一个容器container和动画 json 所在路径path,下面是文档中的一个初始化示例。

var animation = bodymovin.loadAnimation({
  container: document.getElementById('lottie'), // Required
  path: 'data.json', // Required
  renderer: 'svg/canvas/html', // Required
  loop: true, // Optional
  autoplay: true, // Optional
  name: 'Hello World' // Name for future reference. Optional.
})

所以可以写一个简单的组件,传入相关参数即可,当然你也可以使用别人封装好的lottie-web-vueopen in new window,这里由于使用场景比较简单,就自己撸一个了,先将 lottie-web 安装一下。

NPM
npm install lottie-web

由于自己的博客使用的 vuepress2open in new window,可以在src/.vuepress/components目录中新建一个LottieWeb的自定义组件。

由于使用场景比较简单,将相关配置直接通过options传入,派发一个DOMLoaded事件。

LottieWeb/index.vue
<template>
  <div class="lottie-web" ref="animContainer"></div>
</template>

<script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref } from 'vue'
import type { AnimationItem } from 'lottie-web'
import lottie from 'lottie-web'

const props = defineProps({
  options: {
    type: Object,
    required: true
  }
})

const emit = defineEmits(['DOMLoaded'])
const animContainer = ref<Element | null>(null)
const anim = ref<AnimationItem | null>(null)

onMounted(() => {
  anim.value = lottie.loadAnimation({
    container: animContainer.value as Element,
    renderer: 'svg',
    loop: props.options.loop !== false,
    autoplay: props.options.autoplay !== false,
    animationData: props.options.animationData,
    path: props.options.path,
    rendererSettings: props.options.rendererSettings
  })
  anim.value.addEventListener('DOMLoaded', () => {
    emit('DOMLoaded', anim)
  })
})

onBeforeUnmount(() => {
  if (anim.value && anim.value) {
    anim.value.destroy()
  }
})
</script>

集成到 404

可以参照 Vuepress 的继承文档说明open in new window替换默认的 404 页面。博客主题使用的是Mr.Hopeopen in new window大佬写的VuePress Theme Hopeopen in new window主题,好在大佬贴心的给NotFoundopen in new window布局提供了一个默认的内容插槽,所以我们只需要引用内置的NotFound,将动画内容放到里面即可。

src/.vuepress/layouts下面新建一个新的 NotFound 布局,将上面下载的 json 数据放到同级目录下并通过new URL('./data.json', import.meta.url).href形式传入 path。

新的 NotFound 布局写好后在src/.vuepress/client.ts中的layouts中引入即可。

NotFound/index.vue
<template>
  <NotFound>
    <div class="not-found-hint">
      <p class="error-code">404</p>
      <h1 class="error-title">页面不存在</h1>
    </div>
    <LottieWeb
      :options="options"
      :style="{
        height: '50vh',
        opacity: showLottieWeb ? 1 : 0,
        'margin-top': '-60px'
      }"
      @DOMLoaded="DOMLoaded"
    />
  </NotFound>
</template>

<script lang="ts" setup>
import NotFound from 'vuepress-theme-hope/layouts/NotFound'
import LottieWeb from '../../components/LottieWeb/index.vue'
import { ref } from 'vue'

const showLottieWeb = ref(false)
const options = ref({
  path: new URL('./data.json', import.meta.url).href
})

function DOMLoaded() {
  const $rectList = document.querySelectorAll(
    '.lottie-web rect[fill="#ffffff"]'
  )
  $rectList.forEach((element) => {
    element.setAttribute('fill', 'transparent')
  })
  showLottieWeb.value = true
}
</script>

<style scoped lang="scss">
.not-found-hint {
  padding-bottom: 0;
}
</style>

适配暗黑模式

由于动画背景是白色的,在暗黑模式下还是白色的会很刺眼,所以在上述代码在DOMLoaded的时候做了特殊处理。
我们可以在生成的动画 SVG 中找到背景的元素rect元素,
通过document.querySelectorAll('.lottie-web rect[fill="#ffffff"]')定位到该元素,
使用setAttribute修改该背景的filltransparent透明色。

image
image

此时在暗黑模式下刷新页面的时候会存在白色背景一闪的情况,如下图所示:

image
image

为了解决这个可以在动画组件上加个style样式opacity默认为 0,这样初始的时候不可见,通过showLottieWeb变量控制最终的显示,在样式替换完成后将动画组件显示可见,这样有一个缓冲就不会出现上述的现象了。

效果预览

点击查看open in new window

image
image