Canvas API ile çizim yapmak için sayfaya bir <canvas> elemanı koyar, JavaScript'te canvas.getContext("2d") ile bir CanvasRenderingContext2D nesnesi alır ve bu nesnenin yöntemleriyle dikdörtgen, yol, yay, metin çizersiniz. Koordinat sistemi sol üst köşede (0,0) noktasından başlar; x sağa, y aşağıya doğru artar. Renk, çizgi kalınlığı ve yazı tipi gibi ayarlar bağlamın (context) özellikleridir ve değiştirene kadar sonraki bütün çizimlere uygulanır.
Bu rehber MDN'nin canvas eğitimini temel alır: elemanın boyutu, bağlam türleri, dikdörtgenler, yollar ve yaylar, Path2D, renkler ve degradeler, çizgi stilleri, metin, save()/restore() ile durum yığını, dönüşümler ve bulanık kenar sorununu anlatır. Resim çizme, piksel okuma ve canvas'ı dosyaya çevirme konuları Canvas görsel ve piksel işlemleri yazısında; animasyon döngüsü requestAnimationFrame yazısında.
canvas elemanı ve boyutu
<canvas id="canvas" width="300" height="150">
Satış grafiği: ocakta 120, şubatta 180 adet.
</canvas><canvas> elemanının yalnızca iki özniteliği vardır: width ve height. İkisi de isteğe bağlıdır; verilmezse canvas başlangıçta 300 piksel genişliğinde ve 150 piksel yüksekliğinde olur. Elemanı CSS ile istediğiniz boyutta gösterebilirsiniz, ama çizim sırasında görüntü yerleşim boyutuna ölçeklenir. CSS boyutu canvas'ın kendi oranına uymuyorsa çizim bozuk görünür. MDN'nin önerisi bu yüzden açıktır: çiziminiz bozuk görünüyorsa boyutu CSS ile değil, width ve height öznitelikleriyle verin.
Elemanın içine yazdığınız içerik yedek (fallback) içeriktir. Canvas'ı desteklemeyen tarayıcılarda gösterilir, ekran okuyucular ve botlar tarafından okunur; destekleyen tarayıcılar ise bu içeriği yok sayar. Bu yüzden <img> elemanından farklı olarak kapanış etiketi zorunludur: </canvas> yazılmazsa belgenin geri kalanı yedek içerik sayılır ve görüntülenmez. Canvas yalnızca bir bit eşlemidir (bitmap); çizilen nesneler hakkında erişilebilirlik araçlarına bilgi vermez. MDN, canvas'ı resim gibi kullanmanızı ve önemli içeriği erişilebilir bir işaretleme olmadan yalnızca canvas'a çizmemenizi önerir; tamamen süs amaçlı bir canvas için role="presentation" kullanılabilir.
Bağlamı almak: getContext()
const canvas = document.getElementById("canvas");
if (canvas.getContext) {
const ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(10, 10, 150, 100);
} else {
// canvas desteklenmiyor
}getContext() ilk parametre olarak bağlam türünü alır. "2d" iki boyutlu çizim bağlamını, "webgl" ve "webgl2" WebGL bağlamlarını, "webgpu" WebGPU bağlamını, "bitmaprenderer" ise yalnızca bir ImageBitmap ile içeriği değiştirebilen bağlamı döndürür. Aynı canvas'ta aynı türle tekrar çağırırsanız her zaman aynı bağlam nesnesini alırsınız. Desteklenmeyen bir tür istenirse ya da canvas zaten başka bir türe ayarlanmışsa null döner; canvas denetimi transferControlToOffscreen() ile devredilmişse InvalidStateError fırlatılır.
İkinci parametre bağlam ayarlarıdır. 2d için önemli olanlar: alpha: false canvas'ın saydam olmadığını bildirir ve tarayıcının çizimi hızlandırmasına yardım eder; willReadFrequently: true sık getImageData() okuması yapacağınızı bildirir ve MDN'ye göre yazılımsal (donanım hızlandırmasız) bir canvas kullanılmasını sağlayarak bellekten tasarruf ettirebilir; colorSpace ise "srgb" (varsayılan) veya "display-p3" renk uzayını seçer.
Dikdörtgenler: anında çizen üç yöntem

