Open2
Reactで紙吹雪アニメーションを作成する方法について
Reactで紙吹雪アニメーションを作成する
Reactで紙吹雪のようなアニメーションを実装する時は、既存のライブラリを使用すると、簡単に紙吹雪のアニメーションを追加できます。
おすすめのライブラリをいくつか紹介します。
react-confetti
react-confetti
は、画面全体に紙吹雪を表示するためのライブラリです。
インストール方法:
npm install react-confetti
使用例:
import React from 'react';
import Confetti from 'react-confetti';
import { useWindowSize } from 'react-use';
const ConfettiComponent = () => {
const { width, height } = useWindowSize();
return <Confetti width={width} height={height} />;
};
export default ConfettiComponent;
react-dom-confetti
react-dom-confetti
は、特定の要素から紙吹雪が飛び出すような効果を実現できます。
インストール方法:
npm install react-dom-confetti
使用例:
import React, { useState } from 'react';
import Confetti from 'react-dom-confetti';
const ConfettiButton = () => {
const [active, setActive] = useState(false);
const handleClick = () => {
setActive(true);
// 一定時間後に非表示にする
setTimeout(() => setActive(false), 3000);
};
return (
<div>
<button onClick={handleClick}>お祝いする</button>
<Confetti active={active} />
</div>
);
};
export default ConfettiButton;
カスタム実装
ライブラリを使わずに、自分で紙吹雪アニメーションを実装することも可能です。CanvasやCSSアニメーションを使用して、独自のエフェクトを作成できます。
例: Canvasを使用した実装
import React, { useRef, useEffect } from 'react';
const CustomConfetti = () => {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const context = canvas.getContext('2d');
// キャンバスの初期設定やアニメーションのロジックをここに追加
}, []);
return <canvas ref={canvasRef} width={window.innerWidth} height={window.innerHeight} />;
};
export default CustomConfetti;
ただし、カスタム実装は手間がかかるため、まずは既存のライブラリを使用することをおすすめします。
これらの方法を使って、Reactアプリケーションに紙吹雪のアニメーションを簡単に追加できます。
必要に応じてカスタマイズしてみてください。
参考・引用
紙吹雪、ダイアログ Sample Code🌟
次のような紙吹雪、ダイアログ Sample Code🌟
'use client'
import { useState } from 'react'
import { Check, X } from 'lucide-react'
import Confetti from 'react-confetti'
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Dialog, DialogContent } from "@/components/ui/dialog"
export default function Component() {
const [rating, setRating] = useState(0)
const [isOpen, setIsOpen] = useState(true)
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent className="max-w-sm p-0 bg-white">
{isOpen && <Confetti
width={window.innerWidth}
height={window.innerHeight}
colors={['#ff6b6b', '#ff8787', '#ffa8a8']}
numberOfPieces={200}
gravity={0.2}
/>}
<Card className="border-0 shadow-none">
<CardContent className="p-6">
<Button
variant="ghost"
size="icon"
className="absolute right-4 top-4"
onClick={() => setIsOpen(false)}
>
<X className="h-4 w-4" />
</Button>
<div className="flex flex-col items-center justify-center space-y-4">
<div className="relative">
<div className="w-20 h-20 bg-red-500 rounded-full flex items-center justify-center animate-scale-up">
<Check className="w-10 h-10 text-white" />
</div>
</div>
<div className="text-center space-y-2">
<h2 className="text-xl font-semibold">ご支援ありがとうございます!</h2>
<p className="text-sm text-muted-foreground">チップを送信しました</p>
<p className="text-2xl font-bold">¥1,350</p>
</div>
<div className="w-full pt-4 space-y-2">
<p className="text-center text-sm">山田太郎さんの接客はいかがでしたか?</p>
<div className="flex justify-center space-x-1">
{[1, 2, 3, 4, 5].map((star) => (
<Button
key={star}
variant="ghost"
size="icon"
className={`hover:bg-transparent ${rating >= star ? 'text-yellow-400' : 'text-gray-300'}`}
onClick={() => setRating(star)}
>
<svg
className="w-8 h-8"
fill="currentColor"
viewBox="0 0 20 20"
>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
</svg>
</Button>
))}
</div>
</div>
</div>
</CardContent>
</Card>
</DialogContent>
</Dialog>
)
}