Bu her zaman sizsiniz, Canvas2D

Harun Krajeski
Aaron Krajeski

Gölgelendiriciler, örgüler ve filtreler dünyasında Canvas2D sizi heyecanlandırmayabilir. Ama doğrudur. Web sayfalarının% 30-40'ında <canvas> öğesi bulunur ve tüm tuvallerin% 98'inde Canvas2D oluşturma bağlamı kullanılır. Arabalarda, buzdolabında ve uzayda (gerçekten) Canvas2D'ler vardır.

Son teknoloji 2D çizimler söz konusu olduğunda API'nin biraz geride kaldığını belirtmek isteriz. Neyse ki Canvas2D'de yeni özellikleri uygulamak, CSS'ye ayak uydurmak, ergonomik kullanımı kolaylaştırmak ve performansı artırmak için yoğun şekilde çalışıyoruz.

1. Bölüm: CSS'ye ayak uydurma

CSS'nin Canvas2D'de bulunmayan birkaç çizim komutu var. Yeni API ile en çok istenen birkaç özelliği ekledik:

Yuvarlak dikdörtgen

Yuvarlatılmış dikdörtgenler: İnternet'in, bilgi işlemin, neredeyse medeniyetin temel taşı.

Her bakımdan, yuvarlatılmış dikdörtgenler son derece yararlıdır: Düğmeler, sohbet balonları, küçük resimler, konuşma balonları gibi. Canvas2D'de yuvarlak bir dikdörtgen oluşturmak her zaman mümkün olmuştur. Bu yüzden biraz karışık oluyordu:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'magenta';

const top = 10;
const left = 10;
const width = 200;
const height = 100;
const radius = 20;

ctx.beginPath();
ctx.moveTo(left + radius, top);
ctx.lineTo(left + width - radius, top);
ctx.arcTo(left + width, top, left + width, top + radius, radius);
ctx.lineTo(left + width, top + height - radius);
ctx.arcTo(left + width, top + height, left + width - radius, top + height, radius);
ctx.lineTo(left + radius, top + height);
ctx.arcTo(left, top + height, left, top + height - radius, radius);
ctx.lineTo(left, top + radius);
ctx.arcTo(left, top, left + radius, top, radius);
ctx.stroke();

Mütevazı, basit bir yuvarlak dikdörtgen için tüm bunlar gerekliydi:

Yuvarlatılmış dikdörtgen.

Yeni API ile roundRect() yöntemi kullanılabilir.

ctx.roundRect(upper, left, width, height, borderRadius);

Dolayısıyla yukarıdakiler tamamen şununla değiştirilebilir:

ctx.roundRect(10, 10, 200, 100, 20);

ctx.roundRect() yöntemi ayrıca en fazla dört sayılık borderRadius bağımsız değişkeni için bir dizi alır. Bu yarıçaplar, yuvarlatılmış dikdörtgenin dört köşesini CSS'de olduğu gibi kontrol eder. Örneğin:

ctx.roundRect(10, 10, 200, 100, [15, 50, 30]);

Demoya göz atın!

Konik Gradyan

Çizgisel renk geçişleri gördünüz:

const gradient = ctx.createLinearGradient(0, 0, 200, 100);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.5, 'magenta');
gradient.addColorStop(1, 'white');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);

Çizgisel gradyan.

Dairesel renk geçişleri:

const radialGradient = ctx.createRadialGradient(150, 75, 10, 150, 75, 70);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(0.5, 'magenta');
radialGradient.addColorStop(1, 'lightblue');

ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);

Dairesel renk geçişi.

Peki ama güzel bir konik gradyana ne dersiniz?

const grad = ctx.createConicGradient(0, 100, 100);

grad.addColorStop(0, 'red');
grad.addColorStop(0.25, 'orange');
grad.addColorStop(0.5, 'yellow');
grad.addColorStop(0.75, 'green');
grad.addColorStop(1, 'blue');

ctx.fillStyle = grad;
ctx.fillRect(0, 0, 200, 200);

Konik gradyan.

Metin değiştiriciler

Canvas2D'nin metin oluşturma özelliklerinin çok gerisinde kaldı. Chrome, Canvas2D metin oluşturmaya birkaç yeni özellik ekledi:

Bu özelliklerin tümü, aynı ada sahip CSS eşdeğerleriyle eşleşir.

2. bölüm: ergonomik ince ayarlar

Önceden, Canvas2D ile bazı şeyler mümkün olsa da uygulanması gereksiz derecede karmaşıktı. Burada, Canvas2D'yi kullanmak isteyen JavaScript geliştiricileri için bazı yaşam kalitesi iyileştirmelerini görebilirsiniz:

Bağlam sıfırlandı

Bir tuvalin nasıl temizlendiğini açıklamak üzere, retro deseni çizecek şekilde küçük bir işlevimiz var:

draw90sPattern();

Retro üçgen ve kare deseni.

