---
title: 'Animasyon Başarımı'
source: 'https://academia.sh/tr/kurslar/duzen-ve-duyarli-tasarim/animasyon-basarimi'
course: 'Düzen Sistemleri ve Duyarlı Tasarım'
language: tr
updated: '2026-08-17T18:09:26+00:00'
license: 'CC BY-SA 4.0'
---

# Animasyon Başarımı

Hareketin çizim hattındaki karşılığı; hangi özellik değişiminin yerleşim, boyama ve bileşim aşamalarını yeniden çalıştırdığı, bileşik katmanın ne olduğu, zorlanmış yerleşim hesabı ve kare bütçesi.

Önceki üç ders hareketi tanımladı: dönüşüm geometriyi verdi, geçiş ve anahtar kareler
zamanı verdi. Bedelinden hiç söz edilmedi.

Bir kartı sağa kaydırmanın iki yolu var: `left` değerini artırmak ya da `transform`
listesine öteleme yazmak. Ekranda ikisi aynı görünür. Tarayıcı için ikisi aynı iş değildir.
Bu ders farkın nereden geldiğini kural olarak kurar.

## Çizim Hattı

Bir sayfanın ekrana gelmesi sıralı aşamalardan geçer. Hareket açısından dördü önemlidir:

1. **Stil hesabı.** Hangi bildirimin hangi ögeye uygulandığı çözülür; basamaklama ve
   kalıtım burada işler. Her değişim bu aşamayı çalıştırır.
2. **Yerleşim.** Her kutunun ölçüsü ve yeri hesaplanır. Bir kutunun genişliği değişirse
   kardeşleri, ana ögesi ve sonraki akış etkilenebilir; hesap yerel kalmayabilir.
3. **Boyama.** Kutuların içeriği — renk, kenarlık, gölge, metin — piksellere çevrilir.
4. **Bileşim.** Boyanmış yüzeyler sıralanır, dönüştürülür ve ekrana yerleştirilir.

Aşamalar sıralıdır: yerleşim yeniden çalışırsa boyama ve bileşim de çalışır. Ama tersi geçerli
değildir; bileşim tek başına çalışabilir.

## Hangi Özellik Hangi Aşamayı Tetikler

