Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce bilgisayarınızda Node.js'in güncel bir sürümünün (LTS) kurulu olması gerekmektedir. React projesi oluşturmak için Vite kullanmanızı öneriyoruz, çünkü hem hızlıdır hem de modern geliştirme standartlarıyla tam uyumludur.
- Node.js (v20 veya üzeri)
- React (v19 veya üzeri)
- Temel JavaScript ve DOM bilgisi
- Bir kod editörü (VS Code tercih edilir)
İlk adım olarak terminalinize şu komutu yazarak projenizi oluşturun:
npm create vite@latest cizim-tahtasi -- --template react
cd cizim-tahtasi
npm install
npm run dev
Bu komutlar, projenizin temel iskeletini kuracak ve geliştirme sunucusunu başlatacaktır. Artık kodlamaya başlamaya hazırsınız.
React İçinde Canvas Bileşenini Oluşturma
React'te Canvas kullanırken en önemli nokta, Canvas elemanına doğrudan erişim sağlamaktır. Bunun için useRef kancasını kullanırız. useRef, bileşen yaşam döngüsü boyunca değişmeyen bir referans tutmamızı sağlar.
import { useRef, useEffect } from 'react';
const CizimTahtasi = () => {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const context = canvas.getContext('2d');
context.fillStyle = '#ffffff';
context.fillRect(0, 0, canvas.width, canvas.height);
}, []);
return ;
};
Burada canvasRef değişkeni ile DOM'daki canvas elementine ulaşıyoruz. useEffect içerisinde getContext('2d') metodunu çağırarak çizim yapabileceğimiz 2D bağlamı elde ediyoruz.
Fare Olayları ile Çizim Mantığını Kurma
İnteraktif bir tahta için farenin hareketlerini takip etmeliyiz. Bunun için onMouseDown, onMouseMove ve onMouseUp olaylarını kullanacağız. Çizim durumunu yönetmek için isDrawing adında bir durum değişkeni tanımlamamız gerekir.
import { useState, useRef } from 'react';
const CizimTahtasi = () => {
const [isDrawing, setIsDrawing] = useState(false);
const canvasRef = useRef(null);
const startDrawing = (e) => {
setIsDrawing(true);
draw(e);
};
const stopDrawing = () => setIsDrawing(false);
const draw = (e) => {
if (!isDrawing) return;
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
ctx.lineTo(e.nativeEvent.offsetX, e.nativeEvent.offsetY);
ctx.stroke();
};
return (
);
};
Bu kod bloğunda, farenin her hareketinde lineTo ve stroke metodlarını kullanarak çizgi oluşturuyoruz. nativeEvent.offsetX ve offsetY, farenin canvas üzerindeki koordinatlarını verir.
Çizim Özelliklerini Özelleştirme
Kullanıcıların fırça kalınlığını veya rengini değiştirmesini sağlamak, uygulamanızı profesyonel bir seviyeye taşır. State yönetimi ile bu değerleri dinamik olarak Canvas'a aktarabiliriz.
const [color, setColor] = useState('#000000');
const [lineWidth, setLineWidth] = useState(5);
// Çizim fonksiyonunun içinde:
const ctx = canvasRef.current.getContext('2d');
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
lineCap = 'round' özelliği, çizgilerin daha yumuşak ve pürüzsüz görünmesini sağlar. Bu, özellikle serbest el çizimlerinde daha doğal bir sonuç verir.
Performans ve Optimizasyon İpuçları
Canvas API ile çalışırken performans, özellikle karmaşık çizimlerde kritik bir sorundur. Çizim sırasında gereksiz yeniden render işlemlerinden kaçınmalısınız.
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Doğrudan DOM Manipülasyonu | Çok hızlı | React state ile senkronize etmek zor |
| React State ile Çizim | Kolay yönetim | Performans kaybı yaşatabilir |
Güvenlik Uyarısı: Canvas verilerini sunucuya gönderirken XSS (Cross-Site Scripting) riskine karşı dikkatli olun. Kullanıcıdan gelen görsel verileri doğrudan HTML içinde render etmeyin; her zaman sunucu tarafında doğrulama yapın.
Sıkça Sorulan Sorular
Canvas çizimlerini nasıl kaydedebilirim?
canvasRef.current.toDataURL('image/png') metodunu kullanarak çizimi bir Base64 string'ine dönüştürebilir ve bir link etiketi ile indirilmesini sağlayabilirsiniz.
Mobil cihazlarda çizim yapabilir miyim?
Evet, onTouchStart, onTouchMove ve onTouchEnd olaylarını dinleyerek dokunmatik ekran desteği ekleyebilirsiniz.
Çizim tahtasını nasıl temizlerim?
ctx.clearRect(0, 0, canvas.width, canvas.height) komutu ile canvas üzerindeki tüm pikselleri silebilirsiniz.
Neden çizgiler kesik kesik görünüyor?
beginPath() ve moveTo() metodlarını her yeni çizgi başlangıcında doğru çağırmadığınızda bu sorun oluşabilir. Her tıklamada yeni bir yol başlattığınızdan emin olun.
React.StrictMode neden çizimi iki kez tetikliyor?
Geliştirme modunda React.StrictMode bileşenleri iki kez render eder. Bu, üretim (production) ortamında gerçekleşmez, endişelenmenize gerek yoktur.
Gelişmiş Özellik: Çizim Geçmişini Yönetme (Undo/Redo)
Profesyonel bir çizim uygulamasında kullanıcıların yaptıkları hataları geri alabilmesi kritik bir ihtiyaçtır. React state yapısını kullanarak çizim adımlarını bir yığın (stack) içerisinde tutabilir ve Canvas'ın putImageData metodunu kullanarak geçmişe dönebiliriz.
Geçmiş Yönetimi İçin Adım Adım Mantık
- Her çizim işlemi bittiğinde (
onMouseUp), mevcut canvas görüntüsünü bir diziye kaydedin. - Geri al butonuna tıklandığında, dizideki son görüntüyü pop edin.
ctx.putImageDataile canvas'ı bir önceki haline getirin.
const [history, setHistory] = useState([]);
const saveToHistory = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
setHistory(prev => [...prev, imageData]);
};
const undo = () => {
if (history.length > 0) {
const newHistory = [...history];
const previousState = newHistory.pop();
setHistory(newHistory);
canvasRef.current.getContext('2d').putImageData(previousState, 0, 0);
}
};
Canvas Uygulamalarında Performans Analizi ve İleri Optimizasyon
Büyük boyutlu canvas alanlarında çizim yaparken tarayıcı performansı düşebilir. Özellikle yüksek çözünürlüklü ekranlarda (Retina display) devicePixelRatio kullanımı, görüntü netliğini artırırken işlem yükünü de beraberinde getirir. Performansı optimize etmek için şu stratejileri uygulayabilirsiniz:
1. RequestAnimationFrame Kullanımı
Çizim işlemlerini doğrudan fare olayları içinde çalıştırmak yerine, requestAnimationFrame kullanarak tarayıcının ekran yenileme hızına (genellikle 60fps) uyum sağlayabilirsiniz. Bu, gereksiz render işlemlerini engeller.
2. OffscreenCanvas ile İşlem Yükünü Dağıtma
Eğer karmaşık katmanlar kullanıyorsanız, ana canvas'ı yormamak için arka planda görünmeyen bir OffscreenCanvas üzerinde hesaplamalar yapıp, sonucu ana canvas'a tek seferde aktarabilirsiniz.
İpucu: Canvas üzerinde çok fazla "path" (yol) birikmesi tarayıcıyı yavaşlatır. Belirli aralıklarla ctx.beginPath() kullanmayı ve gereksiz çizim döngülerini temizlemeyi unutmayın.
Performans Karşılaştırma Tablosu
| Yöntem | Avantajı | Kullanım Senaryosu |
|---|---|---|
| Doğrudan Çizim | Düşük gecikme | Basit, tek katmanlı çizimler |
| requestAnimationFrame | Akıcı animasyon | Fırça efektleri ve karmaşık şekiller |
| OffscreenCanvas | Yüksek performans | Çok katmanlı grafik editörleri |
Bu teknikleri projenize entegre ederek, uygulamanızın sadece bir çizim aracı değil, aynı zamanda yüksek performanslı bir grafik yazılımı gibi çalışmasını sağlayabilirsiniz.
Sonuç
React ile Canvas API kullanarak interaktif bir çizim tahtası oluşturmak, hem React'in DOM yönetimi kabiliyetlerini hem de tarayıcı grafik yeteneklerini anlamanızı sağlar. Bu temel yapı üzerine "Geri Al" (Undo) özelliği ekleyebilir veya katmanlı bir yapı kurarak daha gelişmiş grafik editörleri geliştirebilirsiniz. Bir sonraki adım olarak, çizimleri bir veritabanına JSON formatında kaydetmeyi deneyerek projenizi bir üst seviyeye taşıyabilirsiniz.
Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanmadan önce girdi sanitasyonu ve veri güvenliği önlemlerini mutlaka gözden geçirin.


Yorumlar (0)
Yorum Yaz