İsteğinizi aldık. Bu desenle işim bittiğinde, kanvası temizlemek ve başka bir şey çizmek istiyorum. Bir kanvas tekrar nasıl temizlenir? İşte bu! Tabii ki ctx.clearRect().

ctx.clearRect(0, 0, canvas.width, canvas.height);

Ne de olsa işe yaramadı. İşte bu! Önce dönüşümü sıfırlamam gerekiyor:

ctx.resetTransform();
ctx.clearRect(0, 0, canvas.width, canvas.height);
Boş bir tuval.

Mükemmel! Güzel bir boş tuval. Şimdi güzel bir yatay çizgi çizmeye başlayalım:

ctx.moveTo(10, 10);
ctx.lineTo(canvas.width, 10);
ctx.stroke();

Yatay ve çapraz çizgi.

Hırrrr! Doğru değil! 😡 O ekstra çizginin burada ne işi var? Bir de neden pembe? Tamam, şimdi StackOverflow'u kontrol edelim.

canvas.width = canvas.width;

Neden bu kadar gülünç? Neden bu kadar zor?

Ama artık durum yok. Yeni API'de çığır açıcı, sade ve şık bir tasarım var:

ctx.reset();

Bu işlem uzun sürdüğü için özür dileriz.

Filtreler

SVG filtreleri başlı başına ayrı bir dünyadır. Bu ekip sizi yeni kullanmaya başladıysa, muhteşem potansiyellerinden bazılarını gösteren The Art Of SVG Filtreler And Why It Is Awesome (SVG Sanatı Filtreleri ve Neden Başarılı Olunur?) adlı makaleyi okumanızı kesinlikle öneririm.

SVG stili filtreler Canvas2D için zaten kullanılabilir. Filtreyi, sayfadaki başka bir SVG filtre öğesine işaret eden URL olarak iletmeye istekli olmanız gerekir:

<svg>
  <defs>
    <filter id="svgFilter">
      <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
      <feConvolveMatrix kernelMatrix="-3 0 0 0 0.5 0 0 0 3" />
      <feColorMatrix type="hueRotate" values="90" />
    </filter>
  </defs>
</svg>
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 400;
const ctx = canvas.getContext('2d');
document.body.appendChild(canvas);

ctx.filter = "url('#svgFilter')";
draw90sPattern(ctx);

Bu da kalıbımızı bayağı bozuyor.

Bulanık efekt uygulanmış retro desen.

Ancak, yukarıdakileri yapmak ancak JavaScript'te kalmak ve dizelerle uğraşmak istememek isterseniz ne yapabilirsiniz? Yeni API ile bu tamamen mümkün.

ctx.filter = new CanvasFilter([
  { filter: 'gaussianBlur', stdDeviation: 5 },
  {
    filter: 'convolveMatrix',
    kernelMatrix: [
      [-3, 0, 0],
      [0, 0.5, 0],
      [0, 0, 3],
    ],
  },
  { filter: 'colorMatrix', type: 'hueRotate', values: 90 },
]);

Çok kolay! Deneyin ve buradaki demoda yer alan parametrelerle oynayın.

3. Bölüm: Performans iyileştirmeleri

Yeni Canvas2D API ile mümkün olduğunda performansı artırmak da istedik. Geliştiricilerin web siteleri üzerinde daha ayrıntılı bir kontrole sahip olmasını sağlamak ve mümkün olan en hassas kare hızlarını sağlamak için birkaç özellik ekledik:

Sık okuyacakım

Piksel verilerini kanvastan geri okumak için getImageData() uygulamasını kullanın. Çok yavaş olabilir. Yeni API, okuma amacıyla bir kanvası açıkça işaretlemenin bir yolunu sunar (örneğin, oluşturma efektler için). Bu sayede, gelişmiş özellikleri optimize edebilir ve daha çeşitli kullanım alanları için kanvasın hızlı olmasını sağlayabilirsiniz. Bu özellik bir süredir Firefox'taydı ve nihayet tuval spesifikasyonunun bir parçası haline getiriyoruz.

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });

Bağlam kaybı

Üzgün sekmeleri tekrar mutlu edelim! Bir istemcinin GPU belleğinin tükenmesi veya tuvalinize başka bir felaketin düşmesi durumunda artık geri arama alabilir ve gerektiğinde yeniden çizim yapabilirsiniz:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

canvas.addEventListener('contextlost', onContextLost);
canvas.addEventListener('contextrestored', redraw);

Tuval bağlamı ve kaybı hakkında daha fazla bilgi edinmek istiyorsanız WhatsApp'ın wiki'sinde iyi bir açıklaması bulunmaktadır.

Sonuç

Canvas2D'yi kullanmaya yeni başlamış, yıllardır kullanıyor veya yıllardır kullanmaktan kaçınmış olun, kanvasa başka bir görünüm kazandırmak için size yardımcı olmaya hazırız. Bu, en başından beri API'nin anahtarıydı.

Teşekkür

Unsplash'teki Sandie Clarke'ın lokomotif resmi.