HSawana9

在React/Nextjs中使用"canvas-confetti"而不是"react-canvas-confitti"

Sawana Huang Fri Aug 01 2025

在尝试使用canvas-confetti时,我发现自己没有理解示例网站应该怎么使用、导入包时出现了一些bug、官方仓库用的是nodejs而不是react……上面提到的种种问题将在这篇博客得到解决!

在尝试使用canvas-confetti时,我发现自己没有理解示例网站应该怎么使用、导入包时出现了一些bug、官方仓库用的是nodejs而不是react……

上面提到的种种问题将在这篇博客得到解决!

这是一篇小小的记录和分享,记录了如何在React框架中使用canvas-confetti,希望能帮到遇到和我一样问题的人。

核心问题:如何在react/nextjs中使用"canvas-confetti"而不是"react-canvas-confetti"

为什么选择 canvas-confetti

canvas-confetti 是官方推荐的库,相比 react-canvas-confetti 有更好的维护和更多的功能选项。但是在 React 项目中使用时会遇到一些配置问题。

这个解决方法来自 StackOverflow,经过实践验证非常有效。

完整实现步骤

安装包时需要添加 @types

重要:在 TypeScript 项目中应当同时下载 @types/canvas-confetticonfetti-confetti

npm i canvas-confetti
npm i @types/canvas-confetti

这是最重要的一步,仓库推荐的安装方法在 React/TypeScript 项目中会有类型定义问题。

canvas-confetti:这是实际的JavaScript库,它包含了实现五彩纸屑动画效果的所有功能代码。当你调用这个库中的函数时,就会在页面上看到彩带效果。所以,真正起作用(产生视觉效果)的是 canvas-confetti。

@types/canvas-confetti:这是一个类型定义包,专门为TypeScript设计的。它本身不包含任何可执行的动画代码,而是为 canvas-confetti 库中的所有函数和参数提供了类型信息。

从官方示例网站复制粘贴函数

前往 canvas-confetti 官方示例网站

Canvas Confetti 示例网站

链接网页中的每一个代码块都记录了一个完整的函数,你只需要复制粘贴它们,并且包装成回调函数就可以在 React 中使用。

例如将这个函数包装好导出:

const ConfettiAction = () => {
  // 将整块代码复制下来
  var duration = 15 * 1000;
  var animationEnd = Date.now() + duration;
  var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };

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

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

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

    var particleCount = 50 * (timeLeft / duration);
    // since particles fall down, start a bit higher than random
    confetti(
      Object.assign({}, defaults, {
        particleCount,
        origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 },
      }),
    );
    confetti(
      Object.assign({}, defaults, {
        particleCount,
        origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 },
      }),
    );
  }, 250);
};

export { ConfettiAction };

调用函数,如在 button 的 onclick 中调用

在你的 React 组件中导入并使用:

import { ConfettiAction } from "./confetti-actions";

function MyComponent() {
  return <button onClick={ConfettiAction}>🎉 庆祝一下!</button>;
}

实际应用示例

体验一下这个组件:

点击 generate 成功生成结果之后就会抛出礼花🎉

这个按钮组件的代码如下:

confetti-button.tsx
"use client";

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import confetti from "canvas-confetti";

interface ConfettiButtonProps {
  className?: string;
}

export default function ConfettiButton({
  className,
  ...props
}: React.ComponentProps<"div"> & ConfettiButtonProps) {
  return (
    <div
      className={cn("py-4 md:py-4 lg:py-6 xl:py-6 2xl:py-8", className)}
      {...props}
    >
      <Button className="cursor-pointer" onClick={ConfettiAction}>
        Congratulation!!! 🎉
      </Button>
    </div>
  );
}

function ConfettiAction() {
  // e.preventDefault(); // 阻止默认行为

  const count = 200;
  const defaults = {
    origin: { y: 0.7 },
  };

  function fire(particleRatio: number, opts: confetti.Options) {
    confetti({
      ...defaults,
      ...opts,
      particleCount: Math.floor(count * particleRatio),
    });
  }

  fire(0.25, {
    spread: 26,
    startVelocity: 55,
  });
  fire(0.2, {
    spread: 60,
  });
  fire(0.35, {
    spread: 100,
    decay: 0.91,
    scalar: 0.8,
  });
  fire(0.1, {
    spread: 120,
    startVelocity: 25,
    decay: 0.92,
    scalar: 1.2,
  });
  fire(0.1, {
    spread: 120,
    startVelocity: 45,
  });
}

常见问题解决

TypeScript 类型错误

如果遇到类型错误,确保:

  1. 安装了 @types/canvas-confetti
  2. 在文件顶部添加类型声明(如果需要)

在 Next.js 中的使用

在 Next.js 中使用时,可能需要动态导入以避免 SSR 问题:

import dynamic from "next/dynamic";

const ConfettiButton = dynamic(() => import("./ConfettiButton"), {
  ssr: false,
});

更多效果

你可以在官方示例网站找到各种不同的礼花效果:

  • 烟花效果
  • 彩带效果
  • 爆炸效果
  • 持续效果

每个效果都有对应的代码示例,复制粘贴即可使用。

总结

使用 @types/canvas-confetti 而不是 react-canvas-confetti 的优势:

  • 更好的 TypeScript 支持
  • 更多的自定义选项
  • 官方维护,更新及时
  • 更小的包体积

通过这种方法,你可以轻松地在 React/Next.js 项目中添加漂亮的庆祝动效!


👋 关于我
我是一个正在学习和实现网站开发的开发者,希望在今年运营出一个 MRR $100 的作品。
如果你发现了什么问题、可改进的地方,或者只是想随意地聊聊天,都非常欢迎联系我!
即刻 @Sawana | X @HSawana9

作者:Sawana Huang
发布时间:2025年8月1日

声明: 本文采用CC BY-NC-SA 4.0许可协议,转载请注明出处。