added motion to login scene
BIN
public/.DS_Store
vendored
Normal file
Before Width: | Height: | Size: 265 KiB After Width: | Height: | Size: 258 KiB |
1255
public/images/clouds__bg.svg
Normal file
After Width: | Height: | Size: 45 KiB |
1902
public/images/clouds__cloud.svg
Normal file
After Width: | Height: | Size: 131 KiB |
1337
public/images/clouds__cube.svg
Normal file
After Width: | Height: | Size: 48 KiB |
2074
public/images/clouds__dudes.svg
Normal file
After Width: | Height: | Size: 92 KiB |
3652
public/images/clouds__trash.svg
Normal file
After Width: | Height: | Size: 202 KiB |
|
@ -1,14 +1,87 @@
|
||||||
import React, { FC, useState } from "react";
|
import React, {
|
||||||
|
FC,
|
||||||
|
memo,
|
||||||
|
MouseEventHandler,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
import styles from "./styles.module.scss";
|
import styles from "./styles.module.scss";
|
||||||
|
|
||||||
interface LoginSceneProps {}
|
interface LoginSceneProps {}
|
||||||
|
|
||||||
const LoginScene: FC<LoginSceneProps> = () => {
|
interface Layer {
|
||||||
|
src: string;
|
||||||
|
velocity: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const layers: Layer[] = [
|
||||||
|
{
|
||||||
|
src: "/images/clouds__bg.svg",
|
||||||
|
velocity: -0.3,
|
||||||
|
width: 3840,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/images/clouds__cube.svg",
|
||||||
|
velocity: -0.1,
|
||||||
|
width: 3840,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/images/clouds__cloud.svg",
|
||||||
|
velocity: 0.2,
|
||||||
|
width: 3840,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/images/clouds__dudes.svg",
|
||||||
|
velocity: 0.5,
|
||||||
|
width: 3840,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/images/clouds__trash.svg",
|
||||||
|
velocity: 0.8,
|
||||||
|
width: 3840,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const LoginScene: FC<LoginSceneProps> = memo(() => {
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
|
|
||||||
|
const onMouseMove = useCallback(
|
||||||
|
(event: MouseEvent): any => {
|
||||||
|
if (!ref.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { x, width } = ref.current.getBoundingClientRect();
|
||||||
|
const middle = (width - x) / 2;
|
||||||
|
const shift = event.pageX / middle / 2 - 0.5;
|
||||||
|
|
||||||
|
layers.map((it, index) => {
|
||||||
|
document.getElementById(
|
||||||
|
`LoginScene__${index}`,
|
||||||
|
)?.style.transform = `translate(${shift * it.velocity * 200}px, 0)`;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[ref],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.addEventListener("mousemove", onMouseMove);
|
||||||
|
return () => document.removeEventListener("mousemove", onMouseMove);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.scene}>
|
<div className={styles.scene} ref={ref}>
|
||||||
<svg
|
<svg
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
|
@ -39,19 +112,23 @@ const LoginScene: FC<LoginSceneProps> = () => {
|
||||||
fill="url(#fallbackGradient)"
|
fill="url(#fallbackGradient)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{layers.map((it, index) => (
|
||||||
<image
|
<image
|
||||||
href="/images/clouds.svg"
|
id={`LoginScene__${index}`}
|
||||||
width={1920}
|
key={it.src}
|
||||||
height={1080}
|
href={it.src}
|
||||||
x={0}
|
width={it.width}
|
||||||
|
height={it.height}
|
||||||
|
x={1920 / 2 - it.width / 2}
|
||||||
y={0}
|
y={0}
|
||||||
opacity={loaded ? 1 : 0}
|
opacity={loaded ? 1 : 0}
|
||||||
onLoad={() => setLoaded(true)}
|
onLoad={() => setLoaded(true)}
|
||||||
className={styles.image}
|
className={styles.image}
|
||||||
/>
|
/>
|
||||||
|
))}
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export { LoginScene };
|
export { LoginScene };
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
transition: opacity 1s;
|
transition: opacity 1s;
|
||||||
|
will-change: opacity, transform;
|
||||||
|
|
||||||
@include tablet {
|
@include tablet {
|
||||||
display: none;
|
display: none;
|
||||||
|
|