CSS animasyonları basit animasyonları JavaScript kullanmadan yapmayı saÄlar.
JavaScript, CSS animasyonlarını kontrol etmek ve biraz kodla daha iyi hale getirmek için kullanılabilir.
CSS GeçiÅleri
CSS geçiÅlerinin fikri basittir. Bir özelliÄi ve o özelliÄin deÄiÅiminin nasıl anime edileceÄini tanımlarız. O özellik deÄiÅtiÄinde, tarayıcı animasyonu çizer.
Yani, yapmamız gereken tek Åey özelliÄi deÄiÅtirmek. ÃzelliÄin deÄiÅiminin nasıl çizileceÄini tarayıcı halledecektir.
ÃrneÄin, aÅaÄıdaki CSS background-color özelliÄindeki deÄiÅimlerin animasyonunu 3 saniye boyunca oynatır.
.animated {
transition-property: background-color;
transition-duration: 3s;
}
Åimdi, eÄer bir element .animated sahipse, background-color özelliÄindeki herhangi bir deÄiÅiklik 3 saniye boyunca canlandırılır.
Arka planın animasyonunu oynatmak için aÅagıdaki tuÅa tıkla:
<button id="color">Bana tıkla</button>
<style>
#color {
transition-property: background-color;
transition-duration: 3s;
}
</style>
<script>
color.onclick = function() {
this.style.backgroundColor = 'red';
};
</script>
CSS geçiÅlerini tanımlamak için 4 özellik vardır:
transition-propertytransition-durationtransition-timing-functiontransition-delay
Bunları biraz sonra açıklayacaÄız, Åimdilik bilmemiz gereken, transition özelliÄi ile bu dört özelliÄi beraber Åu sırayla tanımlayabildiÄimiz: property duration timing-function delay. Ayrıca birden fazla özelliÄin animasyonunu tek seferde tanımlayabiliriz.
ÃrneÄin, bu tuÅ hem color hem de font-size özelliklerini canlandırır.
<button id="growing">Bana tıkla</button>
<style>
#growing {
transition: font-size 3s, color 2s;
}
</style>
<script>
growing.onclick = function() {
this.style.fontSize = '36px';
this.style.color = 'red';
};
</script>
Åimdi, animasyon özelliklerini teker teker açıklayalım.
transition-property
transition-property özelliÄine canlandıracaÄımız özelliklerin listesine yazarız. ÃrneÄin left, margin-left, height, color.
Tüm özelliklere animasyon eklenemez ama çoÄuna. all deÄeri âtüm özellikleri canlandırâ anlamına gelir.
transition-duration
transition-duration özelliÄinde animasyonun ne kadar sürmesi gerektiÄini tanımlayabiliriz. Süre CSS Time Formatkurallarına uymalıdır: saniye olarak s ya da milisaniye ms.
transition-delay
transition-delay özelliÄi ile animasyon baÅlamadan önceki gecikmeyi tanımlayabiliriz. ÃrneÄin, transition-delay: 1s ise animasyon deÄiÅimden 1 saniye sonra baÅlar.
Negatif deÄerler tanımlamak da mümkün. O zamansa animasyon ortadan baÅlar. ÃrneÄin, transition-duration: 2s ise ve gecikme -1s ise animasyon 1 saniye sürer ve yarısından baÅlar.
Buradaki animasyon 0âdan 9âa kadar sayıları CSS translate özelliÄini kullanarak kaydırıyor.
stripe.onclick = function() {
stripe.classList.add('animate');
};#digit {
width: .5em;
overflow: hidden;
font: 32px monospace;
cursor: pointer;
}
#stripe {
display: inline-block
}
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
transition-timing-function: linear;
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
Click below to animate:
<div id="digit"><div id="stripe">0123456789</div></div>
<script src="script.js"></script>
</body>
</html>transform özelliÄinin animasyonu böyle tanımlanmıÅtır:
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
}
Yukardaki örnekte JavaScript .animate sınıfını elemente ekler â ve animasyon baÅlar.
stripe.classList.add('animate');
Ayrıca animasyonu âortadanâ da, belli bir sayıdan, baÅlatabiliriz. Yani, transition-delay özelliÄine negatif deÄer vererek Åu anki saniyeye karÅılık gelen sayıdan baÅlatabiliriz.
Rakama tıklarsanız, animasyonu Åu anki saniyeden baÅlatır.
stripe.onclick = function() {
let sec = new Date().getSeconds() % 10;
stripe.style.transitionDelay = '-' + sec + 's';
stripe.classList.add('animate');
};#digit {
width: .5em;
overflow: hidden;
font: 32px monospace;
cursor: pointer;
}
#stripe {
display: inline-block
}
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
transition-timing-function: linear;
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
Click below to animate:
<div id="digit"><div id="stripe">0123456789</div></div>
<script src="script.js"></script>
</body>
</html>Bunu JavaScriptâe bir satır fazladan ekleyerek yapabiliriz:
stripe.onclick = function() {
let sec = new Date().getSeconds() % 10;
// for instance, -3s here starts the animation from the 3rd second
stripe.style.transitionDelay = '-' + sec + 's';
stripe.classList.add('animate');
};
transition-timing-function
Bu özellik, zamanlama fonksiyonu, animasyon iÅleminin süre boyunca nasıl daÄıtılacaÄını tanımlamamızı saÄlar. ÃrneÄin, yavaÅ baÅlayıp sonra hızlanacak mı yoksa tam tersi mi gibi.
İlk bakıÅta en karmaÅık özellik gibi gözükebilir. Ama üstünde biraz zaman harcayınca çok basitleÅecektir.
Bu özellik iki tip deÄer kabul eder: bir Bezier eÄrisi ya da steps fonksiyonu. Daha sık kullanıldıÄı için ilk olarak eÄriden baÅlayalım.
Bezier eÄrisi
Zamanlama fonksiyonu Åu özellikleri saÄlayan 4 kontrol noktası olan bir Bezier eÄrisi ile tanımlanabilir:
- lk kontrol noktası:
(0,0). - Son kontrol noktası:
(1,1). - Ara noktalar için
x deÄeriÂ0..1aralıÄında olmalıdır,Ây her Åey olabilir.
CSSâde bir bezier eÄrisi Åöyle tanımlanır: cubic-bezier(x2, y2, x3, y3). Burada sadece 2. ve 3. kontrol noktalarını tanımlamamız yeterli çünkü 1. nokta (0,0)'a 4. nokta da (1,1)'e sabitlenmiÅtir.
Zamanlama fonksiyonu animasyonun zaman içinde ne kadar hızlı gerçekleÅtiÄini tanımlar.
x ekseni zamanı gösterir:Â0 â baÅlama anı,Â1 âtransition-durationözelliÄinin son anı.y ekseni iÅlemin ne kadarının tamamlandıÄını gösterir.Â0 â canlandırılan özelliÄin baÅlama deÄeri,Â1 â özelliÄin son deÄeri.
En basit eÄri biçimi animasyon eÅit bir Åekilde oynatıldıÄında, yani doÄrusal bir hızda olduÄundadır. Bu eÅit daÄılım Åu eÄri ile tanımlanabilir: cubic-bezier(0, 0, 1, 1).
İÅte eÄrinin nasıl gözüktüÄü:
â¦GörüldüÄü üzere, bu eÄri aslında düz bir çizgi. Zaman (x) geçtikçe, animasyonun tamamlanması (y) 0âdan 1âe sabit Åekilde artıyor.
AÅaÄıdaki örnekteki tren, soldan saÄa sabit bir hızla hızla hareket ediyor. (Trene tıkla).
.train {
position: relative;
cursor: pointer;
width: 177px;
height: 160px;
left: 0;
transition: left 5s cubic-bezier(0, 0, 1, 1);
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='450px'">
</body>
</html>CSS özelliÄi olan transition biraz önce gördüÄümüz eÄriyi kullanarak tanımlanmıÅ.
.train {
left: 0;
transition: left 5s cubic-bezier(0, 0, 1, 1);
/* JavaScript left'e 450px deÄerini verir*/
}
â¦Peki trenin yavaÅladıÄını nasıl gösterebiliriz?
BaÅka bir bezier eÄrisi kullanabiliriz: cubic-bezier(0.0, 0.5, 0.5 ,1.0)
EÄrinin grafiÄi:
GörüldüÄü gibi, animasyon hızlı baÅlıyor daha sonra ise hızlanması gitgide yavaÅlıyor.
Åimdi ise zamanlama fonksiyonunu çalıÅırken görelim (Trene tıkla):
.train {
position: relative;
cursor: pointer;
width: 177px;
height: 160px;
left: 0px;
transition: left 5s cubic-bezier(0.0, 0.5, 0.5, 1.0);
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='450px'">
</body>
</html>CSS:
.train {
left: 0;
transition: left 5s cubic-bezier(0, .5, .5, 1);
/* JavaScript left'e 450px deÄerini verir*/
}
CSSâde önceden tanımlanmıÅ, hazır, birkaç fonksiyon vardır. linear, ease, ease-in, ease-out ve ease-in-out.
linear fonksiyonu cubic-bezier(0, 0, 1, 1) için bir kısayoldur â Zaten görmüŠolduÄumuz düz bir çizgi.
DiÄerleri ise Åu cubic-bezier eÄrileri için kısayoldur:
ease* |
ease-in |
ease-out |
ease-in-out |
|---|---|---|---|
(0.25, 0.1, 0.25, 1.0) |
(0.42, 0, 1.0, 1.0) |
(0, 0, 0.58, 1.0) |
(0.42, 0, 0.58, 1.0) |
* â EÄer bir zamanlama fonksiyonu tanımlanmadıysa, varsayılan deÄer, ease kullanılır
Yani, trenimizi yavaÅlatmak için ease-out fonksiyonunu kullanabilirdik.
.train {
left: 0;
transition: left 5s ease-out;
/* transition: left 5s cubic-bezier(0, .5, .5, 1); */
}
Ama biraz farklı görünüyor.
Bir bezier eÄrisi, animasyonun sınırları dıÅına âtaÅmasınaâ neden olabilir.
EÄrinin üzerindeki kontrol noktaları herhangi bir y deÄeri alabilir: negatif veya çok büyük deÄerler. O zaman bezier eÄrisi de çok aÅaÄıya düÅebilir ya da çok yukarı zıplayabilir ve animasyonun normal sınırları dıÅına çıkmasına sebep olabilir.
AÅaÄıdaki örneÄin animasyon kodu:
.train {
left: 100px;
transition: left 5s cubic-bezier(.5, -1, .5, 2);
/* JavaScript left'e 400px deÄerini verir*/
}
Bu animasyonun, left özelliÄini 100pxâden 400pxâe kadar oynatılmasını bekliyoruz.
Ama trene tıklarsanız göreceksiniz ki:
- İlk olarak, tren geri gidiyor:
left100pxâden daha az oluyor. - Sonra ileri gidiyor,
400pxâden biraz daha ileri. - Ve
400pxâe geri dönüyorâ¦
.train {
position: relative;
cursor: pointer;
width: 177px;
height: 160px;
left: 100px;
transition: left 5s cubic-bezier(.5, -1, .5, 2);
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='400px'">
</body>
</html>Peki neden böyle oluyor? AÅaÄıdaki bezier eÄrisinin grafiÄine bakarsak gayet açıkça anlayabiliriz.
2. noktanın y koordinatını sıfırın altına çektik ve 3. noktanın y koordinatını da 1âin üstüne çıkardık. Bu yüzden, eÄri âdüzgünâ dörtgenin dıÅına çıkıyor. y deÄeri âstandartâ aralıÄın, 0...1âin, dıÅına çıkıyor.
BildiÄimiz gibi, y âanimasyonun ne kadarının tamamlandıÄınıâ gösteriyor. y = 0 deÄeri özelliÄin baÅlama deÄerine ve y = 1 de son deÄerine karÅılık geliyor. Yani, y < 0 olan deÄerler özelliÄi, left özelliÄinin baÅlama deÄerinden daha aÅaÄıya çekiyor ve y > 1 olan deÄerler ise son left deÄerinden daha üste çıkarıyor.
Bu tabii ki daha âyumuÅakâ bir örnek. EÄer y deÄerine -99 ve 99 gibi deÄerler verseydik tren aralıÄın çok daha dıÅına çıkardı.
Ama spesifik bir iÅ için Bezier eÄrisini nasıl yapabiliriz? Bunun için birçok yardımcı araç var. ÃrneÄin, http://cubic-bezier.com/ sitesiyle bir bezier eÄrisi çizebiliriz.
Steps
Bir zamanlama fonksiyonu olan steps(number of steps[, start/end]), animasyonu adımlara bölmemizi saÄlar.
Animasyonu rakamları kullandıÄımız bir örnekte görelim.
AÅaÄıda, sadece temel olması için, animasyonsuz bir rakam dizisi var.
#digit {
border: 1px solid red;
width: 1.2em;
}
#stripe {
display: inline-block;
font: 32px monospace;
}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="digit"><div id="stripe">0123456789</div></div>
</body>
</html>Kırmızı âpencereninâ dıÅında olan rakamları görünmez yaparak ve her adımda diziyi sola kaydırarak rakamların teker teker gözükmesini saÄlayacaÄız.
Toplamda 9 adım olacak, her rakam için bir adım hareketi:
#stripe.animate {
transform: translate(-90%);
transition: transform 9s steps(9, start);
}
ÃalıÅırken görelim:
#digit {
width: .5em;
overflow: hidden;
font: 32px monospace;
cursor: pointer;
}
#stripe {
display: inline-block
}
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
transition-timing-function: steps(9, start);
}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
Click below to animate:
<div id="digit"><div id="stripe">0123456789</div></div>
<script>
digit.onclick = function() {
stripe.classList.add('animate');
}
</script>
</body>
</html>steps(9, start) fonksiyonun ilk argümanı adım sayısını gösterir. transform 9 parçaya ayrılacak (parçaların her biri 10%). Zaman aralıÄı da otomatik olarak 9 eÅit parçaya ayrılacak. Yani transition: 9s bize tüm animasyon için 9 saniye veriyor ve o da her rakam için 1 saniye olacak Åekilde bölünüyor.
İkinci argüman Åu iki kelimeden biri olabilir: start ya da end.
start animasyon baÅladıÄı anda ilk adımı yapmamız gerektiÄini söyler.
Animasyon sırasında da görebileceÄimiz gibi, rakama tıkladıÄımız zaman anında 1âe (ilk adıma) geçiyor ve bir sonraki saniye baÅladıÄında tekrar deÄiÅiyor.
Yani, deÄerler Åu Åekilde deÄiÅiyor:
0sâ-10%(İlk saniyenin baÅında gerçekleÅen deÄiÅim, anında gerçekleÅiyor)1sâ-20%- â¦
8sâ-80%- (Son saniyeyse son deÄeri gösteriyor).
DiÄer bir alternatif olan end deÄeri, deÄiÅimin her saniyenin baÅında deÄil de, bu sefer sonunda gerçekleÅeceÄini söyler.
Bu sefer deÄerler Åu Åekilde deÄiÅiyor:
0sâ01sâ-10%(İlk deÄiÅim 1. saniyenin sonunda gerçekleÅiyor)2sâ-20%- â¦
9sâ-90%
Burada step(9, end) fonksiyonun nasıl çalıÅtıÄını görebiliriz. İlk rakam deÄiÅimindeki duraklamaya dikkat edin.
#digit {
width: .5em;
overflow: hidden;
font: 32px monospace;
cursor: pointer;
}
#stripe {
display: inline-block
}
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
transition-timing-function: steps(9, end);
}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
Click below to animate:
<div id="digit"><div id="stripe">0123456789</div></div>
<script>
digit.onclick = function() {
stripe.classList.add('animate');
}
</script>
</body>
</html>Bu deÄerlerin kısayolları da var:
step-startâsteps(1, start)ile aynı anlama gelir. Animasyon anında baÅlar ve toplamda 1 adımı vardır. Yani baÅlayıp anında biter, sanki hiç animasyon yokmuÅ gibi.step-endâsteps(1, end)ile aynı anlama gelir: AnimasyonuÂtransition-durationsonunda 1 adım olacak Åekilde yapar.
Bu deÄerler çok nadiren kullanılır çünkü bunlar animasyondan çok, tek seferde deÄiÅimlerdir.
transitionend Eventâi
CSS animasyonu bittiÄi zaman transitionend eventâi tektiklenir.
Animasyon tamamlandıktan sonra bir aksiyon yapmak için kullanılır. Ayrıca, animasyonları birbirine baÄlamamızı saÄlar.
ÃrneÄin, aÅaÄıdaki gemi tıklanıldıÄında ileri doÄru yüzmeye ve sonra geri dönmeye baÅlar. Her seferinde biraz daha saÄa doÄru gidiyor.
Animasyon go fonksiyonun çaÄrılması ile baÅlıyor ve animasyon bittiÄi zaman geminin yönünü ters çevirip tekrar çaÄrılıyor.
boat.onclick = function() {
//...
let times = 1;
function go() {
if (times % 2) {
// saÄa doÄru yüz
boat.classList.remove('back');
boat.style.marginLeft = 100 * times + 200 + 'px';
} else {
// sola doÄru yüz
boat.classList.add('back');
boat.style.marginLeft = 100 * times - 200 + 'px';
}
}
go();
boat.addEventListener('transitionend', function() {
times++;
go();
});
};
transitionend eventâinin objesinin birkaç özelliÄi vardır:
event.propertyName- Animasyonu biten CSS özelliÄinin adı. Birden çok özelliÄe animasyon eklediÄimiz zaman kullanılıÅlı olabilir.
event.elapsedTimetransition-delayhariç, animasyonun saniye olarak ne kadar sürdüÄünü gösterir.
Keyframes
@keyframes CSS kuralını kullanarak birden çok basit animasyonu birleÅtirebiliriz.
Animasyonun âadınıâ ve kurallarını tanımlamamızı saÄlar. Bu kurallar animasyonun neye, ne zaman ve nereye doÄru olacaÄını gösterir. Sonra, animation özelliÄini kullanarak animasyonu bir elemente ekleyebilir ve ek olarak parametre girebilmemizi saÄlar.
AÅaÄıda açıklamalı bir örnek görebilirsiniz:
<div class="progress"></div>
<style>
@keyframes go-left-right { /* bir isim ver: "go-left-right" */
from { left: 0px; } /* animasyonu left: 0px'den baÅlat */
to { left: calc(100% - 50px); } /* animasyonu 100%-50px'de bitir */
}
.progress {
animation: go-left-right 3s infinite alternate;
/* "go-left-right" animasyonunu elemente ekle
animasyon süresi 3 saniye
kaç kere yapılacaÄı: sonsuz (infinite)
her seferinde yönünü ters çevir
*/
position: relative;
border: 2px solid green;
width: 50px;
height: 20px;
background: lime;
}
</style>
@keyframes hakkında birçok makale ve detaylı açıklamasını bulabilirsiniz.
Büyük ihtimalle @keyframesâe çok sık ihtiyacınız olmayacak, sitenizdeki her Åey sürekli hareket etmediÄi takdirde.
Ãzet
CSS animasyonları bir veya birden fazla CSS özelliÄindeki deÄiÅimlere rahatça animasyon eklememizi saÄlar.
ÃoÄu animasyon iÅi için iyidir. Animasyonlar ayrıca JavaScript kullanarak da eklenebilir. Bir sonraki bölüm de onun üzerine.
Javascript Animasyonları ile karÅılaÅtırıldıÄında CSS animasyonların farkları Åunlardır:
- Kolay Åeyleri kolayca yapmamızı saÄlar.
- Hızlı ve CPU için hafiftir.
- JavaScript animasyonları daha esnektir. Her türlü animasyonu programlayabilmenizi saÄlar. ÃrneÄin, bir elementin âpatlamaâ animasyonu gibi.
- JavaScript animasyonları sadece CSS özelliÄi deÄiÅimleri ile sınırlı deÄildir. JavaScript ile bir animasyon için yeni elementler yaratabiliriz.
Animasyonların çoÄu bu bölümde anlatıldıÄı gibi CSS ile gerçekleÅtirilebilir. transitionend eventâi animasyon bittikten sonra JavaScript kodu çalıÅtırmamızı saÄlar. Bu sayede kodla da kolayca entegre edilebilir.
Bir sonraki bölümde daha karmaÅık animasyonlar için JavaScript animasyonları kullanacaÄız.
Yorumlar
<code>kullanınız, birkaç satır eklemek için ise<pre>kullanın. EÄer 10 satırdan fazla kod ekleyecekseniz plnkr kullanabilirsiniz)