fix(navegacao): foco em âncora de outra página, vitrine acessível e 3D mais leve
Foco cai no destino ao chegar de outra página; âncoras ignoram ?tipo=; movimento reduzido salta em todos os cliques; cronômetro da janela ampliada; degradê no topo de Projetos e legendas do mergulho com intervalos testados; vitrine acima da barra de cookies e com 2 paradas por projeto; reel-list.css no global; 3D montado em tarefas curtas, limitado a ~30 qps e estático com WebGL por software; pôsteres da vitrine de 330 para 158 KB; SC Plus regravado; scripts sem funções acima de complexidade 10.
This commit is contained in:
1 parent
9e2d65a926
commit
204ebd5fa5
49 files changed
+2197
-606
No files matched your search
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import {
|
||||
type CSSProperties,
|
||||
type RefObject,
|
||||
@@ -47,6 +48,16 @@ const headerHeight = () => {
|
||||
return headerCache.height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Larguras (CSS) em que os pôsteres aparecem, para o next/image pedir o arquivo do tamanho certo (um WebP/AVIF de
|
||||
* ~1080 px no notebook e de ~256 px no celular) e não o original de 1440 px: o notebook mede ~58vw (até ~1100 px nas
|
||||
* telas largas; 90vw abaixo de 1024 px, com a vitrine em coluna) e o celular da moldura, 22% dele.
|
||||
*/
|
||||
const LAPTOP_POSTER_SIZES =
|
||||
"(min-width: 1900px) 1100px, (min-width: 1024px) 58vw, 90vw";
|
||||
const PHONE_POSTER_SIZES =
|
||||
"(min-width: 1900px) 240px, (min-width: 1024px) 13vw, 20vw";
|
||||
|
||||
/** Põe o vídeo no instante `fraction` (0 a 1) sem repetir buscas enquanto a anterior ainda não terminou. */
|
||||
function seekVideo(video: HTMLVideoElement | null, fraction: number) {
|
||||
if (!video || video.readyState < 1 || !video.duration) return;
|
||||
@@ -519,16 +530,22 @@ function ReelLayer({
|
||||
inert={!isActive}
|
||||
>
|
||||
<BrowserFrame url={displayUrl(project)} className="ds-reel-laptop">
|
||||
<div
|
||||
className="ds-reel-screen"
|
||||
style={
|
||||
poster ? { backgroundImage: `url(${desktop.poster})` } : undefined
|
||||
}
|
||||
>
|
||||
<div className="ds-reel-screen">
|
||||
{/* o pôster é a imagem de baixo (uma só, otimizada): o vídeo, por cima, cobre-a ao carregar */}
|
||||
{poster && (
|
||||
<Image
|
||||
src={desktop.poster}
|
||||
alt=""
|
||||
width={desktop.width}
|
||||
height={desktop.height}
|
||||
sizes={LAPTOP_POSTER_SIZES}
|
||||
loading="eager"
|
||||
fetchPriority="low"
|
||||
/>
|
||||
)}
|
||||
<video
|
||||
ref={videoRef}
|
||||
src={attached ? getScrubSource(config.id) : undefined}
|
||||
poster={poster ? desktop.poster : undefined}
|
||||
muted
|
||||
playsInline
|
||||
preload="metadata"
|
||||
@@ -541,10 +558,19 @@ function ReelLayer({
|
||||
/>
|
||||
</div>
|
||||
</BrowserFrame>
|
||||
<PhoneFrame
|
||||
className="ds-reel-phone"
|
||||
poster={poster ? phone.poster : undefined}
|
||||
/>
|
||||
<PhoneFrame className="ds-reel-phone">
|
||||
{poster && (
|
||||
<Image
|
||||
src={phone.poster}
|
||||
alt=""
|
||||
width={phone.width}
|
||||
height={phone.height}
|
||||
sizes={PHONE_POSTER_SIZES}
|
||||
loading="eager"
|
||||
fetchPriority="low"
|
||||
/>
|
||||
)}
|
||||
</PhoneFrame>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -615,7 +641,11 @@ function ReelCaption({
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
<ProjectActions item={item} onExpand={() => onExpand(config.id)} />
|
||||
<ProjectActions
|
||||
item={item}
|
||||
onExpand={() => onExpand(config.id)}
|
||||
grouped
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user