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:
@@ -26,6 +26,12 @@ const HOT_COLOR = "#f97316"; // orange-500
|
||||
const HOT_OPACITY = 0.85;
|
||||
const HEAT_DURATION = 0.15; // ısınma: anlık geri bildirim
|
||||
const COOL_DURATION = 1.4; // soğuma: iz gibi yavaşça söner
|
||||
// Kırpışma: imleç olmadan, rastgele tek piksel ısınıp söner. Yormasın diye
|
||||
// seyrek ve yumuşak — aynı anda ekranda bir-iki sıcak piksel olur.
|
||||
const KIRPISMA_BEKLEME = 1500; // ms; sayfa otursun
|
||||
const KIRPISMA_ARALIK = [500, 1200]; // ms; iki kırpışma arası (rastgele)
|
||||
const KIRPISMA_ISINMA = 0.5; // imleçtekinden yavaş: göz kırpar, çakmaz
|
||||
const KIRPISMA_TUTMA = 900; // ms; ısınma + kısa bekleyiş, sonra soğur
|
||||
|
||||
type HeatTarget = {
|
||||
el: SVGRectElement;
|
||||
@@ -139,18 +145,74 @@ function ayril(inst: HeatInstance) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Rastgele pikselleri seyrek aralıklarla ısıtıp soğutur; durdurucu döner.
|
||||
* Fırçayla aynı `calistir`/`hot` üzerinden çalışır: imlecin altındaki
|
||||
* piksele dokunmaz, fırça da kırpışan pikseli devralabilir. Harita ekran
|
||||
* dışındayken ya da sekme arka plandayken bekler. */
|
||||
function kirpismaBaslat(inst: HeatInstance) {
|
||||
const yanan = new Set<SVGRectElement>();
|
||||
const bekleyen = new Set<number>();
|
||||
let gorunur = true;
|
||||
const io = new IntersectionObserver(([g]) => {
|
||||
gorunur = g.isIntersecting;
|
||||
});
|
||||
io.observe(inst.svg);
|
||||
|
||||
let sayac = 0;
|
||||
const tik = () => {
|
||||
const [enAz, enCok] = KIRPISMA_ARALIK;
|
||||
sayac = window.setTimeout(tik, enAz + Math.random() * (enCok - enAz));
|
||||
if (!gorunur || document.hidden) return;
|
||||
const p = inst.pixels[Math.floor(Math.random() * inst.pixels.length)];
|
||||
if (inst.hot.has(p.el) || yanan.has(p.el)) return;
|
||||
yanan.add(p.el);
|
||||
calistir(
|
||||
inst,
|
||||
p.el,
|
||||
{ fill: HOT_COLOR, fillOpacity: HOT_OPACITY },
|
||||
KIRPISMA_ISINMA,
|
||||
);
|
||||
const s = window.setTimeout(() => {
|
||||
bekleyen.delete(s);
|
||||
yanan.delete(p.el);
|
||||
if (inst.hot.has(p.el)) return;
|
||||
calistir(
|
||||
inst,
|
||||
p.el,
|
||||
{ fill: inst.baseColor, fillOpacity: p.baseOpacity },
|
||||
COOL_DURATION,
|
||||
);
|
||||
}, KIRPISMA_TUTMA);
|
||||
bekleyen.add(s);
|
||||
};
|
||||
sayac = window.setTimeout(tik, KIRPISMA_BEKLEME);
|
||||
|
||||
return () => {
|
||||
window.clearTimeout(sayac);
|
||||
bekleyen.forEach((s) => window.clearTimeout(s));
|
||||
io.disconnect();
|
||||
};
|
||||
}
|
||||
|
||||
export function usePixelHeat(
|
||||
svgRef: RefObject<SVGSVGElement | null>,
|
||||
{
|
||||
/** Fırça yarıçapı, SVG (viewBox) biriminde */
|
||||
radius = 34,
|
||||
}: { radius?: number } = {},
|
||||
/** İmleç olmadan da rastgele pikseller seyrekçe ısınıp sönsün (hero) */
|
||||
kirpisma = false,
|
||||
}: { radius?: number; kirpisma?: boolean } = {},
|
||||
) {
|
||||
useEffect(() => {
|
||||
const svg = svgRef.current;
|
||||
if (!svg) return;
|
||||
// Dokunmatik cihazlarda hover yanlış tetiklenir; efekti imleçli cihazlara sakla
|
||||
if (!window.matchMedia(FINE_POINTER_QUERY).matches) return;
|
||||
// Dokunmatik cihazlarda hover yanlış tetiklenir; fırça imleçli cihazlara
|
||||
// saklanır. Kırpışma imleç istemez ama "hareketi azalt"ta kapalıdır.
|
||||
const imlecli = window.matchMedia(FINE_POINTER_QUERY).matches;
|
||||
const kirp =
|
||||
kirpisma &&
|
||||
!window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
if (!imlecli && !kirp) return;
|
||||
|
||||
if (!svg.viewBox.baseVal.width) return;
|
||||
|
||||
@@ -173,7 +235,11 @@ export function usePixelHeat(
|
||||
hot: new Set(),
|
||||
controls: new Map(),
|
||||
};
|
||||
kaydol(inst);
|
||||
return () => ayril(inst);
|
||||
}, [svgRef, radius]);
|
||||
if (imlecli) kaydol(inst);
|
||||
const kirpismaDur = kirp ? kirpismaBaslat(inst) : null;
|
||||
return () => {
|
||||
kirpismaDur?.();
|
||||
ayril(inst);
|
||||
};
|
||||
}, [svgRef, radius, kirpisma]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user