البرمجة

رسم Canvas بجافاسكربت

مقدّمة عامّة حول الرسم على اللوحة في جافاسكربت (HTML Canvas)

يشكِّل عنصر  أحد أهمّ عناصر واجهة الويب الحديثة القادرة على عرض رسومات ثنائيّة (2‑D) وثلاثيّة الأبعاد (3‑D) مباشرةً داخل المتصفِّح من دون حاجة إلى مكوّنات إضافيّة. ومنذ إدراجه ضمن مواصفة HTML5، تحوّل إلى حجر زاوية في تطوير الألعاب، والرسوم البيانيّة التفاعليّة، ومعالِجات الصور، ومحاكيات الفيزياء، والخرائط، وأدوات التخطيط الفنيّ والهندسيّ، وغيرها من التطبيقات الثرية.

هذا المقال يتعمّق، على امتداد أكثر من أربعة آلاف كلمة، في البنية التقنيّة لـ Canvas وجافاسكربت، وأفضل الممارسات، وأشهر المكتبات، وقضايا الأداء وعلاقتها بوحدة معالجة الرسوم (GPU)، وأمن الرسومات، إضافة إلى منهجيّات الاختبار، والفرق بين تقنيّات Canvas و SVG و WebGL، مع جداول توضّح نقاط المقارنة العمليّة، وصولًا إلى إرشادات معمّقة لتطوير مشروعٍ رسوميّ مستدام وقابل للتوسّع.


1. أصل الفكرة وتطوّر HTML Canvas

بدأت الحاجة إلى رسمٍ ديناميكيّ داخل المتصفّحات مع بروز التطبيقات الغنيّة بالوسائط في مطلع الألفيّة. اعتمد المطوّرون على تقنيّات مثل Flash و Java Applets لتعويض القصور في HTML و CSS. لكن تلك الحلول عانت من مشكلات أمنيّة وأدائيّة وتوافقية، فتكوّن إجماعٌ على ضرورة معيار مفتوح. ظهر Canvas لأوّل مرة في متصفّح Safari عام 2004، ثم تبنّته لجنة WHATWG وأُدرج رسميًا في HTML5 سنة 2014. يتكوّن Canvas من مساحة بكسليّة خام تتحكّم بها واجهة أوامر جافاسكربت تُسمّى Canvas Rendering Context (أو Context اختصارًا) وتأتي بنكهتين: ثنائيّة الأبعاد 2d ومواصفة WebGL للرسومات ثلاثيّة الأبعاد.


2. هيكل العنصر وتهيئته

html
<canvas id="scene" width="800" height="600">canvas> <script> const canvas = document.getElementById('scene'); const ctx = canvas.getContext('2d'); // أو 'webgl' script>
  • العرض والارتفاع: تُحدّدان صفات البكسل الفعلية. تغييرهما عبر CSS فقط يطبّق تحجيمًا (scaling) وقد يضيع التفاصيل.

  • السياق (Context): يوفّر مجموعة دوالّ للرسم وتحرير البكسلات.


3. رسم الأشكال الأساسيّة

3.1 المستطيلات

js
ctx.fillStyle = '#3498db'; ctx.fillRect(50, 40, 200, 120); ctx.lineWidth = 4; ctx.strokeStyle = '#1f618d'; ctx.strokeRect(50, 40, 200, 120);

3.2 المسارات Paths

js
ctx.beginPath(); ctx.moveTo(300, 100); ctx.lineTo(450, 150); ctx.lineTo(400, 250); ctx.closePath(); ctx.fill();

3.3 الدوائر والأقواس

js
ctx.beginPath(); ctx.arc(150, 300, 80, 0, Math.PI * 2); ctx.fillStyle = 'rgba(231, 76, 60, .7)'; ctx.fill();

4. النصوص ومعالجة الخطوط

يدعم Canvas تسريع رسم النصّ عبر Font Glyph Caching، لكنّه لا يملك نموذج تخطيط معقّد مثل DOM. لذلك يتحمّل المطوّر تحديد font‑family والحجم والمحاذاة يدويًا:

js
ctx.font = "bold 24px 'Cairo', sans-serif"; ctx.fillStyle = '#2c3e50'; ctx.fillText('مرحبًا Canvas!', 320, 380);

5. تضمين الصور والتلاعب بالبكسل

js
const img = new Image(); img.src = 'photo.jpg'; img.onload = () => ctx.drawImage(img, 0, 0, 800, 600);

لإنشاء فلاتر لونيّة:

