1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36:40 +07:00
vault-frontend/src/components/auth/login/LoginScene/index.tsx
2022-08-01 22:27:33 +07:00

145 lines
3.2 KiB
TypeScript

import React, {
FC,
memo,
useCallback,
useEffect,
useRef,
useState,
} from "react";
import { useWindowSize } from "~/hooks/dom/useWindowSize";
import styles from "./styles.module.scss";
interface 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 containerRef = useRef<HTMLDivElement>(null);
const [loaded, setLoaded] = useState(false);
const imageRefs = useRef<Array<SVGImageElement | null>>([]);
const { isMobile } = useWindowSize();
const onMouseMove = useCallback(
(event: MouseEvent): any => {
if (!containerRef.current) {
return;
}
const { x, width } = containerRef.current.getBoundingClientRect();
const middle = (width - x) / 2;
const shift = event.pageX / middle / 2 - 0.5;
layers.forEach((it, index) => {
const target = imageRefs.current[index];
if (target) {
target.style.transform = `translate(${shift *
it.velocity *
200}px, 0)`;
}
});
},
[containerRef],
);
useEffect(() => {
document.addEventListener("mousemove", onMouseMove);
return () => document.removeEventListener("mousemove", onMouseMove);
}, []);
if (isMobile) {
return null;
}
return (
<div className={styles.scene} ref={containerRef}>
<svg
width="100%"
height="100%"
viewBox="0 0 1920 1080"
preserveAspectRatio="xMidYMid slice"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<linearGradient id="fallbackGradient" x1={0} x2={0} y1={1} y2={0}>
<stop style={{ stopColor: "#ffccaa", stopOpacity: 1 }} offset="0" />
<stop
style={{ stopColor: "#fff6d5", stopOpacity: 1 }}
offset="0.34655526"
/>
<stop
style={{ stopColor: "#afc6e9", stopOpacity: 1 }}
offset="0.765342"
/>
<stop style={{ stopColor: "#879fde", stopOpacity: 1 }} offset="1" />
</linearGradient>
</defs>
<rect
width={1920}
height={1080}
x={0}
y={0}
fill="url(#fallbackGradient)"
/>
{layers.map((it, index) => (
<image
ref={it => imageRefs.current.push(it)}
key={it.src}
href={it.src}
width={it.width}
height={it.height}
x={1920 / 2 - it.width / 2}
y={0}
opacity={loaded ? 1 : 0}
onLoad={() => setLoaded(true)}
className={styles.image}
/>
))}
</svg>
</div>
);
});
export { LoginScene };