🎊

[electron + Next.js] canvas-confettiを使って簡単に紙吹雪を降らす!

2023/02/19に公開

はじめに

紙吹雪を使用したいタイミングがあり、
自分なりにコンポーネント化してみたので、備忘録的にzennを書かせていただきます。

完成イメージ

環境

electron + next.js + typescript
node-version 16.0.0

canvas-confetti
https://github.com/catdad/canvas-confetti#readme

import

npm install --save canvas-confetti
npm install --save @types/canvas-confetti

or

yarn add canvas-confetti
yarn add @types/canvas-confetti

code

confetti.tsxという紙吹雪コンポーネントを作成してみたので今回はこれを使用します。

confetti.tsx

import { useEffect, useRef, useImperativeHandle, forwardRef } from 'react'
import CanvasConfetti ,{CreateTypes, Shape} from "canvas-confetti"

interface IProps {
}
export interface IConfettiFunc {
	show: () => void
	hide: () => void
}

const intervalTime = 400

const Confetti = forwardRef<IConfettiFunc, IProps>((props: IProps, ref) => {
	const canvasRef = useRef<HTMLCanvasElement>()
	let confetti: CreateTypes

	useImperativeHandle(ref, () => ({
		show, hide
	}));

	useEffect(()=>{
		if(!confetti) confetti = CanvasConfetti.create(canvasRef.current, { resize: true });
	}, [])

	const show =()=> {
		update()
	}

	const update =()=> {
		if(!confetti) return
		const option = {
			origin: {
				x: Math.random(),
				y: 0
			},
			colors: [
				'#00f',
				'#0f0',
				'#f00',
			],
			shapes: ['square'] as Shape[],
			particleCount: 8,
			ticks: 800,
		}
		confetti(option);
		setTimeout(function() {
			requestAnimationFrame(update)
		}, intervalTime)
	}

	const hide =()=> {
		if(confetti) confetti.reset()
	}

	  return (
		<canvas ref={canvasRef} style={{width: "100%", height: "100vh"}}/>
	)
});
export default Confetti

index.tsx

import { useEffect, useRef } from 'react'
import Confetti, {IConfettiFunc} from '../components/confetti'

const IndexPage = () => {
	const confettiRef = useRef<IConfettiFunc>()

	useEffect(() => {
		confettiRef.current.show()
		return () => {
			confettiRef.current.hide()
		}
	}, [])

	return (
		<Confetti ref={confettiRef}/>
	)
}

export default IndexPage

useRefを使用して、<confetti/>のrefを取得してください。

あとは、好きなタイミングで
表示

confettiRef.current.show()

非表示

confettiRef.current.hide()

を行ってください。

カスタマイズ

confetti.tsxのoption中身を変更していきます。

origin
x, yどちらもキャンバス全体を0-1に正規化したものになります。
ex. 画面右半分にのみ紙吹雪をふらしたいとき

origin: {
	x: Math.random() * 0.5,
	y: 0
}

と変更して下さい。

colors
colorの配列で色を変更することが可能です、

particleCount
一度に降らせる紙吹雪の量です。

※canvas-confettiは紙吹雪を降らせるタイミングでcolorsを上から順に取得していきます。
ですので、colors.lengthよりparticleCountが少ない場合、振らない色が発生するので注意してください。

shapes
紙吹雪の形です。
'circle', 'square', 'star'
から、選択可能です。(もちろん複数入れることも可能です。)

ticks
生存時間です。

その他、パラメーターまだまだありますので、公式git参考にしてください。
https://github.com/catdad/canvas-confetti#readme

intervalTime
紙吹雪を降らせる間隔です。

最後に

紙吹雪を爆速で実装したいときは、すごく便利です!
なにかあれば、コメントいただけますと幸いです。

Discussion