Discord-inspired canvas confetti effect for React. See a demo.
yarn add @stevent-team/react-party
Spread the canvasProps
returned from the hook into a html canvas
element. This includes styles to position the canvas over the whole screen.
import { useConfetti } from '@stevent-team/react-party'
const MyComponent = () => {
const { createConfetti, canvasProps } = useConfetti()
return <>
<canvas {...canvasProps} />
<button onClick={createConfetti}>Click Me!</button>
</>
}
Customise the behaviour of the confetti by passing options to useConfetti
.
import { useConfetti } from '@stevent-team/react-party'
const MyComponent = () => {
const { createConfetti, canvasProps } = useConfetti({
// Control the distribution of shapes
shapeWeights: {
triangle: 2,
circle: 2,
square: 3,
star: 1,
},
// Speed up the movement
speed: 1.2,
// Decrease gravity,
gravity: 6,
// Use your own colors #vampireconfetti
colors: [
'red',
'orange',
'darkred',
'black',
]
})
return <>
<canvas {...canvasProps} />
<button onClick={createConfetti}>Click Me!</button>
</>
}
You can pass a sourceRef
to createConfetti()
to customise where the confetti appears from.
import { useConfetti } from '@stevent-team/react-party'
const MyComponent = () => {
const holeRef = useRef()
const { createConfetti, canvasProps } = useConfetti()
return <>
<canvas {...canvasProps} />
<AHoleInTheWall ref={holeRef}>
<button onClick={() => createConfetti({ sourceRef: holeRef })}>Click Me!</button>
</>
}
The canvasProps
object contains ref
and style
. The ref is required to render confetti, but you can either use your own styles and just pass the ref, or override the styles like below:
import { useConfetti } from '@stevent-team/react-party'
const MyComponent = () => {
const { createConfetti, canvasProps } = useConfetti()
return <>
<canvas {...canvasProps} style={{ ...canvasProps.style, backgroundColor: 'black' }} />
<button onClick={createConfetti}>Click Me!</button>
</>
}
React Party supports custom particle drawing functions, including images.
import { useRef } from 'react'
import { useConfetti, loadImage, drawImageParticle } from '@stevent-team/react-party'
const MyComponent = () => {
// Use a react ref to store the image
const imageRef = useRef()
useEffect(() => {
loadImage('https://example.com/image.svg')
.then(img => imageRef.current = img)
}, [])
const { createConfetti, canvasProps } = useConfetti({
// Set up a custom image particle
shapeFunctions: {
myCustomImage: drawImageParticle(imageRef.current),
},
// Tell the library to only use your custom particle function
shapeWeights: {
myCustomImage: 1,
},
// Stop the confetti from rotating or flipping
twirl: 0,
initialAngle: 0,
angleIncrement: 0,
initialFlip: 0,
flipIncrement: 0,
})
return <>
<canvas {...canvasProps} />
<button onClick={createConfetti}>Click Me!</button>
</>
}
Property | Type | Default | Description |
---|---|---|---|
gravity |
Number | 9.8 |
A number representing the gravity applied to each particle. Controls vertical acceleration. |
wind |
Number | 0 |
A number between -1 and 1 that applies wind to each particle. Controls horizontal acceleration. |
speed |
Number | 1 |
The speed of the simulation. |
killDistance |
Number | 100 |
The number of pixels past the edges of the canvas that particles will be deleted. |
count |
Number | 75 |
The amount of particles that will be spawned on each call to createConfetti . |
duration |
Number | 0 |
Distributes confetti over this many milliseconds on each call to createConfetti . |
initialVelocity |
Vector | [0, -3] |
A vector representing the initial x and y velocity of each particle. |
initialVelocitySpread |
Vector | [5, 7] |
A vector representing an x and y velocity spread that's applied to the initialVelocity values to randomise the spread of confetti. |
diameter |
Range or number | [10, 30] |
Minimum and maximum values for the diameter of each particle in pixels. Set to a number to use the same value for every particle. |
twirl |
Range or number | [0, 0.2] |
Minimum and maximum values for the twirl of each particle between 0 and 1. Offsets the centerpoint of each particle. Set to a number to use the same value for every particle. |
initialAngle |
Range or number | [0, 360] |
Minimum and maximum values for the initial angle of each particle in degrees. Set to a number to use the same value for every particle. |
angleIncrement |
Range or number | [-10, 10] |
Minimum and maximum values for the angle increment every frame of each particle in degrees. Set to a number to use the same value for every particle. |
initialFlip |
Range or number | [0, 360] |
Minimum and maximum values for the initial flip of each particle in degrees. Set to a number to use the same value for every particle. |
flipIncrement |
Range or number | [-10, 10] |
Minimum and maximum values for the flip increment every frame of each particle in degrees. Set to a number to use the same value for every particle. |
rotationVelocityCoefficient |
Number | 0.8 |
A number that is multiplied with the velocity of the particle to adjust the flip each frame. Essentially causes a particle to flip faster if its velocity is higher. Set to 0 to disable. |
colors |
String[] | DEFAULT_COLORS |
An array of CSS colors. |
shapeFunctions |
Record<string, function> | DEFAULT_SHAPE_FUNCTIONS |
An object of functions for each shape that is used to draw them. See below for more details. |
shapeWeights |
Record<string, number> | { triangle: 1, circle: 1, star: 1, square: 1 } |
An object mapping shapes to their weights. A higher weight will cause that shape to appear more often. All keys in this array must also appear in shapeFunctions object. |
Property | Type | Default | Description |
---|---|---|---|
count |
Number | 75 |
The amount of particles that will be spawned. Overrides the count property in the options passed to useConfetti . |
duration |
Number | 0 |
Distributes confetti over this many milliseconds. Overrides the duration property in the options passed to useConfetti . |
sourceRef |
React ref | Pass in a ref to use as the source of the confetti. By default, document.activeElement will be used if this isn't set. |
The following shapes are provided by default:
line
circle
triangle
square
pentagon
hexagon
heptagon
octagon
diamond
star
hexagram
You can define your own functions inside the shapeFunctions
option. Spread in the default shapes that are exported if you'd simply like to add a function without removing the defaults.
Each function receives an object with p
and ctx
as parameters, and you can use these to render a custom shape.
import { DEFAULT_SHAPE_FUNCTIONS } from '@stevent-team/react-party'
const shapeFunctions = {
...DEFAULT_SHAPE_FUNCTIONS,
myCustomShape: ({ p, ctx }) => {
// Draw a square
ctx.fillStyle = p.color
ctx.beginPath()
ctx.rect(
-p.diameter * p.twirl, -p.diameter * p.twirl,
p.diameter, p.diameter,
)
ctx.fill()
},
}
Check out drawing.js to see the currently implemented particle drawing functions, which are also exported from this library.
To test the components in this library, follow the steps below:
- Clone the repo onto your machine
- Run
yarn
to install dependencies - Run
yarn dev
to start the sample project
Build the library to dist
using yarn build
. You can build the sample project using yarn build:sample
.
Issue contributions and PRs are greatly welcomed and appreciated!
@stevent-team/react-party
is licensed under MIT
Created with love by the Stevent Team π