Piksel harita ve logo animasyonu iyileştirmeleri
All checks were successful
Deploy / deploy (push) Successful in 7m52s
All checks were successful
Deploy / deploy (push) Successful in 7m52s
Şehir/Türkiye piksel haritası görünüme girince oynar; animasyonlu-mark, console-asr, use-pixel-heat ve cta-sira-form güncellendi. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -195,40 +195,61 @@ function PikselSvg({
|
||||
const svgRef = useRef<SVGSVGElement>(null);
|
||||
usePixelHeat(svgRef, { radius: ISI_YARICAPI });
|
||||
|
||||
// Yüklenince gecikmeyle odağa yakınlaş. viewBox her karede yazılır; ısı
|
||||
// fırçası viewBox'ı canlı okuduğu için imleç hep doğru kareyi ısıtır.
|
||||
// Harita görünüme girince (yüklenince değil) gecikmeyle odağa yakınlaş;
|
||||
// il karelerinin sırayla belirmesi de o ana kadar bekler (globals.css:
|
||||
// data-gorundu yokken kt-piksel-belir duraklatılır). Ekranın altında kalan
|
||||
// harita, kullanıcı oraya inmeden animasyonunu harcamasın. viewBox her
|
||||
// karede yazılır; ısı fırçası viewBox'ı canlı okuduğu için imleç hep doğru
|
||||
// kareyi ısıtır.
|
||||
const { sinir, zoom } = harita;
|
||||
const hizaLg = odakHiza?.lg ?? ORTA;
|
||||
const hizaDar = odakHiza?.dar ?? ORTA;
|
||||
useEffect(() => {
|
||||
const svg = svgRef.current;
|
||||
if (!svg || !sinir) return;
|
||||
const rect = svg.getBoundingClientRect();
|
||||
const oran = rect.width && rect.height ? rect.width / rect.height : VIEW_W / VIEW_H;
|
||||
const genis = window.matchMedia("(min-width: 1024px)").matches;
|
||||
const odak = odakKutusu(sinir, oran, zoom, genis ? hizaLg : hizaDar);
|
||||
if (!svg) return;
|
||||
const yaz = (k: Kutu) => svg.setAttribute("viewBox", kutuMetni(k));
|
||||
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
||||
yaz(odak);
|
||||
return () => yaz(TAM_KUTU);
|
||||
}
|
||||
const bas = TAM_KUTU;
|
||||
const kontrol = animate(0, 1, {
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
delay: ODAK_GECIKME,
|
||||
duration: ODAK_SURE,
|
||||
onUpdate: (t) =>
|
||||
yaz([
|
||||
bas[0] + (odak[0] - bas[0]) * t,
|
||||
bas[1] + (odak[1] - bas[1]) * t,
|
||||
bas[2] + (odak[2] - bas[2]) * t,
|
||||
bas[3] + (odak[3] - bas[3]) * t,
|
||||
]),
|
||||
});
|
||||
let kontrol: { stop: () => void } | null = null;
|
||||
const basla = () => {
|
||||
svg.setAttribute("data-gorundu", "");
|
||||
if (!sinir) return;
|
||||
const rect = svg.getBoundingClientRect();
|
||||
const oran = rect.width && rect.height ? rect.width / rect.height : VIEW_W / VIEW_H;
|
||||
const genis = window.matchMedia("(min-width: 1024px)").matches;
|
||||
const odak = odakKutusu(sinir, oran, zoom, genis ? hizaLg : hizaDar);
|
||||
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
||||
yaz(odak);
|
||||
return;
|
||||
}
|
||||
const bas = TAM_KUTU;
|
||||
kontrol = animate(0, 1, {
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
delay: ODAK_GECIKME,
|
||||
duration: ODAK_SURE,
|
||||
onUpdate: (t) =>
|
||||
yaz([
|
||||
bas[0] + (odak[0] - bas[0]) * t,
|
||||
bas[1] + (odak[1] - bas[1]) * t,
|
||||
bas[2] + (odak[2] - bas[2]) * t,
|
||||
bas[3] + (odak[3] - bas[3]) * t,
|
||||
]),
|
||||
});
|
||||
};
|
||||
// Haritanın dörtte biri, ekranın alt %15'lik şeridinin üstüne çıkınca
|
||||
const gozlemci = new IntersectionObserver(
|
||||
(girdiler) => {
|
||||
if (!girdiler.some((g) => g.isIntersecting)) return;
|
||||
gozlemci.disconnect();
|
||||
basla();
|
||||
},
|
||||
{ threshold: 0.25, rootMargin: "0px 0px -15% 0px" },
|
||||
);
|
||||
gozlemci.observe(svg);
|
||||
return () => {
|
||||
kontrol.stop();
|
||||
yaz(TAM_KUTU);
|
||||
gozlemci.disconnect();
|
||||
kontrol?.stop();
|
||||
svg.removeAttribute("data-gorundu");
|
||||
if (sinir) yaz(TAM_KUTU);
|
||||
};
|
||||
}, [sinir, zoom, hizaLg, hizaDar]);
|
||||
|
||||
@@ -237,7 +258,7 @@ function PikselSvg({
|
||||
ref={svgRef}
|
||||
viewBox={`0 0 ${VIEW_W} ${VIEW_H}`}
|
||||
preserveAspectRatio={doldur ? "xMidYMid slice" : "xMidYMid meet"}
|
||||
className={cn(doldur ? "h-full w-full" : "h-auto w-full", "text-primary", className)}
|
||||
className={cn(doldur ? "h-full w-full" : "h-auto w-full", "kt-piksel-harita text-primary", className)}
|
||||
role="img"
|
||||
aria-label={etiket}
|
||||
// Statik, deterministik markup — her render'da yeniden kurulmaz
|
||||
|
||||
Reference in New Issue
Block a user