-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: added snow #71
feat: added snow #71
Changes from 7 commits
b815eea
5fe9619
0f7d9b1
d70ec86
b3d759a
9ad38e4
bb58911
3774809
1ff1174
3149ae6
84140e7
6841e72
5789494
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
import './styles/snowflakes.css'; | ||
import './styles/snowflakesMedia.css'; | ||
import { Snowflake } from './models/Snowflake'; | ||
|
||
import Switch from '@material-ui/core/Switch'; | ||
import { makeStyles } from '@material-ui/core/styles'; | ||
|
||
export function Snowflakes() { | ||
|
||
const [isSnowing, setSnowing] = useState<boolean>(true); | ||
const requestId = React.useRef(0); | ||
|
||
useEffect(() => { | ||
startSnowflakes(); | ||
}); | ||
|
||
const getCanvasElementById = (id: string): HTMLCanvasElement => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. useCallback hook for function creation |
||
const canvas = document.getElementById(id); | ||
|
||
if (!(canvas instanceof HTMLCanvasElement)) { | ||
throw new Error(`The element of id "${id}" is not a HTMLCanvasElement. Make sure a <canvas id="${id}""> element is present in the document.`); | ||
} | ||
|
||
return canvas; | ||
}; | ||
|
||
const getCanvasRenderingContext2D = (canvas: HTMLCanvasElement): CanvasRenderingContext2D => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. useCallback hook for function creation |
||
const context = canvas.getContext('2d'); | ||
|
||
if (!(context instanceof CanvasRenderingContext2D)) { | ||
throw new Error('This browser does not support 2-dimensional canvas rendering contexts.'); | ||
} | ||
|
||
return context; | ||
}; | ||
|
||
function startSnowflakes() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. useCallback hook for function creation |
||
|
||
const canvas: HTMLCanvasElement = getCanvasElementById('snow'); | ||
const ctx: CanvasRenderingContext2D = getCanvasRenderingContext2D(canvas); | ||
|
||
if (!isSnowing) { | ||
window.cancelAnimationFrame(requestId.current); | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
return; | ||
} | ||
|
||
const flakesAmoung = getFlakesAmoungByScreenWidth(window.innerWidth); | ||
const flakes: Snowflake[] = createSnowflakes(flakesAmoung); | ||
|
||
window.addEventListener("resize", function () { | ||
canvas.width = window.innerWidth; | ||
canvas.height = window.innerHeight; | ||
}); | ||
|
||
snowStep(); | ||
|
||
function getFlakesAmoungByScreenWidth(width: number) { | ||
if (width < 500) { | ||
return (60); | ||
} else if (width < 750) { | ||
return (80); | ||
} else if (width < 1000) { | ||
return (100); | ||
} else if (width < 1200) { | ||
return (120); | ||
} else if (width < 1600) { | ||
return (160); | ||
} else { | ||
return (180); | ||
} | ||
} | ||
|
||
function snowStep() { | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
for (let i = 0; i < flakes.length; i++) { | ||
const flake: Snowflake = flakes[i]; | ||
|
||
flake.speedX *= .98; | ||
flake.speedX += Math.cos(flake.step += .05) * flake.stepSize; | ||
|
||
flake.y += flake.speedY; | ||
flake.x += flake.speedX; | ||
|
||
if (flake.y >= canvas.height || flake.y <= 0) { | ||
reset(flake); | ||
} | ||
|
||
if (flake.x >= canvas.width || flake.x <= 0) { | ||
reset(flake); | ||
} | ||
|
||
ctx.beginPath(); | ||
ctx.fillStyle = "rgba(255,255,255," + flake.opacity + ")"; | ||
ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2); | ||
ctx.fill(); | ||
} | ||
requestId.current = requestAnimationFrame(snowStep); | ||
}; | ||
|
||
function reset(flake: Snowflake) { | ||
flake.x = Math.floor(Math.random() * canvas.width); | ||
flake.y = 0; | ||
flake.size = (Math.random() * 3) + 2; | ||
flake.speedY = (Math.random() * 1) + 0.5; | ||
flake.speedX = 0; | ||
flake.opacity = (Math.random() * 0.5) + 0.3; | ||
} | ||
|
||
function createSnowflakes(flakeCount: number): Snowflake[] { | ||
const flakes: Snowflake[] = []; | ||
for (let i = 0; i < flakeCount; i++) { | ||
const x = Math.floor(Math.random() * canvas.width), | ||
y = Math.floor(Math.random() * canvas.height), | ||
size = (Math.random() * 3) + 2, | ||
speedY = (Math.random() * 1) + 0.5, | ||
opacity = (Math.random() * 0.5) + 0.3; | ||
|
||
flakes.push({ | ||
speedY: speedY, | ||
speedX: 0, | ||
x: x, | ||
y: y, | ||
size: size, | ||
stepSize: (Math.random()) / 30, | ||
step: 0, | ||
opacity: opacity, | ||
}); | ||
} | ||
return flakes; | ||
}; | ||
} | ||
|
||
const MAIN_YELLOW = '#F2E14C'; | ||
|
||
const useStyles = makeStyles({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please create useStyles variable outside component, otherwise this variable will be create on each component Render |
||
colorSecondary: { | ||
'&$checked': { | ||
color: MAIN_YELLOW, | ||
}, | ||
}, | ||
switchBase: { | ||
color: 'white', | ||
'&$checked': { | ||
color: 'white', | ||
'& + $track': { | ||
backgroundColor: MAIN_YELLOW, | ||
opacity: 1, | ||
}, | ||
"&:hover": { | ||
backgroundColor: '#f2e14c4d', | ||
}, | ||
}, | ||
}, | ||
track: {}, | ||
checked: {}, | ||
}); | ||
|
||
const classes = useStyles(); | ||
|
||
return ( | ||
<> | ||
<div className='snow-switcher'> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please use styles that you created by makeStyles, the same for all className |
||
<span className='snow-switcher__label'>Happy New Year</span> | ||
<Switch | ||
classes={classes} | ||
size='small' | ||
checked={isSnowing} | ||
value={isSnowing} | ||
onClick={() => setSnowing(!isSnowing)}> | ||
</Switch> | ||
</div> | ||
<canvas id="snow" width={window.innerWidth} height={window.innerHeight}></canvas> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export interface Snowflake { | ||
speedY: number, | ||
speedX: number, | ||
x: number, | ||
y: number, | ||
size: number, | ||
stepSize: number, | ||
step: number, | ||
opacity: number | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#snow { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please relocate styles to makeStyles function |
||
position: fixed; | ||
height: 100%; | ||
width: 100%; | ||
z-index: 1; | ||
pointer-events: none; | ||
} | ||
|
||
.snow-switcher { | ||
display: flex; | ||
position: absolute; | ||
z-index: 1101; | ||
color: white; | ||
} | ||
|
||
.snow-switcher__label { | ||
font-size: 0.9rem;; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
@media screen and (min-width: 960px) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can add media by css-in-js, please relocate it inside makeStyles function, |
||
.snow-switcher { | ||
top: 29px; | ||
left: 38px; | ||
} | ||
} | ||
|
||
@media screen and (max-width: 959px) { | ||
.snow-switcher { | ||
top: 18px; | ||
left: 24px; | ||
} | ||
} | ||
|
||
@media screen and (max-width: 600px) { | ||
.snow-switcher { | ||
top: 0px; | ||
left: -4px; | ||
flex-direction: row-reverse; | ||
} | ||
} | ||
|
||
@media screen and (max-width: 600px) and (orientation: landscape) { | ||
.snow-switcher { | ||
top: -2px; | ||
} | ||
|
||
.snow-switcher__label { | ||
font-size: 0.9rem; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can create useSnowflakes hook and incapsulate all logic inside