entrada suave no video, loader com logo e login vazio
This commit is contained in:
parent
d0f3ba8655
commit
6cc1a2bc00
@ -88,34 +88,24 @@ h3,
|
||||
z-index: 50;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
background: #000;
|
||||
color: #e8f4e5;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.orbit-loader-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 999px;
|
||||
background: #82c85c;
|
||||
animation: loader-pulse 1s ease-in-out infinite;
|
||||
.orbit-loader-logo {
|
||||
width: min(11.5rem, 58vw);
|
||||
height: auto;
|
||||
animation: loader-glow 1.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes loader-pulse {
|
||||
@keyframes loader-glow {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.35;
|
||||
transform: scale(1);
|
||||
opacity: 0.4;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(1.35);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,10 @@ type ScrollFilmProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
function easeInOutCubic(value: number) {
|
||||
return value < 0.5 ? 4 * value * value * value : 1 - (-2 * value + 2) ** 3 / 2;
|
||||
}
|
||||
|
||||
export function ScrollFilm({ src, poster, children }: ScrollFilmProps) {
|
||||
const orbitRef = useRef<HTMLDivElement>(null);
|
||||
const filmRef = useRef<HTMLVideoElement>(null);
|
||||
@ -30,6 +34,9 @@ export function ScrollFilm({ src, poster, children }: ScrollFilmProps) {
|
||||
let current = 0;
|
||||
let frame = 0;
|
||||
let blobUrl: string | null = null;
|
||||
let introStartedAt = 0;
|
||||
let introDone = false;
|
||||
const introMs = 2400;
|
||||
|
||||
const markReady = () => {
|
||||
if (ready) {
|
||||
@ -39,6 +46,9 @@ export function ScrollFilm({ src, poster, children }: ScrollFilmProps) {
|
||||
film.pause();
|
||||
film.classList.add("is-ready");
|
||||
setLoading(false);
|
||||
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
introDone = reduce;
|
||||
introStartedAt = reduce ? 0 : performance.now();
|
||||
};
|
||||
|
||||
fetch(src)
|
||||
@ -59,13 +69,33 @@ export function ScrollFilm({ src, poster, children }: ScrollFilmProps) {
|
||||
return y / total;
|
||||
};
|
||||
|
||||
const tick = () => {
|
||||
const introSeconds = (now: number, duration: number) => {
|
||||
if (introDone || !introStartedAt) {
|
||||
return null;
|
||||
}
|
||||
if (progressFromScroll() > 0.02) {
|
||||
introDone = true;
|
||||
return null;
|
||||
}
|
||||
const elapsed = now - introStartedAt;
|
||||
const t = Math.min(elapsed / introMs, 1);
|
||||
const peak = Math.min(2, Math.max(duration * 0.22, 0.6));
|
||||
const trip = t < 0.5 ? easeInOutCubic(t * 2) : 1 - easeInOutCubic((t - 0.5) * 2);
|
||||
if (t >= 1) {
|
||||
introDone = true;
|
||||
return 0;
|
||||
}
|
||||
return trip * peak;
|
||||
};
|
||||
|
||||
const tick = (now: number) => {
|
||||
const target = progressFromScroll();
|
||||
current += (target - current) * 0.42;
|
||||
orbit.style.setProperty("--scrub", current.toFixed(4));
|
||||
|
||||
if (ready && film.duration && !film.seeking) {
|
||||
const time = current * (film.duration - 0.04);
|
||||
const intro = introSeconds(now, film.duration);
|
||||
const time = intro ?? current * (film.duration - 0.04);
|
||||
if (Math.abs(film.currentTime - time) >= 0.02) {
|
||||
film.currentTime = time;
|
||||
}
|
||||
@ -104,9 +134,8 @@ export function ScrollFilm({ src, poster, children }: ScrollFilmProps) {
|
||||
</div>
|
||||
<div className="orbit-story">{children}</div>
|
||||
{loading ? (
|
||||
<div className="orbit-loader" role="status" aria-live="polite">
|
||||
<span className="orbit-loader-dot" />
|
||||
<p>Carregando Sinka</p>
|
||||
<div className="orbit-loader" role="status" aria-live="polite" aria-label="Sinka">
|
||||
<img src="/brand/sinka-logo.webp" alt="Sinka" className="orbit-loader-logo" />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@ -19,10 +19,8 @@ export function LoginForm({
|
||||
google_unlinked: "Este e-mail Google não tem acesso à administração.",
|
||||
google_denied: "Não foi possível entrar com o Google.",
|
||||
}[search.get("error") ?? ""];
|
||||
const [email, setEmail] = useState(
|
||||
variant === "admin" ? "tina.r@example.net" : "xena.w@example.org",
|
||||
);
|
||||
const [password, setPassword] = useState(variant === "admin" ? "SinkaPlatform!1" : "SinkaAdmin!1");
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user