Skip to content
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

Merged
merged 13 commits into from
Dec 23, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/js-machine-front/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { memo, useMemo } from 'react';
import React, { useMemo } from 'react';

import './firebase.conf';
import { theme } from './theme';
Expand All @@ -13,6 +13,7 @@ import { Authorization } from './scenes/authorization/Authorization';
import { Route, Redirect, Switch, Router } from 'react-router';
import { ThemeProvider } from '@material-ui/styles';
import { SnackbarProvider } from 'notistack';
import { Snowflakes } from './components/Snowflakes';

// Internationalization
import { intl } from './i18n/messages';
Expand All @@ -36,6 +37,7 @@ export const App: React.FC = observer(() => {
<ThemeProvider theme={theme}>
<RawIntlProvider value={intl}>
<Router history={history}>
<Snowflakes/>
<SnackbarProvider maxSnack={3}>
<DynamicNavBar />
<ErrorBoundary>
Expand Down
178 changes: 178 additions & 0 deletions apps/js-machine-front/src/app/components/Snowflakes.tsx
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();
Copy link
Collaborator

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

});

const getCanvasElementById = (id: string): HTMLCanvasElement => {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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 => {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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() {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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({
Copy link
Collaborator

Choose a reason for hiding this comment

The 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'>
Copy link
Collaborator

Choose a reason for hiding this comment

The 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>
</>
);
}
10 changes: 10 additions & 0 deletions apps/js-machine-front/src/app/components/models/Snowflake.tsx
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
}
18 changes: 18 additions & 0 deletions apps/js-machine-front/src/app/components/styles/snowflakes.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#snow {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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,
if you need an example, you can find code with 'theme.breakpoints.'

.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;
}
}
Loading