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

🐔 安装

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

import { nextTick } from "vue";
interface Origin {
  x?: number;
  y?: number;
}
// 注释需要放在函数上面,不然调用鼠标放上去没提示
/**
 * 显示彩屑效果
 * @param { number } type - 彩屑效果类型
 * @type 1: 默认屏幕中间喷射
 * @type 2: 满屏随机炸裂
 * @type 3: 屏幕中间随机位置喷射
 * @type 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 = 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);
    });
    nextTick(() => {
      canvasEle.style.zIndex = "-1";
      myConfetti.reset();
    });
  });
}

🎋 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,
      () => {
        const duration = 3 * 1000;
        const animationEnd = Date.now() + duration;
        const defaults = {
          startVelocity: 30,
          spread: 360,
          ticks: 60,
          zIndex: 0,
        };

        function randomInRange(min: number, max: number) {
          return Math.random() * (max - min) + min;
        }

        const interval: any = setInterval(function () {
          const timeLeft = animationEnd - Date.now();

          if (timeLeft <= 0) {
            return clearInterval(interval);
          }

          const 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的子数组
  const 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>

仓库:Vite + Ts + Vue3 - template --- 模板: 🎉🎉🔥 Vite + Vue3 + Ts + router + Vuex + axios + eslint 、prettier、stylelint、husky、gitCommit--- 集成多种组件、Hooks支持开封即用,严格的代码质量检验、祝您轻松上大分😷🤺🤺🤺 【动态路由、特效、N个组件、N个自定义指令...】https://gitee.com/zhang-kun8888/Vite--Ts--Vue3---template 

完毕!以上为全部代码,复制即用,默认封装四种特效、可以按照需求自定义奥~

 🥰😉  谢谢观看

7730e2bd39d64179909767e1967da702.jpeg

 _______________________________  期待再见  _______________________________

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彩色之外

你的打赏是我创作的氮气加速动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值