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:
1 parent
8d07b8c6bb
commit
c9a0b80656
48 files changed
+7210
-1241
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { render } from "@testing-library/react";
|
||||
import { act, render } from "@testing-library/react";
|
||||
import FilmGrain from "./FilmGrain";
|
||||
|
||||
describe("static cinematic effects", () => {
|
||||
@@ -11,3 +11,66 @@ describe("static cinematic effects", () => {
|
||||
expect(grain.container.querySelector("canvas")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("film grain over the project screens", () => {
|
||||
let screenTop = 5000;
|
||||
|
||||
function addScreen(className: string) {
|
||||
const element = document.createElement("div");
|
||||
element.className = className;
|
||||
element.getBoundingClientRect = () =>
|
||||
({ top: screenTop, bottom: screenTop + 600, height: 600 }) as DOMRect;
|
||||
document.body.append(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
function scroll(to: number) {
|
||||
screenTop = to;
|
||||
act(() => {
|
||||
window.dispatchEvent(new Event("scroll"));
|
||||
jest.advanceTimersByTime(40);
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
screenTop = 5000;
|
||||
Object.defineProperty(window, "innerHeight", {
|
||||
configurable: true,
|
||||
value: 800,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
|
||||
it("steps aside while a project screen is in view and comes back when it leaves", () => {
|
||||
addScreen("ds-reel");
|
||||
const { container } = render(<FilmGrain />);
|
||||
const grain = container.firstElementChild as HTMLElement;
|
||||
expect(grain).not.toHaveAttribute("data-over-projects");
|
||||
|
||||
scroll(300); // a vitrine entrou na janela
|
||||
expect(grain).toHaveAttribute("data-over-projects");
|
||||
|
||||
scroll(-900); // passou: a cena acabou 300 px acima do topo
|
||||
expect(grain).not.toHaveAttribute("data-over-projects");
|
||||
});
|
||||
|
||||
it("also covers the browser and phone frames", () => {
|
||||
addScreen("ds-bframe");
|
||||
const { container } = render(<FilmGrain />);
|
||||
scroll(100);
|
||||
expect(container.firstElementChild).toHaveAttribute("data-over-projects");
|
||||
});
|
||||
|
||||
it("stays on when there is no project screen on the page", () => {
|
||||
const { container } = render(<FilmGrain />);
|
||||
scroll(100);
|
||||
expect(container.firstElementChild).not.toHaveAttribute(
|
||||
"data-over-projects",
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user