Skip to content

Commit 62a16dd

Browse files
committed
feat: add wrapping in translate calculations
this avoids clustering of snowflakes on the side/top of the screen after the window loses focus/is minimized for a while.
1 parent 0be5345 commit 62a16dd

File tree

8 files changed

+77
-51
lines changed

8 files changed

+77
-51
lines changed

lib/Snowfall.js

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

lib/Snowflake.d.ts

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

lib/Snowflake.js

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

lib/utils.d.ts

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

lib/utils.js

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

src/Snowfall.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export default class Snowfall extends React.Component<Props, State> {
7777
const ctx = canvas.getContext('2d')
7878
if (ctx) {
7979
ctx.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight)
80-
this.snowflakes.forEach(snowflake => snowflake.draw(canvas))
80+
this.snowflakes.forEach(snowflake => snowflake.draw(canvas, ctx))
8181
}
8282
}
8383
}

src/Snowflake.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ class Snowflake {
7070

7171
resized = () => (this.params.isResized = true)
7272

73-
draw = (canvas: HTMLCanvasElement) => {
74-
const ctx = canvas.getContext('2d')
73+
draw = (canvas: HTMLCanvasElement, inputCtx?: CanvasRenderingContext2D) => {
74+
const ctx = inputCtx || canvas.getContext('2d')
7575
if (ctx) {
7676
ctx.beginPath()
7777
ctx.arc(this.params.x, this.params.y, this.params.radius, 0, 2 * Math.PI)
@@ -81,12 +81,16 @@ class Snowflake {
8181
}
8282
}
8383

84-
translate = (framesPassed: number = 1) => {
85-
this.params.y += this.params.speed * framesPassed
86-
this.params.x += this.params.wind * framesPassed
84+
translate = (canvas: HTMLCanvasElement, framesPassed: number = 1) => {
85+
const { x, y, wind, speed, nextWind, nextSpeed } = this.params
8786

88-
this.params.speed = lerp(this.params.speed, this.params.nextSpeed, 0.01)
89-
this.params.wind = lerp(this.params.wind, this.params.nextWind, 0.01)
87+
// Update current location, wrapping around if going off the canvas
88+
this.params.x = (x + wind * framesPassed) % canvas.offsetWidth
89+
this.params.y = (y + speed * framesPassed) % canvas.offsetHeight
90+
91+
// Update the wind and speed towards the desired values
92+
this.params.speed = lerp(speed, nextSpeed, 0.01)
93+
this.params.wind = lerp(wind, nextWind, 0.01)
9094

9195
if (this.framesSinceLastUpdate++ > this.config.changeFrequency) {
9296
this.updateTargetParams()
@@ -99,19 +103,8 @@ class Snowflake {
99103
this.params.nextWind = random(...this.config.wind)
100104
}
101105

102-
handleOffScreen = (canvas: HTMLCanvasElement) => {
103-
if (this.params.x > canvas.offsetWidth) {
104-
this.params.x = 0
105-
}
106-
107-
if (this.params.y > canvas.offsetHeight) {
108-
this.params.y = 0
109-
}
110-
}
111-
112106
update = (canvas: HTMLCanvasElement, framesPassed?: number) => {
113-
this.translate(framesPassed)
114-
this.handleOffScreen(canvas)
107+
this.translate(canvas, framesPassed)
115108
}
116109
}
117110

src/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Enhanced random function, selects a random value between a minimum and maximum. If the values provided are both
3+
* integers then the number returned will be an integer, otherwise the return number will be a decimal.
4+
* @param min The minimum value
5+
* @param max The maximum value
6+
*/
17
export function random(min: number, max: number): number {
28
const randomNumber = Math.random() * (max - min + 1) + min
39

@@ -8,6 +14,12 @@ export function random(min: number, max: number): number {
814
}
915
}
1016

17+
/**
18+
* Linear interpolation function to gradually step towards a target value
19+
* @param start The current value
20+
* @param end The target value
21+
* @param normal The rate of change between 0 and 1 (0 = no change, 1 = instant)
22+
*/
1123
export function lerp(start: number, end: number, normal: number) {
1224
return (1 - normal) * start + normal * end
1325
}

0 commit comments

Comments
 (0)