目录
🪂 演示
🛹 目录树
🐔 安装
🤖 global.d.ts
😷 zkConfettiCanvas.vue
🌍 confetti.ts
🎋 confettiIndex.ts
😷 index.vue
🥰😉 谢谢观看
🤺🤺🤺前期回顾
前端:UI 交互式特效 —— Css、Js_彩色之外的博客-CSDN博客css 使用示例,及源码https://blog.csdn.net/m0_57904695/article/details/131677759?spm=1001.2014.3001.5501
🪂 演示
彩屑飘落 特效一键直达https://www.kirilv.com/canvas-confetti/
🛹 目录树
1:封装canvas
2:封装彩屑 Ts
3:抽离逻辑判断 Ts
4:页面调用
src
|--- types
|--- global.d.ts
|--- components
|--- zkConfettiCanvas.vue
|--- utils
|--- confetti.ts
|--- confettiIndex.ts
|--- views
|---- home.vue
🐔 安装
pnpm install --save canvas-confetti
🤖 global.d.ts
// 申明外部 npm 插件模块
declare module 'canvas-confetti';
😷 zkConfettiCanvas.vue
<template>
<canvas
id="confetti"
style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
"
></canvas>
</template>
🌍 confetti.ts
interface Origin {
x?: number;
y?: number;
}
/**
* 显示彩屑效果
* @param { number } type - 彩屑效果类型
* 1: 默认屏幕中间喷射
* 2: 满屏随机炸裂
* 3: 屏幕中间随机位置喷射
* 4: 屏幕两端向内喷射
* @param { Origin } origin - 彩屑的原点坐标
* x: x轴位置,默认值为0.5
* y: y轴位置,默认值为0.7
* @url https://www.kirilv.com/canvas-confetti/
* @returns { Promise<void> } - Promise对象
*/
export async function showConfetti(
type: number = 1,
origin: Origin = { x: 0.5, y: 0.7 }
): Promise<void> {
await import('canvas-confetti').then((confetti) => {
const canvasEle: HTMLCanvasElement | null =
document.querySelector('#confetti');
if (!canvasEle) return;
canvasEle.style.zIndex = '9999';
const myConfetti = confetti.create(canvasEle, {
resize: true,
useWorker: true,
disableForReducedMotion: true,
});
import('./confettiIndex').then((confettiIndex) => {
confettiIndex.getUserDescribe(type, myConfetti, origin);
});
setTimeout(() => {
canvasEle.style.zIndex = '-1';
myConfetti.reset();
}, 3000);
});
}
🎋 confettiIndex.ts
interface Origin {
x?: number;
y?: number;
}
export function getUserDescribe(type: number, myConfetti: any, origin: Origin) {
const describeForNameMap = [
[
() => type === 1, // 判断条件
() =>
myConfetti({
particleCount: 100,
spread: 70,
// 默认屏幕中间喷射,可以在引入的时候传入参数,如 showConfetti({x:0.1,y:0.5})
origin: origin,
}), // 执行函数
],
[
() => type === 2,
() => {
let duration = 3 * 1000;
let animationEnd = Date.now() + duration;
let defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
function randomInRange(min: number, max: number) {
return Math.random() * (max - min) + min;
}
let interval = setInterval(function () {
let timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
let particleCount = 50 * (timeLeft / duration);
myConfetti(
Object.assign({}, defaults, {
particleCount,
origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 },
})
);
myConfetti(
Object.assign({}, defaults, {
particleCount,
origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 },
})
);
}, 250);
},
],
[
() => type === 3,
() => {
function randomInRange(min: number, max: number) {
return Math.random() * (max - min) + min;
}
myConfetti({
angle: randomInRange(55, 125),
spread: randomInRange(50, 70),
particleCount: randomInRange(50, 100),
origin: origin,
});
},
],
[
() => type === 4,
() => {
const duration = performance.now() + 1 * 1000;
const confettiColors = ['#6967fe', '#85e9f4', '#e16984'];
void (function frame() {
myConfetti({
particleCount: confettiColors.length,
angle: 60,
spread: 55,
origin: { x: 0 },
colors: confettiColors,
});
myConfetti({
particleCount: confettiColors.length,
angle: 120,
spread: 55,
origin: { x: 1 },
colors: confettiColors,
});
if (performance.now() < duration) {
requestAnimationFrame(frame);
}
})();
},
],
];
function myError() {
throw new Error('没有找到对应的效果');
}
// 通过find方法找到子数组中的第一个函数(判断条件)为true的子数组
let getDescribe = describeForNameMap.find((item) => item[0]());
// 子数组存在则运行子数组中的第二个元素(执行函数)
getDescribe ? getDescribe[1]() : myError();
}
😷 index.vue
<template>
<div>
<zw-confetti-canvas />
<el-button type="success" @click="onTrigger">发射彩屑</el-button>
</div>
</template>
<script setup lang="ts">
import { showConfetti } from '/@/utils/confetti';
const onTrigger = () => {
showConfetti();
};
</script>
完毕!以上为全部代码,复制即用,默认封装四种特效、可以按照需求自定义奥~
🥰😉 谢谢观看
_______________________________ 期待再见 _______________________________