使用 Vue 和 Canvas-Confetti 实现烟花动画特效
在开发中,为用户提供具有视觉冲击力的反馈是一种提升用户体验的好方法。今天,我们将结合 Vue 框架、canvas-confetti 和 Lottie 动画,创建一个动态对话框动画,其中包含炫酷的烟花特效。
效果图:

效果简介
当用户触发特定事件时:
- 弹出一个对话框,加载基于用户等级的 Lottie 动画。
- 配合对话框的展示,启动烟花特效(
canvas-confetti),模拟庆祝场景。 - 用户关闭对话框时,清除动画和特效。
使用的技术栈
- Vue 3: 构建响应式用户界面。
- Lottie: 显示矢量动画,支持用户等级的动态变化。
- canvas-confetti: 用于生成烟花效果,支持细粒度的控制和动画定制。
实现步骤
1. 安装依赖
npm install canvas-confetti lottie-web
2. 代码实现
以下是核心代码的分步解析:
初始化状态和依赖
import confetti from 'canvas-confetti'
import lottie from 'lottie-web'
import { watchEffect, computed, ref } from 'vue'
import { useGlobalStore } from '@/stores/global'
import { useUserStore } from '@/stores/user'
- 引入
canvas-confetti和lottie-web。 - 使用
useGlobalStore和useUserStore来获取全局状态和用户数据。
动态动画加载
通过 watchEffect 监听对话框状态,动态加载 Lottie 动画和烟花效果:
watchEffect(() => {if (value.value) {// 加载 Lottie 动画animation = lottie.loadAnimation({container: animationContainer.value,renderer: 'svg',loop: true,autoplay: true,animationData: getLottieFileByUserLevel(),})// Lottie 动画加载完成后触发烟花效果animation.addEventListener('DOMLoaded', startConfetti)} else {// 清除动画和烟花if (animation) {animation.destroy()animation = null}if (animationFrameId) {cancelAnimationFrame(animationFrameId)animationFrameId = null}}
})
创建烟花效果
通过 requestAnimationFrame 控制粒子效果的动态生成:
const startConfetti = () => {const duration = 15 * 1000 // 烟花持续时间const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 2100 }const animationEnd = Date.now() + durationconst frame = () => {const timeLeft = animationEnd - Date.now()if (timeLeft <= 0) {if (animationFrameId) cancelAnimationFrame(animationFrameId)return}const particleCount = 10 * (timeLeft / duration)confetti({...defaults,particleCount,origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 },})confetti({...defaults,particleCount,origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 },})// 循环调用animationFrameId = requestAnimationFrame(frame)}frame()
}
这里的 randomInRange 函数用来随机生成粒子发射的方向和范围:
function randomInRange(min: number, max: number) {return Math.random() * (max - min) + min
}
根据用户等级加载 Lottie 动画
不同的用户等级对应不同的动画文件:
const getLottieFileByUserLevel = () => {let level = userStore.userLevelif (level === 2) {return Level02Lottie} else if (level === 3) {return Level03Lottie} else if (level === 4) {return Level04Lottie} else if (level === 5) {return Level05Lottie} else if (level === 6) {return Level06Lottie} else {return Level01Lottie}
}
3. 完整代码
<script lang="ts" setup>
import confetti from 'canvas-confetti'
import { watchEffect, computed, ref } from 'vue'
import { useGlobalStore } from '@/stores/global'
import { useUserStore } from '@/stores/user'
import lottie from 'lottie-web'
import Level01Lottie from '@/assets/lottie/Level01.json'
import Level02Lottie from '@/assets/lottie/Level02.json'
import Level03Lottie from '@/assets/lottie/Level03.json'
import Level04Lottie from '@/assets/lottie/Level04.json'
import Level05Lottie from '@/assets/lottie/Level05.json'
import Level06Lottie from '@/assets/lottie/Level06.json'const globalStore = useGlobalStore()
const userStore = useUserStore()
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const animationContainer = ref()
let animation: any = null
let animationFrameId: number | null = nullconst value = computed({get() {return props.modelValue},set(value) {emit('update:modelValue', value)},
})const beforeClose = () => {globalStore.fireworkVisable.show = false
}// Confetti effect function with requestAnimationFrame
function randomInRange(min: number, max: number) {return Math.random() * (max - min) + min
}const getLottieFileByUserLevel = () => {let level = userStore.userLevelif (level === 2) {return Level02Lottie} else if (level === 3) {return Level03Lottie} else if (level === 4) {return Level04Lottie} else if (level === 5) {return Level05Lottie} else if (level === 6) {return Level06Lottie} else {return Level01Lottie}
}const startConfetti = () => {const duration = 15 * 1000const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 2100 }const animationEnd = Date.now() + durationconst frame = () => {const timeLeft = animationEnd - Date.now()if (timeLeft <= 0) {if (animationFrameId) cancelAnimationFrame(animationFrameId)return}const particleCount = 10 * (timeLeft / duration)confetti({...defaults,particleCount,origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 },})confetti({...defaults,particleCount,origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 },})// Continue the animation loopanimationFrameId = requestAnimationFrame(frame)}frame()
}watchEffect(() => {if (value.value) {// Load lottie animationanimation = lottie.loadAnimation({container: animationContainer.value,renderer: 'svg',loop: true,autoplay: true,animationData: getLottieFileByUserLevel(),})// Start confetti after lottie loadsanimation.addEventListener('DOMLoaded', startConfetti)} else {// Destroy lottie animation and cancel confetti animationif (animation) {animation.destroy()animation = null}if (animationFrameId) {cancelAnimationFrame(animationFrameId)animationFrameId = null}}
})
</script><template><div class="tipBox"><el-dialog v-model="value" title="" :before-close="beforeClose"><div ref="animationContainer" style="width: 100%; height: 100%"></div></el-dialog></div>
</template><style lang="scss" src="./style.scss" scoped />
总结
以上实现为用户提供了动态且炫酷的视觉体验:
- 对话框弹出时加载用户特定的动画。
- 使用
canvas-confetti模拟烟花特效,持续 15 秒。 - 对话框关闭时清理资源,避免性能问题。
这种效果非常适用于用户晋级、任务完成等场景,希望本文能对你有所启发!
相关文章:
使用 Vue 和 Canvas-Confetti 实现烟花动画特效
在开发中,为用户提供具有视觉冲击力的反馈是一种提升用户体验的好方法。今天,我们将结合 Vue 框架、canvas-confetti 和 Lottie 动画,创建一个动态对话框动画,其中包含炫酷的烟花特效。 效果图: 效果简介 当用户触发…...
【银河麒麟操作系统真实案例分享】内存黑洞导致服务器卡死分析全过程
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 现象描述 机房显示器连接服务器后黑屏ÿ…...
如何加强游戏安全,防止定制外挂影响游戏公平性
在现如今的游戏环境中,外挂始终是一个困扰玩家和开发者的问题。尤其是定制挂(Customized Cheats),它不仅复杂且隐蔽,更能针对性地绕过传统的反作弊系统,对游戏安全带来极大威胁。定制挂通常是根据玩家的需求…...
SpringBoot整合knife4j,以及会遇到的一些bug
这篇文章主要讲解了“Spring Boot集成接口管理工具Knife4j怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring Boot集成接口管理工具Knife4j怎么用”吧! 一…...
城电科技|光伏廊道是什么?安装光伏廊道有什么好处?
光伏廊道是什么?光伏廊道专门设计用于集中安装太阳能光伏发电系统的建筑物或构筑物,它可以将光伏转换成可以用于供电的清洁绿电。光伏廊道通常由阳能电池板、太阳能电池、控制器、逆变器、混凝土、钢材等材料组成,具备发电、坚固、耐用、防水…...
当DHCP服务器分配了同一个IP地址
当DHCP服务器分配了同一个IP地址给多个设备时,这通常会导致网络问题,如IP地址冲突,进而影响设备的网络连接。以下是详细的分析和解决步骤: 原因分析: IP地址租约未过期: 租约管理:DHCP服务器维…...
储能能量自动化调配装置功能介绍
随着可再生能源的快速发展,光伏发电已成为全球能源结构转型的关键技术之一。与此同时,储能技术作为实现光伏发电稳定输出的核心技术,得到了广泛关注。在企业电网中,光伏储能系统的运维管理不仅关乎能源利用效率,还涉及…...
vite5+vue3+Ts5 开源图片预览器上线
images-viewer-vue3:一款Vue3的轻量级图像查看器,它基于Flip动画技术,支持PC和h5移动网页预览照片,如果它是Vue3开发的产品。 npm开源地址:https://www.npmjs.com/package/images-viewer-vue3?activeTabreadme Flip 动画 < …...
【深度学习】深入解析长短期记忆网络(LSTMs)
长短期记忆网络(Long Short-Term Memory networks, LSTMs)是一种特殊的递归神经网络(RNN),专门设计用来解决标准 RNN 在处理长序列数据时的梯度消失和梯度爆炸问题。LSTMs 在许多序列数据任务中表现出色,如…...
从Web3到智能合约:探索新一代数据交互模式
随着互联网技术的不断演进,Web3的到来标志着互联网的一个新纪元。与传统的Web2相比,Web3倡导去中心化、更加开放和透明的网络架构,而智能合约则是其中的核心技术之一。本文将介绍Web3与智能合约的概念、应用以及它们如何改变数据交互模式&…...
排查bug的通用思路
⭐️前言⭐️ APP点击某个按钮没有反应/PC端执行某个操作后,响应较慢,通用的问题排查方法: 从多个角度来排查问题 🍉欢迎点赞 👍 收藏 ⭐留言评论 🍉博主将持续更新学习记录收获,友友们有任何问题可以在评…...
如何利用Python爬虫获得商品类目
在当今数字化时代,获取和分析数据的能力对于任何希望在市场上保持竞争力的企业来说都是至关重要的。对于电子商务平台和市场研究公司而言,获取商品类目数据尤为重要,因为这些数据可以帮助他们更好地理解市场趋势、优化产品目录并制定有效的营…...
如何通过 Windows 自带的启动管理功能优化电脑启动程序
在日常使用电脑的过程中,您可能注意到开机后某些程序会自动运行。这些程序被称为“自启动”或“启动项”,它们可以在系统启动时自动加载并开始运行,有时甚至在后台默默工作。虽然一些启动项可能是必要的(如杀毒软件)&a…...
大模型学习有什么发展前景?
前景人工智能大模型是指拥有超大规模参数(通常在十亿个以上)、复杂计算结构的机器学习模型。它通常能够处理海量数据,完成各种复杂任务,如自然语言处理、图像识别等。 2024年政府工作报告提出“发展新质生产力”,并将…...
Excel技巧:如何批量调整excel表格中的图片?
插入到excel表格中的图片大小不一,如何做到每张图片都完美的与单元格大小相同?并且能够根据单元格来改变大小?今天分享,excel表格里的图片如何批量调整大小。 方法如下: 点击表格中的一个图片,然后按住Ct…...
独著与编著的区别是?
独著和编著主要有以下区别: 一、创作性质 - 独著 - 独著是作者完全独立进行创作的作品。其内容是作者自己的研究成果、观点见解或者经验总结。作者从最初的选题构思,到资料收集、分析研究,再到内容撰写、修改润色等全过程都是独立完成的。…...
vue中pdf.js的使用,包括pdf显示,跳转指定页面,高亮关键词
目录 一、下载pdf.js 二、引入到本地的项目中 三、实现预览pdf 四、跳转到指定页面 五、利用pdf里面的find查找关键词 六、修改页面大小为实际大小 一、下载pdf.js https://github.com/mozilla/pdf.js 里面有很多的版本, 高版本的可能浏览器不兼容或者还要考…...
【Spring Boot】自动装配机制详解
1. 传统的 Spring 注入方式(基于 XML 配置) 在传统的 Spring 中,依赖注入(DI)通常通过 XML 配置文件来进行管理。常见的方式有两种: 通过 <property> 元素进行属性注入: <bean id&qu…...
Flink集群搭建整合Yarn运行
Flink 集群 1. 服务器规划 服务器h1、h4、h5 2. StandAlone 模式(不推荐) 2.1 会话模式 在h1操作 #1、解压 tar -zxvf flink-1.19.1-bin-scala_2.12.tgz -C /app/#2、修改配置文件 cd /app/flink-1.19.1/conf vim conf.yaml ##内容:## j…...
Linux Ubuntu 安装配置RabbitMQ,springboot使用RabbitMQ
rabbit-Ubuntu 一篇文章学会RabbitMQ 在Ubuntu上查看RabbitMQ状态可以通过多种方式进行,包括使用命令行工具和Web管理界面。以下是一些常用的方法: 1-使用systemctl命令: sudo systemctl start rabbitmq-server sudo systemctl status ra…...
如何用Planck-Pi实现低成本嵌入式开发?基于F1C200s的全栈方案解析
如何用Planck-Pi实现低成本嵌入式开发?基于F1C200s的全栈方案解析 【免费下载链接】Planck-Pi Super TINY & Low-cost Linux Develop-Kit Based On F1C200s. 项目地址: https://gitcode.com/gh_mirrors/pl/Planck-Pi Planck-Pi作为一款基于全志F1C200s芯…...
5分钟终极指南:Windows虚拟手柄驱动ViGEmBus完整教程
5分钟终极指南:Windows虚拟手柄驱动ViGEmBus完整教程 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 想要在Windows系统上享受专业级的游戏控制体…...
ERNIE-4.5-0.3B-PT智能合约分析:区块链安全检测系统
ERNIE-4.5-0.3B-PT智能合约分析:区块链安全检测系统 1. 引言 区块链开发者们经常面临一个头疼的问题:智能合约部署后才发现存在安全漏洞,导致资产损失。传统的安全审计需要专业团队花费数天甚至数周时间,成本高昂且效率低下。现…...
闪豆视频下载器 v20260329-B站抖音爱优腾多平台批量下载,画质自选速度快
一款面向电脑端打造的多平台视频批量下载工具,支持 B 站、A 站、抖音、爱奇艺、优酷、腾讯视频等主流内容平台,覆盖范围较广,适合经常需要从不同平台保存视频内容的用户使用。 软件操作流程简单直接,解析和下载过程清晰易懂&#…...
OFA-VE环境部署:Python 3.11+PyTorch+CUDA一站式配置手册
OFA-VE环境部署:Python 3.11PyTorchCUDA一站式配置手册 1. 引言:认识OFA-VE视觉推理系统 OFA-VE是一个基于阿里巴巴达摩院OFA大模型构建的多模态推理平台,专门用于分析图像内容与文本描述之间的逻辑关系。这个系统采用了现代化的赛博朋克视…...
Pixel Script Temple 效果进阶:YOLOv11目标识别引导的精准构图像素画
Pixel Script Temple 效果进阶:YOLOv11目标识别引导的精准构图像素画 1. 效果亮点预览 当像素艺术遇上目标检测技术,会碰撞出怎样的火花?最新发布的YOLOv11模型与Pixel Script Temple的结合,让像素画创作进入了精准构图的新阶段…...
当openclaw遇见ai:借助快马平台打造能理解内容的智能抓取命令
最近在开发一个叫openclaw的网页抓取工具时,发现单纯抓取网页内容已经不能满足需求了。很多时候我们需要对抓取的内容进行二次处理,比如自动摘要、分类、去噪等。这时候就想到了借助AI来增强工具的能力,正好发现了InsCode(快马)平台这个好帮手…...
多模态Agent架构实战落地:从需求分析到生产部署
多模态Agent架构实战落地:从需求分析到生产部署 随着大语言模型技术的普及,单一文本交互的智能系统已无法满足复杂业务场景需求——电商平台需要同时理解用户的商品描述文本、实拍图片和售后语音诉求,教育场景需要处理手写作业、视频讲解和文…...
别再死记硬背了!用eNSP模拟一个500人公司的真实网络(含VLAN、MSTP、VRRP完整配置)
从零构建500人企业网络:eNSP实战中的VLAN、MSTP与VRRP深度解析 当你第一次面对企业级网络规划时,是否曾被各种协议和配置弄得晕头转向?本文将以一个真实的500人企业网络为蓝本,带你用华为eNSP模拟器完成从需求分析到最终实现的完整…...
BGE-Reranker-v2-m3为何必须用?RAG幻觉过滤入门必看
BGE-Reranker-v2-m3为何必须用?RAG幻觉过滤入门必看 如果你正在搭建RAG系统,或者已经搭建了但总觉得回答质量时好时坏,经常出现“幻觉”——也就是模型一本正经地胡说八道——那你很可能遇到了一个核心问题:向量检索“搜不准”。…...