```js
// basarim.mjs — ozellik degisiminin cizim hattinda tetikledigi asamalar ve zorlanmis duzen sayimi
const HAT = ["stil", "duzen", "boyama", "bilesim"];

// Kural: bir ozellik hangi asamadan itibaren yeniden calisir?
const BASLANGIC = {
  width: "duzen", height: "duzen", "margin-block-start": "duzen", padding: "duzen",
  "border-width": "duzen", "font-size": "duzen", "line-height": "duzen",
  top: "duzen", left: "duzen", display: "duzen", "flex-basis": "duzen",
  color: "boyama", "background-color": "boyama", "background-image": "boyama",
  "border-radius": "boyama", "box-shadow": "boyama", outline: "boyama",
  visibility: "boyama", "text-decoration": "boyama",
  transform: "bilesim", opacity: "bilesim",
};

console.log("--- ozellik degisimi hangi asamadan itibaren yeniden calisir ---");
console.log("ozellik".padEnd(20) + HAT.map((a) => a.padStart(10)).join("") + "   asama sayisi");
for (const [ozellik, bas] of Object.entries(BASLANGIC)) {
  const i = HAT.indexOf(bas);
  const isaret = HAT.map((_, k) => (k === 0 || k >= i ? "x" : "-").padStart(10)).join("");
  console.log(ozellik.padEnd(20) + isaret + String(HAT.length - i + (i > 0 ? 1 : 0)).padStart(15));
}

console.log("\n--- ayni gorsel sonucu veren iki yazim ---");
for (const [a, b] of [["left", "transform"], ["width", "transform"], ["visibility", "opacity"]]) {
  const ia = HAT.indexOf(BASLANGIC[a]), ib = HAT.indexOf(BASLANGIC[b]);
  console.log(
    `${a.padEnd(12)} -> ${HAT.slice(ia).join(" > ").padEnd(26)}` +
    `${b.padEnd(12)} -> ${HAT.slice(ib).join(" > ")}`,
  );
}

// --- zorlanmis duzen (forced synchronous layout) sayimi ---
// Model: yazma islemi duzeni gecersiz kilar; olcu okuma islemi gecersiz duzeni
// okumak icin duzeni yeniden hesaplatir. Kare sonunda bir hesap zaten yapilir.
function duzenSayimi(islemler) {
  let kirli = false, zorlanmis = 0;
  const iz = [];
  for (const [tip, ad] of islemler) {
    if (tip === "yaz") { kirli = true; iz.push(`yaz ${ad}`); }
    else {
      if (kirli) { zorlanmis++; kirli = false; iz.push(`oku ${ad} -> DUZEN HESABI`); }
      else iz.push(`oku ${ad}`);
    }
  }
  return { zorlanmis, kareSonu: kirli ? 1 : 0, iz };
}

const KARISIK = [
  ["oku", "genislik(kart 1)"], ["yaz", "width(kart 1)"],
  ["oku", "genislik(kart 2)"], ["yaz", "width(kart 2)"],
  ["oku", "genislik(kart 3)"], ["yaz", "width(kart 3)"],
];
const AYRIK = [
  ["oku", "genislik(kart 1)"], ["oku", "genislik(kart 2)"], ["oku", "genislik(kart 3)"],
  ["yaz", "width(kart 1)"], ["yaz", "width(kart 2)"], ["yaz", "width(kart 3)"],
];

for (const [ad, islemler] of [["okuma ve yazma ic ice", KARISIK], ["once okuma, sonra yazma", AYRIK]]) {
  const s = duzenSayimi(islemler);
  console.log(`\n--- ${ad} ---`);
  for (const satir of s.iz) console.log("  " + satir);
  console.log(`  zorlanmis duzen hesabi: ${s.zorlanmis}, kare sonundaki hesap: ${s.kareSonu}`);
}

console.log("\n--- kare butcesi (yenileme hizindan aritmetik) ---");
for (const hz of [60, 90, 120, 144]) {
  console.log(`${String(hz).padStart(3)} kare/s -> kare basina ${(1000 / hz).toFixed(2)} ms`);
}
```

```
--- ozellik degisimi hangi asamadan itibaren yeniden calisir ---
ozellik                   stil     duzen    boyama   bilesim   asama sayisi
width                        x         x         x         x              4
height                       x         x         x         x              4
margin-block-start           x         x         x         x              4
padding                      x         x         x         x              4
border-width                 x         x         x         x              4
font-size                    x         x         x         x              4
line-height                  x         x         x         x              4
top                          x         x         x         x              4
left                         x         x         x         x              4
display                      x         x         x         x              4
flex-basis                   x         x         x         x              4
color                        x         -         x         x              3
background-color             x         -         x         x              3
background-image             x         -         x         x              3
border-radius                x         -         x         x              3
box-shadow                   x         -         x         x              3
outline                      x         -         x         x              3
visibility                   x         -         x         x              3
text-decoration              x         -         x         x              3
transform                    x         -         -         x              2
opacity                      x         -         -         x              2

--- ayni gorsel sonucu veren iki yazim ---
left         -> duzen > boyama > bilesim  transform    -> bilesim
width        -> duzen > boyama > bilesim  transform    -> bilesim
visibility   -> boyama > bilesim          opacity      -> bilesim

--- okuma ve yazma ic ice ---
  oku genislik(kart 1)
  yaz width(kart 1)
  oku genislik(kart 2) -> DUZEN HESABI
  yaz width(kart 2)
  oku genislik(kart 3) -> DUZEN HESABI
  yaz width(kart 3)
  zorlanmis duzen hesabi: 2, kare sonundaki hesap: 1

--- once okuma, sonra yazma ---
  oku genislik(kart 1)
  oku genislik(kart 2)
  oku genislik(kart 3)
  yaz width(kart 1)
  yaz width(kart 2)
  yaz width(kart 3)
  zorlanmis duzen hesabi: 0, kare sonundaki hesap: 1

--- kare butcesi (yenileme hizindan aritmetik) ---
 60 kare/s -> kare basina 16.67 ms
 90 kare/s -> kare basina 11.11 ms
120 kare/s -> kare basina 8.33 ms
144 kare/s -> kare basina 6.94 ms
```