SVG'den farklı olarak canvas yalnızca iki temel şekli doğrudan destekler: dikdörtgenler ve yollar. Dikdörtgen için üç yöntem vardır ve hepsi aynı parametreleri alır: sol üst köşe (x, y), ardından width ve height.
| Yöntem | Ne yapar |
|---|---|
| fillRect(x, y, w, h) | Dolu dikdörtgen çizer |
| strokeRect(x, y, w, h) | Dikdörtgenin dış çizgisini çizer |
| clearRect(x, y, w, h) | Alanı tamamen saydam yapar (siler) |
const ctx = document.getElementById("canvas").getContext("2d");
ctx.fillRect(25, 25, 100, 100); // 100x100 siyah kare
ctx.clearRect(45, 45, 60, 60); // ortadan 60x60 alan sil
ctx.strokeRect(50, 50, 50, 50); // silinen alanın içine çerçeveBu üç yöntem, birazdan göreceğiniz yol fonksiyonlarından farklı olarak canvas'a hemen çizer. Bir de rect(x, y, w, h) vardır; o ise çizim yapmaz, açık olan yola bir dikdörtgen ekler ve kalem konumunu (x, y) noktasına taşır.
Yollar: beginPath, moveTo, lineTo, fill, stroke
Yol, çizgi parçalarıyla birbirine bağlanmış noktaların listesidir. Bir yolla şekil çizmenin adımları şunlardır: beginPath() ile yeni yol başlatırsınız, çizim komutlarıyla yolu kurarsınız, sonra stroke() ile dış çizgisini ya da fill() ile içini boyarsınız. closePath() isteğe bağlıdır ve geçerli noktadan alt yolun başına düz bir çizgi ekler.
const ctx = document.getElementById("canvas").getContext("2d");
// Dolu üçgen
ctx.beginPath();
ctx.moveTo(25, 25);
ctx.lineTo(105, 25);
ctx.lineTo(25, 105);
ctx.fill();
// Çizgili üçgen
ctx.beginPath();
ctx.moveTo(125, 125);
ctx.lineTo(125, 45);
ctx.lineTo(45, 125);
ctx.closePath();
ctx.stroke();İki üçgen arasındaki fark MDN'nin vurguladığı kurala dayanır: fill() açık şekilleri otomatik kapatır, stroke() kapatmaz. İkinci üçgende closePath() olmasaydı yalnızca iki kenar çizilirdi. Bir diğer önemli kural: yol boşken, örneğin beginPath() çağrısının hemen ardından, ilk yol komutu ne olursa olsun moveTo() gibi davranır. Bu yüzden yeni bir yola başladıktan sonra başlangıç noktasını açıkça moveTo() ile vermek neredeyse her zaman doğru tercihtir.
beginPath() çağırmayı unutmak en yaygın hatalardan biridir. Yol iç tarafta alt yolların listesi olarak tutulur ve her beginPath() bu listeyi sıfırlar. Çağırmazsanız yeni şekil önceki yola eklenir ve sonraki stroke() eski şekilleri de yeniden çizer.
Yaylar ve daireler: arc()
arc(x, y, radius, startAngle, endAngle, counterclockwise) merkezi (x, y) olan bir yay çizer. Açılar x ekseninden ölçülür ve derece değil radyan cinsindendir; son parametre true ise yay saat yönünün tersine çizilir, verilmezse saat yönündedir. Tam daire için başlangıç 0, bitiş Math.PI * 2 olur. MDN'nin dönüşüm formülü (Math.PI / 180) * derece şeklindedir; aşağıdaki küçük fonksiyon Node.js ile çalıştırıldı:
const derece = (d) => (Math.PI / 180) * d;
console.log(derece(180) === Math.PI); // true
console.log(derece(90).toFixed(4)); // 1.5708
console.log(derece(25).toFixed(4)); // 0.4363MDN'nin gülen yüz örneği tek bir yol içinde birkaç yay çizer ve aralarda moveTo() ile kalemi kaldırır; böylece yaylar arasında bağlantı çizgisi oluşmaz:
ctx.beginPath();
ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // dış daire
ctx.moveTo(110, 75);
ctx.arc(75, 75, 35, 0, Math.PI, false); // ağız
ctx.moveTo(65, 65);
ctx.arc(60, 65, 5, 0, Math.PI * 2, true); // sol göz
ctx.moveTo(95, 65);
ctx.arc(90, 65, 5, 0, Math.PI * 2, true); // sağ göz
ctx.stroke();Eğriler için quadraticCurveTo(cp1x, cp1y, x, y) tek kontrol noktalı, bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) iki kontrol noktalı Bézier eğrisi çizer. Köşeleri yuvarlatılmış dikdörtgen için roundRect(x, y, width, height, radii) vardır; radii CSS border-radius gibi bir sayı ya da bir ila dört değerli bir dizi olabilir. Dizi boşsa, dörtten fazla eleman içeriyorsa veya negatif değer varsa RangeError fırlatılır. roundRect() de yalnızca yola ekler; görmek için fill() veya stroke() çağırmanız gerekir.
Path2D ile yolları saklamak
Aynı şekli tekrar tekrar çiziyorsanız Path2D nesnesi komutları kaydetmenizi sağlar. moveTo, rect, arc gibi bütün yol yöntemleri Path2D üzerinde de vardır ve fill(path), stroke(path) yöntemleri yolu parametre olarak kabul eder. Yapıcı bir SVG yol verisi metni de alabilir:
const kare = new Path2D();
kare.rect(10, 10, 50, 50);
const daire = new Path2D();
daire.arc(100, 35, 25, 0, 2 * Math.PI);
ctx.stroke(kare);
ctx.fill(daire);
const svgYolu = new Path2D("M10 10 h 80 v 80 h -80 Z");Bir noktanın yolun içinde olup olmadığını isPointInPath(path, x, y) ile test edebilirsiniz; MDN'nin örneği fare bir dairesel Path2D üzerine gelince daireyi yeşile boyar. Bu, canvas üzerinde tıklanabilir alanlar oluşturmanın temel yoludur; fare olaylarının kendisi Pointer Events yazısında anlatılıyor.
Renkler, saydamlık ve degradeler
fillStyle dolgu, strokeStyle çizgi rengini belirler. Değerler CSS renk değerleridir: "orange", "#FFA500" ve "rgb(255 165 0)" aynı rengi verir. MDN'nin hatırlattığı gibi atadığınız değer, siz değiştirene kadar sonraki bütün şekillerde kullanılır. Saydamlık için ya rengin kendisinde alfa kullanırsınız ("rgb(255 0 0 / 50%)") ya da globalAlpha özelliğine 0.0 ile 1.0 arası bir değer verirsiniz; globalAlpha sonraki bütün şekilleri etkiler.
const degrade = ctx.createLinearGradient(0, 0, 0, 150);
degrade.addColorStop(0, "#00ABEB");
degrade.addColorStop(1, "white");
ctx.fillStyle = degrade;
ctx.fillRect(10, 10, 130, 130);Doğrusal degrade için createLinearGradient(x1, y1, x2, y2), dairesel için createRadialGradient(x1, y1, r1, x2, y2, r2), konik için createConicGradient(angle, x, y) kullanılır. Dönen CanvasGradient nesnesine addColorStop(konum, renk) ile 0.0 ile 1.0 arası konumlarda renk durakları eklenir ve nesne fillStyle veya strokeStyle değerine atanır. Desen için createPattern(resim, "repeat") vardır; MDN, drawImage()'de olduğu gibi resmin önceden yüklenmiş olması gerektiğini hatırlatır.
Çizgi stilleri

