perf: deterministik dekor memo'ları ve küçük render süpürmeleri (Faz 7)
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
- pixel-decor: PixelField/PixelDivider piksel üretimi useMemo([seed]) — 504 iterasyon + ~150 element çekmece reorder'ının her karesinde yeniden üretiliyordu - rapor-listesi: acikSira effect'i önceki-prop desenine döndü (çift render ve eslint-disable kalktı), Set lazy init, tekIl useMemo - program-tablosu: 3 dilimin spread'i useMemo - typing-animation: displayedText state yerine türetme; kaynak reset'i render sırasında — tick başına state yazımı ve effect bağımlılığı azaldı - site-top-banner: saniyelik geri sayım tiki startTransition'da - program-liste-verileri: sparkline 6 dizi geçişi tek döngüde - secimlerim-paneli: SecimSatiri profili prop'tan alır + memo (24 ayrı store aboneliği kalktı) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useRef, type ReactNode } from "react";
|
||||
import { useMemo, useRef, type ReactNode } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { usePixelHeat } from "@/components/use-pixel-heat";
|
||||
|
||||
@@ -88,35 +88,41 @@ export function PixelField({
|
||||
|
||||
const COLS = 42;
|
||||
const ROWS = 12;
|
||||
const cx = (COLS - 1) / 2;
|
||||
const cy = (ROWS - 1) / 2;
|
||||
const maxD = Math.sqrt(cx * cx + cy * cy);
|
||||
|
||||
const pixels: ReactNode[] = [];
|
||||
let accentIdx = 0;
|
||||
// Çıktı seed'e göre deterministik; 504 iterasyon + ~150 element üretimini
|
||||
// her render'da (ör. çekmece reorder'ında) tekrarlama (rendering-hoist-jsx)
|
||||
const pixels = useMemo(() => {
|
||||
const cx = (COLS - 1) / 2;
|
||||
const cy = (ROWS - 1) / 2;
|
||||
const maxD = Math.sqrt(cx * cx + cy * cy);
|
||||
|
||||
// Hero serpintisiyle aynı kural: içeriğin oturduğu orta kolon
|
||||
// (genişliğin %22–78 bandı) tüm yükseklik boyunca tamamen boş kalır
|
||||
const BAND_MIN = COLS * 0.22;
|
||||
const BAND_MAX = COLS * 0.78;
|
||||
const sonuc: ReactNode[] = [];
|
||||
let accentIdx = 0;
|
||||
|
||||
for (let y = 0; y < ROWS; y++) {
|
||||
for (let x = 0; x < COLS; x++) {
|
||||
if (x > BAND_MIN && x < BAND_MAX) continue;
|
||||
// Kenarlara doğru artan doluluk
|
||||
const d = Math.sqrt((x - cx) ** 2 + (y - cy) ** 2) / maxD;
|
||||
const density = 0.1 + 0.42 * d * d;
|
||||
if (hash(x, y, seed) > density) continue;
|
||||
const accent = hash(x, y, seed + 99) > 0.96;
|
||||
pixels.push(
|
||||
pixelRect(x, y, {
|
||||
key: `${x}-${y}`,
|
||||
accent,
|
||||
accentDelay: accent ? (accentIdx++ % 8) * 0.45 : 0,
|
||||
}),
|
||||
);
|
||||
// Hero serpintisiyle aynı kural: içeriğin oturduğu orta kolon
|
||||
// (genişliğin %22–78 bandı) tüm yükseklik boyunca tamamen boş kalır
|
||||
const BAND_MIN = COLS * 0.22;
|
||||
const BAND_MAX = COLS * 0.78;
|
||||
|
||||
for (let y = 0; y < ROWS; y++) {
|
||||
for (let x = 0; x < COLS; x++) {
|
||||
if (x > BAND_MIN && x < BAND_MAX) continue;
|
||||
// Kenarlara doğru artan doluluk
|
||||
const d = Math.sqrt((x - cx) ** 2 + (y - cy) ** 2) / maxD;
|
||||
const density = 0.1 + 0.42 * d * d;
|
||||
if (hash(x, y, seed) > density) continue;
|
||||
const accent = hash(x, y, seed + 99) > 0.96;
|
||||
sonuc.push(
|
||||
pixelRect(x, y, {
|
||||
key: `${x}-${y}`,
|
||||
accent,
|
||||
accentDelay: accent ? (accentIdx++ % 8) * 0.45 : 0,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sonuc;
|
||||
}, [seed]);
|
||||
|
||||
return (
|
||||
<svg
|
||||
@@ -149,28 +155,32 @@ export function PixelDivider({
|
||||
|
||||
const COLS = 12;
|
||||
const ROWS = 2;
|
||||
const cx = (COLS - 1) / 2;
|
||||
|
||||
const pixels: ReactNode[] = [];
|
||||
let accentPlaced = false;
|
||||
// Deterministik çıktı — render başına yeniden üretme (PixelField ile aynı)
|
||||
const pixels = useMemo(() => {
|
||||
const cx = (COLS - 1) / 2;
|
||||
const sonuc: ReactNode[] = [];
|
||||
let accentPlaced = false;
|
||||
|
||||
for (let y = 0; y < ROWS; y++) {
|
||||
for (let x = 0; x < COLS; x++) {
|
||||
// Az sayıda, iri piksel: ortada yoğun, kenara doğru seyrelen küçük küme
|
||||
const dx = Math.abs(x - cx) / cx;
|
||||
const rowFalloff = y === 0 ? 0.9 : 0.35;
|
||||
const density = (1 - dx) ** 1.1 * rowFalloff;
|
||||
if (hash(x, y, seed) > density) continue;
|
||||
const accent = !accentPlaced && hash(x, y, seed + 99) > 0.8;
|
||||
if (accent) accentPlaced = true;
|
||||
pixels.push(
|
||||
pixelRect(x, y, {
|
||||
key: `${x}-${y}`,
|
||||
accent,
|
||||
}),
|
||||
);
|
||||
for (let y = 0; y < ROWS; y++) {
|
||||
for (let x = 0; x < COLS; x++) {
|
||||
// Az sayıda, iri piksel: ortada yoğun, kenara doğru seyrelen küçük küme
|
||||
const dx = Math.abs(x - cx) / cx;
|
||||
const rowFalloff = y === 0 ? 0.9 : 0.35;
|
||||
const density = (1 - dx) ** 1.1 * rowFalloff;
|
||||
if (hash(x, y, seed) > density) continue;
|
||||
const accent = !accentPlaced && hash(x, y, seed + 99) > 0.8;
|
||||
if (accent) accentPlaced = true;
|
||||
sonuc.push(
|
||||
pixelRect(x, y, {
|
||||
key: `${x}-${y}`,
|
||||
accent,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sonuc;
|
||||
}, [seed]);
|
||||
|
||||
return (
|
||||
<svg
|
||||
|
||||
Reference in New Issue
Block a user