Skip to content

Commit c4078e7

Browse files
authored
Merge pull request #90 from ashtonisher/feature
feat: Add 3D rotation effect option for snowflakes
2 parents 24f2435 + bd7f4db commit c4078e7

15 files changed

Lines changed: 321 additions & 53 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ All available properties are detailed below.
6666
| `images` | An array of images that will be rendered as the snowflakes instead of the default circle shapes. | `undefined` |
6767
| `radius` | The minimum and maximum radius of the snowflake in pixels.<br/><br/>The value for each snowflake will be randomly selected within this range. | `[0.5, 3.0]` |
6868
| `rotationSpeed` | The minimum and maximum rotation speed of the snowflake (in degrees of rotation per frame).<br/><br/>The rotation speed determines how quickly the snowflake rotates when an image is being rendered.<br/><br/>The value for each snowflake will be randomly selected within this range. | `[-1.0, 1.0]` |
69+
| `enable3DRotation`| Enable 3D rotation effect (like falling leaves).<br/><br/>When enabled, snowflakes will rotate on X, Y, and Z axes, creating a more realistic 3D tumbling effect.<br/><br/>Works with both images and circles. | `false` |
6970
| `snowflakeCount` | The number of snowflakes to be rendered. | `150` |
7071
| `speed` | The minimum and maximum speed of the snowflake (in pixels per frame).<br/><br/>The speed determines how quickly the snowflake moves along the y axis (vertical speed).<br/><br/>The value for each snowflake will be randomly selected within this range. | `[1.0, 3.0]` |
7172
| `style` | Any style properties that will be passed to the canvas element. | `undefined` |
7273
| `wind` | The minimum and maximum wind of the snowflake (in pixels per frame).<br/><br/>The wind determines how quickly the snowflake moves along the x axis (horizontal speed).<br/><br/>The value for each snowflake will be randomly selected within this range. | `[-0.5, 2.0]` |
73-
| `opacity` | The minimum and maximum opacity of the snowflake.<br/><br/>The value for each snowflake will be randomly selected within this range. | `[1, 1]` |
74+
| `opacity` | The minimum and maximum opacity of the snowflake.<br/><br/>The value for each snowflake will be randomly selected within this range. | `[1, 1]` |
7475

7576
## Using Images
7677

packages/demo/src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ snowflake.src = logo
1414
const images = [snowflake]
1515

1616
const App = () => {
17-
const { color, snowflakeCount, radius, speed, wind, useImages, opacity } = useSettingsStore()
17+
const { color, snowflakeCount, radius, speed, wind, useImages, opacity, enable3DRotation } = useSettingsStore()
1818

1919
return (
2020
<div className="app">
@@ -26,6 +26,7 @@ const App = () => {
2626
wind={wind}
2727
images={useImages ? images : undefined}
2828
opacity={opacity}
29+
enable3DRotation={enable3DRotation}
2930
/>
3031
<a className="title" href={githubURL} style={{ color }}>
3132
<img src={logo} alt="Snowflake Logo" />

packages/demo/src/components/Settings/Settings.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,17 @@ const Settings = () => {
106106
label="Use Images"
107107
/>
108108
</div>
109+
<div>
110+
<FormControlLabel
111+
control={
112+
<Checkbox
113+
checked={settings.enable3DRotation || false}
114+
onChange={(event) => settings.update({ enable3DRotation: event.target.checked })}
115+
/>
116+
}
117+
label="Enable 3D Rotation"
118+
/>
119+
</div>
109120
{settings.useImages ? (
110121
<>
111122
<div>

packages/demo/src/settings.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const useSettingsStore = create<SnowfallSettings>((set) => ({
1616
rotationSpeed: [-1.0, 1.0],
1717
opacity: [0.1, 0.2],
1818
useImages: false,
19+
enable3DRotation: false,
1920
update: (changes) => set(changes),
2021
setUseImages: (useImages) => {
2122
if (useImages) {

packages/react-snowfall/lib/Snowfall.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ export interface SnowfallProps extends Partial<SnowfallCanvasConfig> {
66
*/
77
style?: React.CSSProperties;
88
}
9-
export declare const Snowfall: ({ color, changeFrequency, radius, speed, wind, rotationSpeed, opacity, snowflakeCount, images, style, }?: SnowfallProps) => JSX.Element;
9+
export declare const Snowfall: ({ color, changeFrequency, radius, speed, wind, rotationSpeed, opacity, snowflakeCount, images, enable3DRotation, style, }?: SnowfallProps) => JSX.Element;
1010
export default Snowfall;

packages/react-snowfall/lib/Snowfall.js

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/react-snowfall/lib/Snowfall.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/react-snowfall/lib/SnowfallCanvas.js

Lines changed: 15 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/react-snowfall/lib/SnowfallCanvas.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/react-snowfall/lib/Snowflake.d.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ export interface SnowflakeProps {
6464
* The default value is `[1, 1]`.
6565
*/
6666
opacity: [number, number];
67+
/**
68+
* Enable 3D rotation effect (like falling leaves).
69+
*
70+
* When enabled, snowflakes will rotate on X and Y axes in addition to Z axis,
71+
* creating a more realistic 3D tumbling effect.
72+
*
73+
* The default value is `false`.
74+
*/
75+
enable3DRotation?: boolean;
6776
}
6877
export type SnowflakeConfig = Partial<SnowflakeProps>;
6978
export declare const defaultConfig: SnowflakeProps;
@@ -90,6 +99,15 @@ declare class Snowflake {
9099
private updateTargetParams;
91100
update(offsetWidth: number, offsetHeight: number, framesPassed?: number): void;
92101
private getImageOffscreenCanvas;
102+
/**
103+
* Applies 3D rotation transform to the canvas context.
104+
* This method calculates and applies the transformation matrix for 3D rotation effects.
105+
*
106+
* @param ctx The canvas context to apply the transform to
107+
* @param x The x position to translate to
108+
* @param y The y position to translate to
109+
*/
110+
private apply3DTransform;
93111
/**
94112
* Draws a circular snowflake to the canvas.
95113
*
@@ -107,6 +125,15 @@ declare class Snowflake {
107125
* @param ctx The canvas context to draw to
108126
*/
109127
drawCircle(ctx: CanvasRenderingContext2D): void;
128+
/**
129+
* Draws a circular snowflake with 3D rotation effect to the canvas.
130+
*
131+
* This method is used when 3D rotation is enabled and images are not being used.
132+
*
133+
* @param ctx The canvas context to draw to
134+
* @param color The color to fill the circle with
135+
*/
136+
drawCircle3D(ctx: CanvasRenderingContext2D, color: string): void;
110137
/**
111138
* Draws an image-based snowflake to the canvas.
112139
*

0 commit comments

Comments
 (0)