| Özellik | Değerler | Varsayılan |
|---|---|---|
| lineWidth | Pozitif sayı | 1.0 |
| lineCap | butt, round, square | butt |
| lineJoin | round, bevel, miter | miter |
| miterLimit | Sayı | 10.0 |
| setLineDash(dizi) | Çizgi ve boşluk uzunlukları | Düz çizgi |
| lineDashOffset | Desenin başlangıç kayması | 0 |
Çizgi kalınlığı yolun ortasına yerleşir; yani çizgi yolun iki yanına yarım kalınlık kadar taşar. lineCap yalnızca yolun başlangıç ve bitiş uçlarını etkiler; closePath() ile kapatılmış bir yolda uç yoktur ve köşeler lineJoin ayarıyla birleşir.
Bulanık kenarlar ve keskin çizgiler
Canvas koordinatları pikselin kendisini değil, iki piksel arasındaki sınırı gösterir. MDN'nin örneğinde strokeRect(50, 50, 50, 50) kavramsal olarak 50x50'dir ama 1 birimlik çizgi sınırın iki yanına yarım piksel taştığı için kenarlar yarı yarıya boyanmış piksellere düşer; sonuçta 2 piksel kalınlığında, siyah yerine gri görünen ve gerçekte 52x52 alan kaplayan bir çerçeve oluşur. Tek piksellik keskin bir çizgi için yolu piksel merkezlerinden geçirmelisiniz: 1 birimlik dikey çizgiyi x = 3 yerine x = 3.5 üzerinde çizmek gibi. Çift kalınlıktaki çizgilerde ise yol pikseller arasındaki sınırdan geçmelidir.
Yüksek çözünürlüklü ekranlarda bulanıklığın bir sebebi de CSS pikselinin birden çok fiziksel piksele denk gelmesidir. MDN'nin optimizasyon sayfası şu çözümü gösterir: canvas'ın gerçek boyutunu devicePixelRatio ile çarpın, bağlamı aynı oranla ölçekleyin ve CSS boyutunu eski değerde bırakın:
const dpr = window.devicePixelRatio;
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
ctx.scale(dpr, dpr);
canvas.style.width = `${rect.width}px`;
canvas.style.height = `${rect.height}px`;Boyut atamanın bağlamı sıfırladığını unutmayın; bu kod stil ayarlarından önce çalışmalıdır. Kap boyutu değiştikçe bu işlemi yeniden yapmak için ResizeObserver kullanılabilir.
Metin çizmek
fillText(metin, x, y [, maxWidth]) metni fillStyle ile doldurur, strokeText() dış çizgisini çizer. font özelliği CSS font söz dizimini kullanır ve varsayılan değeri 10px sans-serif değeridir. textAlign (start, end, left, right, center; varsayılan start) yatay hizayı, textBaseline (varsayılan alphabetic) dikey taban çizgisini belirler. measureText() geçerli stille çizilecek metnin genişliğini içeren bir TextMetrics nesnesi döndürür.
ctx.font = "48px serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Merhaba", canvas.width / 2, canvas.height / 2);
const genislik = ctx.measureText("Merhaba").width; // geçerli font ile piksel genişliğiCanvas'a çizilen metin pikseldir; MDN, ekran büyütme kullanan kişiler için okunabilirlik sorunu çıkarabileceğini ve yakınlaştırıldığında bulanıklaşacağını belirtir. Önemli metni HTML olarak vermek daha erişilebilirdir.
Durum yığını: save() ve restore()
save() çizim durumunun tamamını bir yığına iter, restore() en son kaydedileni geri yükler. Durum; uygulanmış dönüşümleri, strokeStyle, fillStyle, globalAlpha, lineWidth, gölge ayarları, font, textAlign, textBaseline gibi özellikleri ve geçerli kırpma yolunu içerir. save() istediğiniz kadar çağrılabilir; her restore() yığının en üstündeki durumu alır.
ctx.fillRect(0, 0, 150, 150); // varsayılan siyah
ctx.save(); // durum 1
ctx.fillStyle = "#0099ff";
ctx.fillRect(15, 15, 120, 120); // mavi
ctx.save(); // durum 2
ctx.fillStyle = "white";
ctx.globalAlpha = 0.5;
ctx.fillRect(30, 30, 90, 90); // yarı saydam beyaz
ctx.restore(); // durum 2: mavi
ctx.fillRect(45, 45, 60, 60);
ctx.restore(); // durum 1: siyah
ctx.fillRect(60, 60, 30, 30);Dönüşümler: translate, rotate, scale
translate(x, y) başlangıç noktasını taşır, rotate(açı) ızgarayı başlangıç noktası etrafında saat yönünde radyan cinsinden döndürür, scale(x, y) birimleri büyütür veya küçültür. Döndürme merkezi her zaman başlangıç noktasıdır; bir şekli kendi merkezi etrafında döndürmek için önce merkeze taşır, döndürür, sonra geri taşırsınız:
ctx.translate(200, 80); // dikdörtgenin merkezine git
ctx.rotate((Math.PI / 180) * 25); // 25 derece döndür
ctx.translate(-200, -80); // geri taşı
ctx.fillRect(150, 30, 100, 100);MDN dönüşümlerden önce durumu kaydetmeyi önerir; ters dönüşüm yazmaktansa restore() çağırmak çoğu zaman daha kolaydır ve döngü içinde kaydetmeden taşıma yaparsanız çiziminizin bir kısmı canvas'ın dışına düşebilir. Negatif ölçekle eksen aynalanır; translate(0, canvas.height); scale(1, -1); başlangıcı sol alta alan Kartezyen sistemi verir. Dönüşüm matrisini doğrudan transform(), setTransform() ile değiştirebilir, resetTransform() ile birim matrise dönebilirsiniz.
Sık yapılan hatalar

