Vue3 + Ts + Vite —— 项目封装使用交互式 彩屑纷飞 示例 (亲测可用、复制即展示)

目录

演示

目录树 

安装

  global.d.ts

  zkConfettiCanvas.vue  

  confetti.ts

confettiIndex.ts

index.vue

   谢谢观看


前期回顾f8e3cc1a0f694ac2b665ca2ad14c49d7.png

前端: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

Vue3 + Ts + Vite —— 项目封装使用交互式 彩屑纷飞 示例 (亲测可用、复制即展示)_第1张图片

安装

pnpm install --save canvas-confetti

  global.d.ts

// 申明外部 npm 插件模块
declare module 'canvas-confetti';

  zkConfettiCanvas.vue  


  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 } - Promise对象
 */
export async function showConfetti(
	type: number = 1,
	origin: Origin = { x: 0.5, y: 0.7 }
): Promise {
	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




Vue3 + Ts + Vite —— 项目封装使用交互式 彩屑纷飞 示例 (亲测可用、复制即展示)_第2张图片

完毕!以上为全部代码,复制即用,默认封装四种特效、可以按照需求自定义奥~Vue3 + Ts + Vite —— 项目封装使用交互式 彩屑纷飞 示例 (亲测可用、复制即展示)_第3张图片

   谢谢观看

7730e2bd39d64179909767e1967da702.jpeg

 _______________________________  期待再见  _______________________________

你可能感兴趣的:(前端,javascript,html)