- canvas-confetti, web sayfalarında canvas tabanlı confetti animasyonları çalıştıran istemci tarafı bir kütüphanedir; hem NPM kurulumu hem de CDN üzerinden doğrudan ekleme destekler
- Temel
confetti() API’si, tek bir seçenek nesnesiyle parçacık sayısı, açı, yayılım, hız, yerçekimi, renk, şekil, konum, z-index gibi ayarları düzenler; Promise destekleyen ortamlarda animasyonun tamamlanma anı alınabilir
- Reduced Motion kullanıcıları için
disableForReducedMotion seçeneğini sunar; bu değer varsayılan olarak false olsa da ilerideki bir major sürümde değişme ihtimali vardır
- SVG Path ve metin tabanlı özel şekiller oluşturulabilir;
square, circle, star varsayılan şekillerine ek olarak emoji confetti gibi efektler de uygulanabilir
confetti.create() belirli bir canvas üzerinde instance oluşturur ve resize, useWorker gibi global seçenekleri destekler; ancak useWorker: true olduğunda canvas kontrolü web worker’a devredilir ve ana thread’den müdahale edilirse hata oluşur
Kurulum ve çalıştırma yöntemi
- Kütüphanenin nasıl çalıştığını demo sayfasında görebilirsiniz
- NPM paketi olarak kurulabilir
npm install --save canvas-confetti
- Proje build’lerinde
require('canvas-confetti') ile kullanılabilir
- Bu kütüphane bir istemci bileşenidir ve Node üzerinde çalışmaz
- README, projenin webpack gibi araçlarla build edilmesi gerektiğini belirtir
- HTML sayfasına CDN script’i olarak doğrudan eklenebilir
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.4/…;
- CDN kullanırken projeye eklediğiniz andaki en güncel sürümü kullanmanız önerilir; tüm sürümler releases page üzerinden görülebilir
Reduced Motion desteği
- Bazı kullanıcılar web sitelerindeki hareketi istemeyebilir veya azaltmayı tercih edebilir; tarayıcılar bunu
prefers-reduced-motion ile iletebilir
disableForReducedMotion seçeneği kullanıldığında, rahatsız edici animasyonlar konusunda zorlanan kullanıcılara confetti gösterilmeyebilir
- Bu seçeneğin mevcut varsayılan değeri
falsetur
- İlerideki bir major sürümde varsayılan değerin değiştirilmesi değerlendiriliyor; güçlü bir görüşünüz varsa issue olarak iletebilirsiniz
disableForReducedMotion uygulanıp confetti devre dışı bırakılırsa confetti() Promise’i hemen resolve olur
Temel API ve Promise davranışı
- NPM ile kurulduğunda proje build’inde istemci bileşeni olarak require edilebilir; CDN sürümünde ise
window üzerindeki confetti fonksiyonu olarak sunulur
confetti([options]) isteğe bağlı tek bir seçenek nesnesi alır
window.Promise varsa animasyonun tamamlandığını bildiren bir Promise döndürür
- Promise olmayan IE gibi ortamlarda
null döndürür
- Promise polyfill’i kullanılabilir
confetti.Promise = MyPromise biçiminde Promise implementasyonunu doğrudan sağlayabilirsiniz
- Tamamlanmadan önce
confetti birden çok kez çağrılırsa her seferinde aynı Promise döndürülür
- Dahili olarak aynı canvas öğesini yeniden kullanır ve mevcut animasyona devam ederken yeni confetti ekler
- Her çağrının döndürdüğü Promise, tüm animasyonlar bittikten sonra resolve olur
Başlıca seçenekler
particleCount: fırlatılacak confetti sayısı, varsayılan 50
angle: fırlatma açısı, varsayılan 90; 90 yukarıyı ifade eder
spread: merkezden yayılma aralığı, varsayılan 45
startVelocity: başlangıç hızı, varsayılan 45
decay: hızın azalma oranı, varsayılan 0.9
- 0 ile 1 arasında tutulmalıdır; aralığın dışına çıkarsa hız artabilir
gravity: parçacıkların aşağı çekilme derecesi, varsayılan 1
0.5 yarım yerçekimi anlamına gelir; sınır olmadığından yukarı çıkacak şekilde de ayarlanabilir
drift: sağa-sola sürüklenme derecesi, varsayılan 0
- Negatif değer sol, pozitif değer sağ anlamına gelir
flat: gerçek 3D confetti gibi eğilme ve sallanma efektini kapatabilir; varsayılan false
ticks: confetti’nin hareket ettiği adım sayısı, varsayılan 200
origin: fırlatmanın başlangıç konumu
origin.x: sayfadaki x konumu; 0 sol, 1 sağ, varsayılan 0.5
origin.y: sayfadaki y konumu; 0 üst, 1 alt, varsayılan 0.5
colors: HEX biçiminde renk string’leri dizisi
shapes: confetti şekilleri dizisi
- Varsayılan yerleşik değerler
square, circle, star
- Varsayılan olarak square ve circle eşit oranda karıştırılır
['circle', 'circle', 'square'] gibi dizi oranlarıyla karışım oranı ayarlanabilir
scalar: her parçacığın ölçeği, varsayılan 1
zIndex: confetti gösterim katmanı, varsayılan 100
disableForReducedMotion: Reduced Motion tercih eden kullanıcılar için confetti’yi devre dışı bırakır
Özel şekil oluşturma
confetti.shapeFromPath({ path, matrix? }), SVG Path string ile özel confetti şekli oluşturur
- Path tabanlı şekillerde bazı kısıtlamalar vardır
- Tüm path’ler dolu şekil olarak işlenir; stroke path uygulanmamıştır
- Path tek renkle sınırlıdır
- Tüm path’ler geçerli bir transform matrix gerektirir
- Matrix hesaplaması maliyetli olduğundan geliştirme sırasında her path için bir kez hesaplayıp cache’lemek önerilir
- Matrix aynı path değeri için her zaman aynıdır
- Kütüphaneyi güncellediğinizde forward compatibility için matrix’i yeniden oluşturup cache’lemek önerilir
- Path tabanlı confetti,
Path2D destekleyen tarayıcılarla sınırlıdır
- Dönüş değeri bir
Shape nesnesidir ve doğrudan shapes dizisine eklenerek kullanılabilir
var triangle = confetti.shapeFromPath({ path: 'M0 10 L5 0 L10 10z' });
confetti({
shapes: [triangle]
});
confetti.shapeFromText({ text, scalar?, color?, fontFamily? }) metin tabanlı confetti şekli oluşturur; standart Unicode emoji kullanılabilir
- Metin tabanlı şekiller emoji confetti için uygundur
- Sallanan confetti için genellikle kareye yakın tek karakterler, özellikle emoji’ler iyi uyar
- Metni her seferinde çizmek yerine rasterize ettiği için, oluşturduktan sonra ölçek çok büyütülürse bulanıklaşabilir
- Confetti seçeneklerinde
scalar kullanmayı planlıyorsanız shape oluştururken aynı scalar değerini kullanmanız önerilir
- Metin seçenekleri
text, scalar, color, fontFamily alır
fontFamily varsayılanı, yerel OS emoji render etme pratiklerini izler ve sans-serife fallback yapar
- Web fontu kullanırken font, confetti render edilmeden önce yüklenmiş olmalıdır
var scalar = 2;
var pineapple = confetti.shapeFromText({ text: '🍍', scalar });
confetti({
shapes: [pineapple],
scalar
});
Özel canvas ve worker render etme
confetti.create(canvas, [globalOptions]), belirli bir canvas’ı kullanan bir confetti fonksiyonu instance’ı oluşturur
- Confetti’yi sayfa içindeki belirli bir alanla sınırlamak istediğinizde kullanışlıdır
- Varsayılan olarak bu metot, canvas’a çizim yapmak dışında canvas’ı değiştirmez
- Canvas’ın görüntü boyutu CSS ile değiştirildiğinde gerçek canvas görüntü boyutu değişmez; bu da görüntünün esneyip bulanıklaşmasına yol açabilir
resize seçeneği açıldığında kütüphane canvas görüntü boyutunu eşleştirir, pencere boyutu değişimlerine ve mobil döndürmeye de yanıt verir
- Aynı canvas öğesiyle confetti instance’ını birden fazla kez başlatmayın; oluşturduğunuz özel instance’ı saklamalısınız
-
Global seçenekler
resize: canvas görüntü boyutunu ayarlayıp pencere değişikliklerine göre koruyup korumayacağını belirler, varsayılan false
useWorker: mümkün olduğunda confetti animasyonunu asenkron bir web worker’da render eder, varsayılan false
- Varsayılan durumda animasyon her zaman ana thread’de çalışır
- Tarayıcı destekliyorsa ana thread’i engellememek için animasyon ana thread dışında çalıştırılır
- Desteklemeyen tarayıcılarda bu değer yok sayılır
disableForReducedMotion: ilgili confetti instance’ının kullanıcının Reduced Motion isteğine her zaman saygı göstermesini sağlar
-
useWorker: true için dikkat edilmesi gerekenler
useWorker: true kullanıldığında canvas kontrolü web worker’a devredilir
- Bu durumda canvas’ı DOM’dan kaldırmak dışında ana thread’den müdahale etmek hata oluşturur
- Canvas’ı doğrudan manipüle etmeniz gerekiyorsa
useWorker seçeneğini kullanmamalısınız
var myCanvas = document.createElement('canvas');
document.body.appendChild(myCanvas);
var myConfetti = confetti.create(myCanvas, {
resize: true,
useWorker: true
});
myConfetti({
particleCount: 100,
spread: 160
});
Animasyonu durdurma ve örnek desenler
confetti.reset() animasyonu durdurur, tüm confetti’leri temizler ve bekleyen Promise’leri hemen resolve eder
confetti.create() ile oluşturulan ayrı instance’ın kendi reset metodu vardır
confetti();
setTimeout(() => {
confetti.reset();
}, 100);
- Temel çalıştırma, argümansız
confetti() çağırmaktır
particleCount: 150 ile çok sayıda confetti fırlatılabilir
spread: 180 ile geniş alana yayılan confetti oluşturulabilir
origin içinde Math.random() kullanıldığında sayfanın rastgele konumlarında küçük patlama efektleri oluşturulabilir
- README örneği,
requestAnimationFrame kullanarak 30 saniye boyunca sol ve sağ kenarlardan sürekli confetti fırlatan bir deseni gösterir
1 yorum
Hacker News yorumları
Burada performanslı animasyon yapmanın püf noktası, canvas’a çizip sonra o canvas’ı diğer tüm öğelerin önüne koymak, ama sayfayla etkileşime devam edilebilmesi için pointer events’i kapatmak
2015’te lisede web geliştirdiğim güzel günleri hatırlattı. Homecoming’e birlikte gitmeyi teklif etmek için bir kıza konfetili küçük bir web sitesi yapmıştım; şimdi dönüp bakınca aşırı nerd’ceymiş
O zamanlar bir çocuk için web sitesi yapmak süper güç gibi geliyordu. Zamanlama açısından bu paket değildi sanırım ama animasyon epey iyiydi
Böyle safça keyif veren küçük projeleri seviyorum. Programlamaya başlama nedenim de buydu, hâlâ da büyük bir motivasyon kaynağı
Demo sayfasındaki şu kısmı sevdim:
Bu tür detay takıntısı nadir; ister istatistik görselleştirmesi olsun, ister film aksesuarı, ister web sitesi konfeti efekti, karşıma çıktığında çok değerli geliyor
Çözüm olarak rastgele dağılımın kendisini değiştirmeyi denerdim. Gerçekten test ederdim ama gerçek hayattaki dağılımın Gauss dağılımına daha yakın olacağını tahmin ediyorum
Satış temsilcisi satışı kapattığında çıkan yönetici paneli konfeti efekti ekledik; beklenmedik şekilde eğlenceli ve motive edici oluyor
reset fonksiyonuna confetti.resetti() deseler iyi olurdu
"confetti.resetti = confetti.reset"ile basitçe düzeltebilirsinBu yaklaşımın biraz yazılım mühendisliği maliyeti olur elbette, ama dikkatli her gözlemcinin açıkça görebileceği gibi getirisi ezici biçimde büyük, o yüzden bence yapılmalı
Güzel ve kullanışlı bir kütüphane olmasının yanında, John Ousterhout’un Philosophy of Software Design’da bahsettiği derin modül için iyi bir örnek
En temel sürüm, yani konfeti çağırma işlevi çok kolay kullanılıyor; ama seçeneklere bakınca kar, belirli renkler, çeşitli konfeti efektleri gibi epey şey elde edilebiliyor
Güzel ve etkileyici
Aynı zamanda kullandığım hiçbir web sitesinde çalıştığını görmek istemem. Özellikle bülten popup’larında ya da sepete ürün eklerken peşinden konfeti gelmesini istemem
Garip şekilde bu efekt epey etkili kullanılabiliyor. Bu tam ekran yaklaşımından emin değilim ama yakın zamanda gittiğim bir müşterinin kullandığı proje yönetim yazılımında bir öğeyi kapatınca buton yeşile dönüyor ve böyle bir efekt ekleniyordu
İnceydi ama fark edilecek kadardı; toplantıdan sonra başka bir geliştiriciyle ikimiz de “epey iyi bir efektmiş” dedik. “Güzel, ilerleme var!” hissini veriyordu
Yeter ki isteğe bağlı yapılsın
Meşru kullanım yeri olarak YouTube’un beğen düğmesi gibi şeyler olabilir. Güzel bir animasyonu var, mobil uygulamada cihaz da titreşiyor. Çok hoş bir kullanıcı deneyimi
Tarayıcıda hareketi azaltma tercih edilebilir. Site sahipleri ve kütüphane bakımcıları konfeti gibi şeyler uygularken buna saygı duymalı. Bu kütüphanede özellikle
disableForReducedMotionseçeneği varBöyle efektlerin yakıştığı yerler var. Örneğin bir oyunu bitirmek gibi
Biz bu kütüphaneyi biri belirli bir yeterliliği karşıladığında kullanıyoruz. Onboarding akışına epey hoş bir etki katıyor
Party.js kütüphanesi de var: https://party.js.org/
O zaman hangisi daha küçük?
10.4 kB minify edilmiş, 4.2 kB minify + Gzip
https://bundlephobia.com/package/canvas-confetti@1.9.2
28.3 kB minify edilmiş, 7.4 kB minify + Gzip
https://bundlephobia.com/package/party-js@2.2.0
Ancak bundlephobia’nın nasıl çalıştığını pek bilmiyorum. Paketin nihai boyutunu en iyi şekilde göstermiyor olabilir. Muhtemelen code splitting ya da sadece gerekenleri import etme gibi yöntemleri hesaba katmıyordur. Bunu sadece hızlı ve kabaca bir genel bakış olarak görüyorum
Gzip’e göre confetti birkaç KB önde gibi; yani o birkaç KB’ı sıkıştırıp çıkarmak zorunda değilseniz, ihtiyacınız olan özelliklerin hangisinde olduğuna bağlı olarak ikisi de olur
Orijinal yazıdaki script mobilde çok daha performanslı görünüyor
Orijinal yazıdaki kütüphane çok daha performanslı görünüyor. Eski iş bilgisayarımda Party.js’e sadece 3 kez tıklayınca bile hafif gecikme hissediliyor
canvas-confetti’de ise birkaç saniye boyunca durmadan tıklayıp muhtemelen 30’dan fazla konfeti instance’ı ve çok sayıda parçacık oluşturduğumda gecikme başlamaya başlıyor
downforacross.com’da bulmaca çözüyorum; bulmacayı bitirince konfeti çıkıyor
Daha hafif hissettirmek için buradaki daha performanslı kodun bir kısmını kullanabilirler belki
Ama “eğlence” sitesi ya da nadir kullanım değilse, bu tür animasyonların her yerde çıkmasını görmek istemem
Başlığa useful kelimesini özellikle koymaya gerek olduğunu sanmıyorum