Tablo bir ölçüm değil, bir **kural kümesidir**: özellikler tanımlarına göre üç gruba
ayrılır. Geometriye dokunanlar yerleşimden itibaren, yalnız görünüşe dokunanlar boyamadan
itibaren, kutunun ne ölçüsünü ne içeriğini değiştirenler ise yalnız bileşimden itibaren
çalışır.

Sınıflandırmanın kenarında birkaç özellik vardır — süzgeç ve karışım kipleri gibi — ve
bunların hangi aşamadan başladığı çizim gerçekleştirimine göre değişir. Kesin bilgi
tarayıcının geliştirici araçlarındaki çizim kaydından okunur; kural olarak
ezberlenmemelidir.

## Aynı Görünüm, Farklı Maliyet

Çıktının ikinci bloğu üç çifti karşılaştırıyor. `left` ile ötelemek üç aşama çalıştırır,
`transform` ile ötelemek bir aşama. `visibility` ile gizlemek boyamayı yeniden çalıştırır,
`opacity` ile soldurmak çalıştırmaz.

Buradan hareket yazımının en pratik kuralı çıkar: **animasyonlar dönüşüm ve saydamlık
üzerinden yazılır.** Bir kutunun büyümesi gerekiyorsa `width` yerine `scale`, yer
değiştirmesi gerekiyorsa `left` yerine `translate` kullanılır.

Kuralın bir bedeli vardır. `scale` kutunun içeriğini de ölçekler; metin, kutu büyürken
büyür. `width` değiştirmek ise metni yeniden satırlara böler. İkisi aynı görsel sonucu
vermez ve seçim, istenen sonucun hangisi olduğuna bağlıdır.

## Bileşik Katman

Dönüşümün ucuz olmasının nedeni, uygulandığı yerdir. Boyanmış bir yüzey bir kez üretilir;
dönüşüm ve saydamlık o yüzeye bileşim aşamasında uygulanır. Yüzey yeniden boyanmaz,
yalnızca farklı yerleştirilir.

Bunun için ögenin kendi yüzeyine, yani **bileşik katmana (compositing layer)** ayrılmış
olması gerekir. Katman ayrımını tarayıcı kendi karar vererek yapar; `will-change` bildirimi
bu kararı önceden bildirmenin yoludur:

```css
.olcum-kartlari > .kart:hover { will-change: transform; }
```

`will-change` bir garanti değil, bir **ipucudur**. Üç kuralı vardır. Katman ayırmak bellek
harcar; her ögeye yazmak yararı tersine çevirir. Bildirim, hareket başlamadan kısa süre
önce açılıp bittikten sonra kaldırılmalıdır — kalıcı yazılan bir ipucu kalıcı bir maliyettir.
Ve `will-change` de yığılma bağlamı kurar; ilk dersteki uyarı burada da geçerlidir.

## Zorlanmış Yerleşim Hesabı

Çıktının üçüncü ve dördüncü blokları, betikle sürülen bir hareketin sık düştüğü tuzağı bir
model üzerinde sayıyor. Model şudur: bir yazma işlemi yerleşimi geçersiz kılar; sonraki bir
ölçü okuma işlemi güncel değeri vermek zorunda olduğu için yerleşimi hemen yeniden hesaplatır.
Buna **zorlanmış yerleşim hesabı (forced synchronous layout)** denir.

Okuma ve yazma iç içe yapıldığında model iki ek hesap sayıyor. Aynı işlemler önce bütün
okumalar, sonra bütün yazmalar biçiminde sıralandığında ek hesap kalmıyor; kare sonunda
zaten yapılacak olan tek hesap yeterli oluyor.

Kural yazımdan bağımsızdır: ölçü okuyan işlemler bir öbekte, ölçü değiştiren işlemler ayrı
bir öbekte toplanır. Öbek sayısı arttıkça hesap sayısı da artar.

## Kare Bütçesi

Son blok aritmetik bir dönüşümdür: saniyede 60 kare üreten bir ekranda kare başına düşen
süre $1000 / 60 \approx 16{,}67$ milisaniyedir. Bu süre, bir karenin bütün aşamalarının —
betik, stil, yerleşim, boyama, bileşim — paylaştığı bütçedir.

