fix(tema): geçişte tek silüet — dolu çizim katmanı kaldırıldı, boşluklar tam ekran solmayla kapanır

"Logo içinde logo" görünmesin (Bilal, 8 Eki 2026): maske artık yalnız
işaretin çizimi + alfası motion ile sürülen tam ekran dolgu. Büyümenin
ikinci yarısında kareler arasında kalan eski görüntü yeni temaya solar.
kolay-tercih-mark-dolu.svg ve --kt-tema-kapanis kaldırıldı; DESIGN §2.3 notu.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-08 23:50:43 +03:00
parent 9f401602a8
commit 4c84a1a974
4 changed files with 32 additions and 103 deletions

View File

@@ -2,8 +2,7 @@
// çevirmez; yeni tema, KolayTercih işaretinin biçiminde önce ekranın altından
// ortaya süzülür, sonra merkezden büyüyerek ekranı kaplar. View Transitions
// API + CSS maskesi (globals.css `.kt-tema-gecis`) eski/yeni görüntü çiftini
// kurar; maskenin konumu, boyu, boşluk kapanışı ve son dolgu motion ile
// sürülür. Tarayıcı View Transitions bilmiyorsa ya da kullanıcı hareketi
// kurar; maskenin konumu, boyu ve son dolgu motion ile sürülür. Tarayıcı View Transitions bilmiyorsa ya da kullanıcı hareketi
// azaltmışsa tema düz değişir.
import { animate, type AnimationPlaybackControls } from "motion";
@@ -11,32 +10,18 @@ import { animate, type AnimationPlaybackControls } from "motion";
/** Geçiş sırasında <html>'de duran sınıf (globals.css). */
const GECIS_SINIFI = "kt-tema-gecis";
// Saniye. Faz 1 (uçuş): işaret ekranın altından ortaya gelir — normal,
// boşluklu hâliyle. Faz 2 (kaplama): merkezden büyüyerek ekranı aşar;
// kaplamanın KAPANIS_BASI…KAPANIS_BITIS aralığında dolu çizim merkezden
// dışa büyür ve kareler arası boşlukları kapatır (en büyük hâle ulaşmadan).
// EASE fazlar arasında geçişin eski koreografisiyle aynı hissi verir.
// Saniye. Faz 1 (uçuş): işaret ekranın altından ortaya gelir. Faz 2
// (kaplama): merkezden büyüyerek ekranı aşar; DOLGU_BASI'ndan sonra tam ekran
// dolgu alfası yükselir ve kareler arasında / kenarlarda kalan eski görüntü
// yeni temaya solar. Ekranda tek silüet vardır, ikinci bir şekil büyümez.
const UCUS_SURE = 0.45;
const KAPLAMA_SURE = 0.6;
const KAPANIS_BASI = 0.55;
const KAPANIS_BITIS = 0.9;
const DOLGU_BASI = 0.5;
const EASE = [0.65, 0, 0.35, 1] as const;
// CSS'teki kt-tema-omur'un süresi: motion bitmeden pseudo eleman kalkmasın
// diye toplamın biraz üstü (globals.css'te --kt-tema-sure ile okunur).
const GECIS_SURESI = UCUS_SURE + KAPLAMA_SURE + 0.1;
// İşaretin dış kenarları (public/kolay-tercih-mark-dolu.svg, 180'lik viewBox;
// orijinal logonun boşlukları doldurulmuş çizimi, dış uzantılar aynı):
// x 27–147, y 29–151. Merkeze (90) göre oranlar — dolgu, bu sınır kutusu
// ekranı tam kapsadığı andan itibaren dolar; erken dolarsa ekrandaki eski
// zemin topluca solardı.
const KENAR_ORAN = {
sol: (90 - 27) / 180,
sag: (147 - 90) / 180,
ust: (90 - 29) / 180,
alt: (151 - 90) / 180,
} as const;
let suruyor = false;
/**
@@ -73,27 +58,13 @@ export function temayiGecisle(uygula: () => void) {
const merkezY = boy / 2;
const baslangicY = boy + ucusKenar / 2;
// Kaplama merkezden ekranın en uzak köşesine kadar büyümeli. İşaretin
// görünür karesi viewBox'ın ~%67'si; kenar bu oranla çarpılır ki en büyük
// hâlde köşe karesi bile ekranı aşsın (eski hesapla aynı çarpan).
const sonKenar = Math.ceil(Math.hypot(merkezX, merkezY) * 3.4);
// Dolgu, işaretin dış kutusu ekranı tam kapsadığı anda başlar (erken
// dolarsa marka henüz ekrana ulaşmadan eski zemin topluca solardı). Alt
// sınır 0.9: kapsama hesaba katılmayan dar bir marjla geç kalırsa bile
// dolgu kaplamanın son ~%10'unda bitsin; aksi hâlde ekranın köşelerinde
// eski zemin belirgin biçimde kalır.
const kapsaKenar = Math.max(
en / 2 / Math.max(KENAR_ORAN.sol, KENAR_ORAN.sag),
boy / 2 / Math.max(KENAR_ORAN.ust, KENAR_ORAN.alt),
);
const dolguBasi = Math.min(
1,
Math.max((kapsaKenar - ucusKenar) / (sonKenar - ucusKenar), 0.9),
);
// görünür karesi viewBox'ın ~%67'si; kenar bu oranla çarpılır ki kareler
// ekranı geniş ölçüde kaplasın — kalan boşlukları dolgu solması kapatır.
const sonKenar = Math.ceil(Math.hypot(merkezX, merkezY) * 3);
kok.style.setProperty("--kt-tema-x", `${merkezX}px`);
kok.style.setProperty("--kt-tema-y", `${baslangicY}px`);
kok.style.setProperty("--kt-tema-kenar", `${ucusKenar}px`);
kok.style.setProperty("--kt-tema-kapanis", "0");
kok.style.setProperty("--kt-tema-dolgu", "0");
kok.style.setProperty("--kt-tema-sure", `${GECIS_SURESI}s`);
kok.classList.add(GECIS_SINIFI);
@@ -118,22 +89,11 @@ export function temayiGecisle(uygula: () => void) {
ease: EASE,
onUpdate: (kenar) => kok.style.setProperty("--kt-tema-kenar", `${kenar}px`),
}),
// Kapanış: dolu çizimin boyu kenar × kapanış — büyümenin ortasından
// sonuna doğru boşluklar merkezden dışa dolar, logo en büyük hâle
// ulaşmadan kapanır. Boyut sürüldüğü için ek bir katmanın alfa
// çakışması gerekmez; maske toplamı (add) değişmez.
// Dolgu: büyümenin ikinci yarısında kareler arasında ve ekran
// kenarlarında kalan eski görüntü yeni temaya solar.
animate(0, 1, {
duration: KAPLAMA_SURE * (KAPANIS_BITIS - KAPANIS_BASI),
delay: UCUS_SURE + KAPLAMA_SURE * KAPANIS_BASI,
ease: EASE,
onUpdate: (kapanis) => kok.style.setProperty("--kt-tema-kapanis", `${kapanis}`),
}),
// Dolgu: işaretin dış çentiklerinde kalan eski zemin son anda dolar —
// ekranı kapsayan boşluklar (kareler arası şeritler) maskenin kendisinde
// dolu çizimle kapanmıştır, burada değil.
animate(0, 1, {
duration: KAPLAMA_SURE * (1 - dolguBasi),
delay: UCUS_SURE + KAPLAMA_SURE * dolguBasi,
duration: KAPLAMA_SURE * (1 - DOLGU_BASI),
delay: UCUS_SURE + KAPLAMA_SURE * DOLGU_BASI,
ease: EASE,
onUpdate: (dolgu) => kok.style.setProperty("--kt-tema-dolgu", `${dolgu}`),
}),