Bu her zaman sizsiniz, Canvas2D

Aaron Krajeski
Aaron Krajeski

Gölgelendiriciler, ağlar ve filtreler dünyasında Canvas2D sizi heyecanlandırmayabilir. Ancak bu şekilde olmalıdır. Web sayfalarının% 30-40'ında bir <canvas> öğesi bulunur ve tüm kanvasların% 98'inde Canvas2D oluşturma bağlamı kullanılır. Canvas2D'ler arabalarda, buzdolaplarında ve uzaydaki cihazlarda (evet, gerçekten) bulunur.

API'nin, en son teknoloji 2D çizim konusunda biraz geride olduğu kabul edilmelidir. Neyse ki CSS'ye yetişmek, ergonomiyi kolaylaştırmak ve performansı artırmak için Canvas2D'de yeni özellikler uygulamak üzere yoğun bir şekilde çalışıyoruz.

1. Bölüm: CSS'yi yakalama

CSS'de, Canvas2D'de eksik olan birkaç çizim komutu vardır. Yeni API ile en çok istenen özelliklerden birkaçını ekledik:

Yuvarlak dikdörtgen

Köşeleri yuvarlatılmış dikdörtgenler: internetin, bilgisayarcılığın ve hatta uygarlığın temel taşı.

Yuvarlatılmış dikdörtgenler, düğme, sohbet balonu, küçük resim, konuşma balonu gibi pek çok alanda son derece kullanışlıdır. Canvas2D'de yuvarlatılmış dikdörtgen oluşturmak her zaman mümkündü, ancak bu işlem biraz karmaşıktı:

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();

Bunların hepsi, daha küçük boyutlu, basit ve yuvarlak bir dikdörtgen için gerekliydi:

Yuvarlak bir dikdörtgen.

Yeni API'de roundRect() yöntemi vardır.

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

Bu nedenle, yukarıdaki kod tamamen şu şekilde değiştirilebilir:

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

ctx.roundRect() yöntemi ayrıca en fazla dört sayıya sahip 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);

Doğrusal 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 güzel bir konik gradyan nasıl olur?

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 özellikleri çok geride kaldı. Chrome, Canvas2D metin oluşturmaya birkaç yeni özellik ekledi:

Bu özelliklerin tümü, aynı ada sahip CSS karşılıklarıyla eşleşir.

2. Bölüm: ergonomik düzenlemeler

Daha önce Canvas2D ile bazı özelliklerin kullanılması mümkündü ancak bu özelliklerin uygulanması fazlasıyla karmaşıktı. Canvas2D kullanmak isteyen JavaScript geliştiricileri için bazı yaşam kalitesi iyileştirmeleri aşağıda verilmiştir:

Bağlam sıfırlama

Bir kanvası temizlemeyi açıklamak için retro desen çizen küçük ve saçma bir işlev yazdım:

draw90sPattern();

Üçgen ve karelerden oluşan retro bir desen.

Mükemmel! Bu deseni tamamladığıma göre tuvali temizleyip başka bir şey çizmek istiyorum. Bir tuvali tekrar nasıl temizleyeceğiz? İşte bu! ctx.clearRect(), elbette.

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

Bu işlem çalışmadı. Evet. Öncelikle dönüşümü sıfırlamamız gerekiyor:

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

Mükemmel! Güzel, boş bir 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! Bu doğru değil. 😡 O fazladan hattın burada anlamı nedir? Ayrıca, neden pembe? Tamam, StackOverflow'u kontrol edelim.

canvas.width = canvas.width;

Bu neden çok saçma? Bu neden bu kadar zor?

Ama artık değil. Yeni API ile basit, zarif ve güzel bir yeniliğe kavuştuk:

ctx.reset();

Bu kadar uzun sürdüğü için özür dilerim.

Filtreler

SVG filtreleri başlı başına bir dünyadır. SVG filtreleri sizin için yeniyse SVG Filtrelerinin Sanatı ve Neden Muhteşem Olduğu başlıklı makaleyi okumanızı öneririz. Bu makalede, SVG filtrelerinin şaşırtıcı potansiyelinden bazıları gösterilmektedir.

SVG stil filtreleri Canvas2D için kullanıma sunuldu. Filtreyi, sayfadaki başka bir SVG filtresi öğesine işaret eden bir URL olarak iletmeniz yeterlidir:

<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 modelimizi iyice karıştırıyor:

Bulanıklaştırılmış efekt uygulanmış retro desen.

Ancak yukarıdakileri yapmak istiyorsanız ancak JavaScript'te kalmak ve dizelerle uğraşmak istemiyorsanız ne olur? Yeni API ile bu tamamen mümkündür.

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 },
]);

Bu kadar kolay. Bu demoda parametrelerle oynayarak deneyebilirsiniz.

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

Yeni Canvas2D API ile mümkün olduğunda performansı da artırmak istedik. Geliştiricilerin web siteleri üzerinde daha ayrıntılı kontrol sahibi olması ve mümkün olan en yüksek kare hızlarını elde etmesi için birkaç özellik ekledik:

Sık sık okuyacak

Bir kanvastaki piksel verilerini geri okumak için getImageData() işlevini kullanın. Çok yavaş olabilir. Yeni API, bir kanvası tekrar okumak için açıkça işaretlemenize olanak tanır (ör. üretken efektler için). Bu sayede, arka planda optimizasyon yapabilir ve kanvası daha fazla kullanım alanı için hızlı tutabilirsiniz. Bir süredir Firefox'ta bulunan bu özelliği artık kanvas 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ği tükenirse veya tuvalinizde başka bir felaket meydana gelirse artık geri arama alabilir ve gerektiği gibi yeniden çizebilirsiniz:

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

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

Kanvas bağlamı ve kaybı hakkında daha fazla bilgi edinmek isterseniz WhatWG'nin wiki'sinde iyi bir açıklaması vardır.

Sonuç

Canvas2D'yi kullanmaya yeni başlayanlar, yıllardır kullanıyor veya yıllardır kullanmaktan kaçınıyor olabilirsiniz. Her durumda tuvale yeniden bir görünüm kazandırmanızı istiyorum. O da hep yanımızda olan API'dir.