实现一个炫酷的 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...

相关推荐
天下无贼!9 分钟前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
Jiaberrr9 分钟前
JS实现树形结构数据中特定节点及其子节点显示属性设置的技巧(可用于树形节点过滤筛选)
前端·javascript·tree·树形·过滤筛选
赵啸林12 分钟前
npm发布插件超级简单版
前端·npm·node.js
罔闻_spider1 小时前
爬虫----webpack
前端·爬虫·webpack
吱吱鼠叔1 小时前
MATLAB数据文件读写:1.格式化读写文件
前端·数据库·matlab
爱喝水的小鼠1 小时前
Vue3(一) Vite创建Vue3工程,选项式API与组合式API;setup的使用;Vue中的响应式ref,reactive
前端·javascript·vue.js
WeiShuai1 小时前
vue-cli3使用DllPlugin优化webpack打包性能
前端·javascript
Wandra1 小时前
很全但是超级易懂的border-radius讲解,让你快速回忆和上手
前端
ice___Cpu1 小时前
Linux 基本使用和 web 程序部署 ( 8000 字 Linux 入门 )
linux·运维·前端
JYbill1 小时前
nestjs使用ESM模块化
前端