实现一个炫酷的 DOM 转粒子动画

前言

在我网络冲浪的时候,无意之间看到了一位大佬做的粒子效果很是炫酷,不过只做了 Mac 端的示例,我于是就学习做了一个 Web 端的 DOM 转 Canvas 粒子动画效果。代码仓库、说明文档及NPM包都在结尾。

实现思路

实现思路的话十分好理解,一句话就可以说的清。

先用 html2canvas 将 DOM 转成 canvas ,然后将 canvas 转成粒子开始做动画。

全部实现下来核心代码 200 多行,7kb左右吧。不过由于依赖了 html2canvas,打包后还是有 200+ kb 的大小。

开发逻辑

输入

既然是要将 DOM 转为 Canvas 粒子,那么输入自然是 DOM 。这里预设了两种粒子效果,就如开篇的图所示。

获取图像数据

调用方法,传入 DOM 和 动画类型初始化后,直接就是获取图像数据,这些数据就是后面要创建的粒子。

自己传入进来的 DOM 什么样,就能截图显示成什么样?(当然,html2canvas 的小缺陷还是避免不了,比如跨域图片的加载 。)

然后除了图像数据外,还有 DOM 的尺寸也要记录下来,到时候在画布上渲染需要用得到。

开始动画

初始化好后,自然不一定希望立即动画,所以导出了一个 startAnimation 方法,一旦调用就开始动画。

而这个方法,自然有几处逻辑上的需要考虑,比如上一次的动画需要清除,动画的持续时间,动画结束之后又要清除以防内存泄露等等。考虑好后,自然就是逻辑上的开发了。

动画渲染

终于到了关键的一步,而这里却很简单。

几个步骤:

  1. 调用动画方法后,增加一个 Canvas 画布,用于渲染粒子。
  2. requestAnimationFrame 渲染动画。
  3. html2canvas 获取的图像数据,遍历创建粒子,这些粒子的位置随 requestAnimationFrame 改变。

核心逻辑就是这样,不过还有一些小细节要考虑。比如要更新一下传入 DOM 的位置,放置窗口 Resize 或者页面 Scroll 造成的位置影响。或者粒子的动画效果该如何去设置。不过这些都是优化项,主要初步的能渲染就行,粒子的动画效果无非就是改变 x || y 值,做匀速、匀加速、正弦余弦波动,几种组合在一起,整的花里胡哨的。

然后还有就是粒子的数量对浏览器的 FPS 的影响。

使用方法

经过两天的时间,开发了一个 html2particle NPM 包,并写了一个简要的说明文档和用法示例。使用 TS 开发的,编译成 JS 发布上去的,所以使用也无关前端框架,都可以使用。这里只放一个 Vue 版本(包括样式)的示例,用 Vitepress 写的说明文档还有原生和 React 的用法。

vue

vue 复制代码
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import html2particle from 'html2particle'

const item4Ref = ref<HTMLElement>()
let handleItem4Click = () => { }
const isShow4 = ref(true)
function initItem4Event() {
  const { startAnimation } = html2particle(item4Ref.value!, { type: 'ExplodingParticle' })
  handleItem4Click = () => {
    isShow4.value = false
    startAnimation()
  }
}

const item5Ref = ref<HTMLElement>()
let handleItem5Click = () => { }
const isShow5 = ref(true)
function initItem5Event() {
  const { startAnimation } = html2particle(item5Ref.value!, { type: 'SinWaveParticle' })
  handleItem5Click = () => {
    isShow5.value = false
    startAnimation()
  }
}

onMounted(() => {
  initItem4Event()
  initItem5Event()
})
</script>

<template>
  <div class="container">
    <div ref="item4Ref" class="image" @click="handleItem4Click">
      <img v-if="isShow4" src="/1.jpg" alt="">
    </div>

    <div ref="item5Ref" class="image" @click="handleItem5Click">
      <img v-if="isShow5" src="/2.jpg" alt="">
    </div>
  </div>
</template>

<style scoped>
.container {
  align-items: center;
  user-select: none;
  display: flex;
  flex-direction: row;
}

.image {
  width: 300px;
  height: 200px;
  cursor: pointer;
  margin: 0 auto 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}

img {
  object-fit: cover;
  width: 100%;
  height: 100%;
  border-radius: 10px;
  overflow: hidden;
  outline: 2px solid #887cc8;
  outline-offset: 2px;
}
</style>

结尾

总的来说,因为样式炫目,才引起的兴趣研究一下这个。虽然代码量不多,不过还是有点意思。如果可以自定义传入粒子效果,而不是只有这两种,那应该更好用些。

Demo 及文档预览 : html2particle.mmeme.me/guide/demo....

NPM 包地址 : www.npmjs.com/package/htm...

GitHub 仓库地址 : github.com/pinky-pig/h...

相关推荐
自由日记8 小时前
学习中小牢骚1
前端·javascript·css
泽泽爱旅行8 小时前
业务场景-opener.focus() 不聚焦解决
前端
VOLUN8 小时前
Vue3 选择弹窗工厂函数:高效构建可复用数据选择组件
前端·javascript·vue.js
ErMao8 小时前
深入理解let、const和var
前端
IT_陈寒8 小时前
SpringBoot 3.2新特性实战:这5个隐藏功能让开发效率翻倍🚀
前端·人工智能·后端
涛哥AI编程8 小时前
【AI编程干货】Token成为硬通货后,我的7000字Claude Code精算准则
前端·ai编程
IT_陈寒8 小时前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升70% 🚀
前端·人工智能·后端
golang学习记9 小时前
从0死磕全栈之深入理解 Next.js 中的 NextResponse:API 详解与实战示例
前端
木易士心9 小时前
CSS 中 `data-status` 的使用详解
前端
木易士心9 小时前
JavaScript 数组的核心操作方法,从基础到高级
前端