在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-confetti
和 confetti-confetti
。
npm i canvas-confetti
npm i @types/canvas-confetti
这是最重要的一步,仓库推荐的安装方法在 React/TypeScript 项目中会有类型定义问题。
canvas-confetti:这是实际的JavaScript库,它包含了实现五彩纸屑动画效果的所有功能代码。当你调用这个库中的函数时,就会在页面上看到彩带效果。所以,真正起作用(产生视觉效果)的是 canvas-confetti。
@types/canvas-confetti:这是一个类型定义包,专门为TypeScript设计的。它本身不包含任何可执行的动画代码,而是为 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 成功生成结果之后就会抛出礼花🎉
这个按钮组件的代码如下:
"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 类型错误
如果遇到类型错误,确保:
- 安装了
@types/canvas-confetti
- 在文件顶部添加类型声明(如果需要)
在 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