Bütçe aşıldığında kare atlanır ve hareket takılır. Bu yüzden hareket yazarken sorulacak soru
"ne kadar sürüyor" değil, "kare başına hangi aşamalar çalışıyor"dur. Aşama sayısını
düşürmek, süreyi tahmin etmeye çalışmaktan daha güvenilir bir yoldur.

Yenileme hızı ekrana göre değişir; aynı animasyon farklı bütçelerle çalışır. Kare sayısına
bağlı yazılmış bir hareket hızlı ekranda hızlanır. Süre üzerinden yazılan bildirimler bu
sorunu taşımaz.

## Boyama Alanını Sınırlamak

Bir ögenin yeniden boyanması komşularını da kapsayabilir; boyama alanı ögeden büyük olabilir.
`contain` bildirimi bu yayılmayı sınırlar: `contain: layout` bir ögenin yerleşim hesabının dışarı
taşmayacağını, `contain: paint` boyamanın kutunun dışına çıkmayacağını bildirir.

Bu bildirim bir söz verir; sözü tutmayan bir içerik bozulur. `paint` değeri yazılan bir
kutudan taşan gölge ya da açılır menü kırpılır. Bildirim, kutunun gerçekten kendi kendine
yeter olduğu yerlerde yazılır.

## İstasyon Sayfasında Ölçüm

```css
/* hareket.css — 4. adım: hareketin çizim maliyetini sınırlamak */
.olcum-kartlari > .kart {
  transform-origin: center bottom;
  transition: transform 240ms ease-out, box-shadow 240ms ease-out;
  contain: layout paint;
}

.olcum-kartlari > .kart:hover,
.olcum-kartlari > .kart:focus-within {
  transform: translateY(-8px) scale(1.04);
  transition-duration: 160ms;
}

.istasyon-durumu[data-durum="bekliyor"] .gosterge {
  animation: nabiz 1400ms 200ms infinite alternate;
  will-change: transform, opacity;
}
```

Kart hareketi yalnız dönüşüm üzerinden yazıldı; `contain` bildirimi kartın yerleşim ve boyama
etkisini kendi kutusuyla sınırlıyor. Gösterge sürekli hareket ettiği için `will-change`
bildirimi orada kalıcı yazıldı — kalıcı hareket, kalıcı katmanı haklı çıkaran ender
durumlardan biridir.

Gölge geçişi bir ödünleşimdir: `box-shadow` boyamayı yeniden çalıştırır. Aynı görünüm,
kartın arkasına konan ayrı bir sözde elemanın saydamlığıyla da elde edilebilir ve o yazım
yalnız bileşim çalıştırır.

## Özet

- Çizim hattı sıralıdır: yerleşim çalışırsa boyama ve bileşim de çalışır, ama bileşim tek
  başına çalışabilir.
- Geometriye dokunan özellikler yerleşimden, yalnız görünüşe dokunanlar boyamadan, dönüşüm ve
  saydamlık ise bileşimden itibaren çalışır.
- Hareket dönüşüm ve saydamlık üzerinden yazıldığında aşama sayısı düşer; ölçü değiştiren
  yazımlar aynı görünümü daha çok işle üretir.
- Bileşik katman dönüşümün ucuz olmasının nedenidir; `will-change` bu ayrımı bildiren bir
  ipucudur ve bellek harcadığı için geçici kullanılır.
- Ölçü okuma ile ölçü yazma işlemleri iç içe yapıldığında zorlanmış yerleşim hesapları oluşur;
  okumaları ve yazmaları öbeklemek bunu ortadan kaldırır.

## Sonraki Adım

Buraya kadar hareketin nasıl yazıldığı ve neye mal olduğu kuruldu. Bir soru dışarıda kaldı:
hareket her kullanıcı için aynı şey midir? Bazı kullanıcılar için ekrandaki hareket
rahatsızlık, baş dönmesi ya da bulantı üretir ve işletim sistemi bu tercihi bildirir.
Sonraki ders, hareket azaltma tercihinin ne anlama geldiğini ve hangi hareketin kaldırılıp
hangisinin korunacağını ele alır.
