perf(movimento): uma transição, 3D leve e vídeo certo por aparelho

Passagens com fade e 32 px, cena anterior termina em opacidade 0, sem visibility nem clip-path. 3D do hero como fundo ambiente, sob demanda e desligado em toque, aparelho fraco, saveData e movimento reduzido. Lenis fora do toque e salto direto em âncoras distantes. Vitrine só de clientes, até 3 capítulos, fixa só no desktop e carrossel no celular; vídeo só do projeto em cena com preload metadata. Rótulos mono a partir de 12 px e limão só no contato.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 03:32:23 -03:00
1 parent 8d07b8c6bb
commit c9a0b80656
48 files changed
+7210 -1241

No files matched your search

+20 -2
View File
@@ -1,8 +1,9 @@
"use client";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { useEffect, useMemo, useRef } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import * as THREE from "three";
import FramePulse from "./FramePulse";
function GridFloor() {
const meshRef = useRef<THREE.Mesh>(null);
@@ -95,20 +96,36 @@ function CameraRig() {
return null;
}
/** Fundo ambiente das páginas internas: desenha sob demanda, a 30 quadros por segundo e só à vista. */
export default function HeroScene({
isVisible = true,
}: {
isVisible?: boolean;
}) {
const rootRef = useRef<HTMLDivElement>(null);
const [inView, setInView] = useState(true);
// fora da tela não desenha nada
useEffect(() => {
const element = rootRef.current;
if (!element) return;
const observer = new IntersectionObserver(([entry]) =>
setInView(entry.isIntersecting),
);
observer.observe(element);
return () => observer.disconnect();
}, []);
return (
<div
ref={rootRef}
className="absolute inset-0 z-0"
style={{ position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }}
>
<Canvas
camera={{ position: [0, 0.5, 8], fov: 60, near: 0.1, far: 100 }}
dpr={[1, 1.5]}
frameloop={isVisible ? "always" : "never"}
frameloop="demand"
gl={{
antialias: false,
alpha: true,
@@ -133,6 +150,7 @@ export default function HeroScene({
/>
<pointLight position={[-5, 3, -5]} intensity={0.2} color="#ffffff" />
<FramePulse active={isVisible && inView} />
<CameraRig />
<GridFloor />
</Canvas>