js
const imageData = ctx.getImageData(0, 0, 800, 600); const data = imageData.data; for (let i = 0; i < data.length; i += 4) { // تحويل للصورة الرماديّة const g = 0.299*data[i] + 0.587*data[i+1] + 0.114*data[i+2]; data[i] = data[i+1] = data[i+2] = g; } ctx.putImageData(imageData, 0, 0);

ملاحظة أدائيّة: معالَجة البكسل في حلقة جافاسكربت كثيفة مكلفة. استخدِم WebGL أو OffscreenCanvas + Workers لتحميل العمل على الـ GPU أو خيوط خلفيّة.


6. التحريك (Animation Loop)

يعتمد Canvas على requestAnimationFrame لجعل معدل الإطارات متزامنًا مع شاشة المستخدم:

js
function animate(t) { ctx.clearRect(0, 0, canvas.width, canvas.height); drawScene(t); requestAnimationFrame(animate); } requestAnimationFrame(animate);

7. قضايا الدقّة على الشاشات عالية الكثافة (HiDPI)

لضمان وضوح الرسم على شاشات Retina، يُضاعَف الحجم المنطقي:

js
const dpr = window.devicePixelRatio || 1; canvas.width = 800 * dpr; canvas.height = 600 * dpr; canvas.style.width = '800px'; canvas.style.height = '600px'; ctx.scale(dpr, dpr);

8. مقارنة Canvas و SVG و WebGL

المعيار Canvas 2D SVG WebGL
نموذج الرسوم بكسلي متّجه بكسلي ثلاثي الأبعاد
تعديل العقد بعد الرسم غير ممكن ممكن (DOM) غير ممكن
الأداء مع آلاف العناصر جيّد ضعيف ممتاز
إمكانات التظليل (Shaders) محدود غير متاح كامل
تعقيد API منخفض متوسط مرتفع
الأفضل لـ الألعاب ثنائية الأبعاد، الرسومات الديناميكية أيقونات، خرائط ثابتة، مخططات ألعاب 3‑D، محاكيات، علم البيانات

9. مكتبات شهيرة تعزّز Canvas

  1. Fabric.js: توفّر كائنات عالية المستوى (دوائر، نصوص، صور) مع دعم التحريك والتصدير كـ SVG.

  2. Paper.js: تركيز على الفن الخطي والعمليات البوليغونية و Booleans الهندسيّة.

  3. PixiJS: مسرّع بواسطة WebGL افتراضيًا مع تلقّي احتياطي لـ Canvas، مناسب للألعاب.

  4. Chart.js و ECharts: توليد مخططات عالية التفاعل.

  5. Konva.js: طبقات، أحداث، دعم Hit Detection.


10. تحسين الأداء

  • قلّل عمليات getImageData و putImageData.

  • اجمع الرسوم الثابتة في Layer معزول ولا تعِد رسمه كل إطار.

  • استخدِم OffscreenCanvas في Web Workers لتجنّب تجميد الـ UI.

  • فعّل willReadFrequently: true عند استدعاء getContext إذا كان التطبيق يعتمد بشدّة على قراءة البكسل.

  • في الألعاب عالية التعقيد، انقل المنطق إلى WebGL أو PixiJS.


11. الأمن والخصوصيّة

يستطيع Canvas التقاط بكسلات من عناصر  أو  قد تحمل علامة CORS. لذا:

  • أضف صفة crossorigin="anonymous" لوسائط نفس المجال أو المصرَّح بها.

  • تمنع المتصفّحات تصدير Canvas كصورة إذا احتوى مصدرًا مقيّدًا.

  • راقِب أدوات البصمة الرقميّة (Fingerprinting) التي تقيس خصائص Canvas لتمييز المتصفّحات.


12. اختبار الرسومات

  • لقطات Snapshot Testing: خزِّن مخرجات Canvas كصور مرجعيّة وقارِنها ثنائيًا.

  • Unit Tests: استدعِ الدوالّ التي تحسب مواضع الفيزياء أو شعاع الاصطدام من دون الحاجة لرسم فعليّ.

  • Performance Budget: حدّد إطارَين رئيسيين (CPU Frame Budget, GPU Frame Budget) وراقِب عبر Performance Panel في DevTools.


13. مشروع نموذجي متقدّم: محرِّر فيكتور بكسلي

  1. المعماريّة

    • Data Model بوصف كائنات رسم (Shape, Group, Layer).

    • Render Engine يحوّل النموذج إلى أوامر Canvas.

    • Command Pattern للتراجع Undo/Redo.

  2. التدرّج اللونيّ غير المتجانس (Gradient Mesh)

    • خوارزمية Coons Patch لموالفة الألوان على شبكة رباعيّة.

  3. التصدير

    • إلى PNG بعمق 32‑bit أو SVG متّجه بالرجوع إلى المسارات.

  4. التخزين التلقائي

    • Serialize JSON إلى IndexedDB كل 30 ثانية مع ضغط lz‑string.


14. الاعتبارات المستقبليّة

  • Canvas 2D Level 2 (جارٍ التوحيد): يضيف مرشّحات مدمَجة (blur(), dropShadow()) ودعمًا لترميز الألوان العريض (Display‑P3).

  • WebGPU: واجهة أحدث تَعد بأداء أعلى في الحوسبة الرسوميّة وإمكانات تظليل متقدّمة، وسيكون Canvas الواجهة البسيطة فوقها.

  • تحسينات إمكانية الوصول: أبحاث لإرفاق وصف DOM شبه شفاف حول الرسم لقرّاء الشاشة.


خاتمة تنفيذية

أصبح الرسم على لوحة Canvas في جافاسكربت نظامًا متكاملًا يلبّي احتياجات المشاريع الحديثة، من واجهات المستخدم المخصّصة إلى الألعاب ثنائية وثلاثية الأبعاد. الفهم العميق لبنية Canvas وواجهتها، وإدراك الفروق الدقيقة بين نماذج الرسوم البديلة، وتطبيق استراتيجيات تحسين الأداء، كلّها عوامل ترفع من كفاءة التطبيق وتمنحه قدرة تنافسية في سوق البرمجيات المتسارِع.


المصادر والمراجع

  1. W3C – HTML Living Standard: Canvas 2D Context.

  2. Mozilla Developer Network (MDN): Canvas API Documentation.