- Boyutu yalnızca CSS ile vermek. Çizim ölçeklenir ve oran bozulursa çarpık görünür;
width/heightözniteliklerini kullanın. beginPath()çağırmamak. Yeni şekil eski yola eklenir ve önceki şekiller tekrar boyanır.- Açıları derece vermek.
arc()verotate()radyan bekler. stroke()ile kapalı şekil beklemek. Kapanış içinclosePath()gerekir;fill()otomatik kapatır.- Boyut değiştirdikten sonra stilleri yeniden ayarlamamak. Boyut ataması bağlamı sıfırlar.
- Kapanış etiketini unutmak.
</canvas>yoksa sayfanın geri kalanı yedek içerik olur.
Sık Sorulan Sorular
Canvas mı SVG mi kullanmalıyım?
Canvas bir bit eşlemidir; çizdiğiniz şekiller sonradan ayrı nesneler olarak kalmaz, değiştirmek için yeniden çizersiniz. Bu yüzden çok sayıda nesnenin her karede yeniden çizildiği oyunlar, görselleştirmeler ve piksel işleme için uygundur. MDN, canvas içeriğinin erişilebilirlik araçlarına anlamsal HTML gibi açılmadığını belirtir; tek tek seçilebilir ve erişilebilir olması gereken şekiller için bu fark önemlidir.
Canvas içeriğini nasıl temizlerim?
Tamamını silmek için ctx.clearRect(0, 0, canvas.width, canvas.height) kullanın. MDN'nin optimizasyon sayfası temizlemenin farklı yollarını (clearRect(), fillRect() veya canvas'ı yeniden boyutlandırmak) denemeyi önerir; boyutlandırmanın bütün bağlam ayarlarını da sıfırladığını unutmayın.
Kütüphane kullanmalı mıyım?
MDN, Canvas API'nin güçlü ama her zaman kolay olmadığını belirtir ve Fabric.js, Konva.js, p5.js, Phaser gibi kütüphaneleri listeler. Temel yöntemleri öğrenmek, bu kütüphanelerin arkasında ne olduğunu anlamanızı sağlar.
3D çizim yapabilir miyim?
2d bağlamı iki boyutludur. Aynı <canvas> elemanı getContext("webgl"), "webgl2" veya "webgpu" ile donanım hızlandırmalı 2D ve 3D çizim için de kullanılabilir; bu API'ler ayrı bir konudur.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Web API öğrenme rehberi · Canvas görsel ve piksel işlemleri · requestAnimationFrame · ResizeObserver · Pointer Events · HTML öğrenme rehberi