گرافیک و چندرسانه‌ای

Canvas و رسم اشکال و متن و تصاویر، انیمیشن، پردازش پیکسل، SVG، Audio و Video API، Web Audio API و آشنایی با WebGL.

Canvas — بوم نقاشی

Canvas بومی برای رسم پیکسلی است — مناسب بازی، نمودار و پردازش تصویر:

<canvas id="myCanvas" width="400" height="300"></canvas>

<script>
const canvas = document.querySelector("#myCanvas");
const ctx = canvas.getContext("2d");  // زمینه دوبعدی

// مختصات از گوشه بالا-چپ:
// (0,0) ───────→ x
//   │
//   ↓ y

رسم اشکال پایه

// مستطیل:
ctx.fillStyle = "#3498db";        // رنگ پر
ctx.fillRect(20, 20, 150, 100);   // x, y, w, h

ctx.strokeStyle = "red";          // رنگ خط
ctx.lineWidth = 3;
ctx.strokeRect(20, 20, 150, 100); // فقط کادر

ctx.clearRect(30, 30, 50, 50);    // پاک کردن

// دایره — arc:
ctx.beginPath();
ctx.arc(250, 150, 60, 0, Math.PI * 2);  // x, y, r, از, تا
ctx.fillStyle = "green";
ctx.fill();

// نیم‌دایره:
ctx.beginPath();
ctx.arc(250, 280, 50, 0, Math.PI);      // نیمه پایین
ctx.fill();

// خط:
ctx.beginPath();
ctx.moveTo(350, 20);      // شروع
ctx.lineTo(380, 100);     // پایان
ctx.lineTo(320, 80);      // ادامه
ctx.closePath();          // بستن
ctx.stroke();

مسیرها (Paths) پیچیده

// مثلث با Path:
ctx.beginPath();
ctx.moveTo(200, 50);
ctx.lineTo(250, 150);
ctx.lineTo(150, 150);
ctx.closePath();
ctx.fillStyle = "orange";
ctx.fill();

// منحنی — quadraticCurveTo:
ctx.beginPath();
ctx.moveTo(50, 250);
ctx.quadraticCurveTo(100, 180, 150, 250);  // کنترل، پایان
ctx.stroke();

// منحنی بزیه — bezierCurveTo:
ctx.beginPath();
ctx.moveTo(50, 280);
ctx.bezierCurveTo(80, 220, 130, 320, 170, 280);
ctx.stroke();

// گرادیان:
const gradient = ctx.createLinearGradient(0, 0, 400, 0);
gradient.addColorStop(0, "#ff6b6b");
gradient.addColorStop(1, "#4ecdc4");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 400, 50);

متن روی Canvas

ctx.font = "30px Arial";          // فونت
ctx.textAlign = "center";         // تراز
ctx.textBaseline = "middle";
ctx.fillStyle = "#333";

ctx.fillText("سلام دنیا", 200, 100);      // پر شده
ctx.strokeStyle = "blue";
ctx.strokeText("متن خطی", 200, 150);      // فقط خط

// اندازه‌گیری:
const metrics = ctx.measureText("سلام دنیا");
console.log(metrics.width);

تصاویر روی Canvas

const img = new Image();
img.src = "picture.jpg";

img.onload = () => {
    // رسم:
    ctx.drawImage(img, 0, 0);                  // اندازه واقعی
    ctx.drawImage(img, 0, 0, 200, 150);        // مقیاس
    ctx.drawImage(img, 50, 50, 100, 100, 0, 0, 200, 200); // برش

    // پردازش پیکسل:
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    console.log(imageData.width, imageData.height);
};

// پیکسل‌ها:
const pixel = ctx.getImageData(x, y, 1, 1).data;
// [R, G, B, A] — هرکدام 0-255

پردازش پیکسل — فیلترها

function applyFilter(imageData, filter) {
    const data = imageData.data;  // RGBA — آرایه تخت

    switch (filter) {
        case "grayscale":
            for (let i = 0; i < data.length; i += 4) {
                const avg = (data[i] + data[i+1] + data[i+2]) / 3;
                data[i] = data[i+1] = data[i+2] = avg;
            }
            break;

        case "invert":
            for (let i = 0; i < data.length; i += 4) {
                data[i] = 255 - data[i];
                data[i+1] = 255 - data[i+1];
                data[i+2] = 255 - data[i+2];
            }
            break;

        case "brightness":
            const factor = 1.2;
            for (let i = 0; i < data.length; i += 4) {
                data[i] *= factor;
                data[i+1] *= factor;
                data[i+2] *= factor;
            }
            break;
    }

    return imageData;
}

// استفاده:
const imageData = ctx.getImageData(0, 0, w, h);
ctx.putImageData(applyFilter(imageData, "invert"), 0, 0);

انیمیشن — requestAnimationFrame

let x = 0;
let direction = 1;

function animate() {
    // پاک کردن فریم قبل:
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // رسم:
    ctx.beginPath();
    ctx.arc(x, 150, 30, 0, Math.PI * 2);
    ctx.fillStyle = "purple";
    ctx.fill();

    // حرکت:
    x += direction * 3;
    if (x > canvas.width - 30 || x < 30) {
        direction *= -1;  // برگشت
    }

    requestAnimationFrame(animate);  // فریم بعدی
}

animate();  // شروع — ۶۰fps
requestAnimationFrame با نرخ نمایشگر (معمولاً ۶۰fps) همگام است و وقتی تب مخفی است توقف می‌کند — بهتر از setInterval.

SVG — گرافیک برداری

بر خلاف Canvas، XML است و هر شکل یک DOM Node:

<svg width="200" height="200">
    <circle cx="100" cy="100" r="50" fill="blue" />
    <rect x="20" y="20" width="60" height="40" fill="red" />
</svg>

// دستکاری با JS:
const circle = document.querySelector("circle");
circle.addEventListener("click", () => {
    circle.setAttribute("fill", "green");
    circle.setAttribute("r", "70");
});

// انیمیشن SVG با CSS:
// circle { transition: all 0.3s; }
// circle:hover { r: 80; }

// ساخت SVG با JS:
const svgNS = "http://www.w3.org/2000/svg";
const rect = document.createElementNS(svgNS, "rect");
rect.setAttribute("width", "50");
rect.setAttribute("height", "50");
rect.setAttribute("fill", "purple");
document.querySelector("svg").appendChild(rect);

Canvas در برابر SVG

ویژگیCanvasSVG
نوعپیکسلی (Raster)برداری (Vector)
رویدادهاروی کل بومروی هر شکل
مقیاس‌پذیریبا کیفیت پایینبی‌نهایت بدون افت
کاراییبهتر برای هزاران شکلکند با DOM زیاد
مناسببازی، پردازش تصویرآیکون، نمودار تعاملی

Video API

<video id="video" src="movie.mp4" controls></video>

const video = document.querySelector("#video");

// کنترل:
video.play();
video.pause();
video.currentTime = 30;   // پرش به ثانیه ۳۰

// خواص:
console.log(video.duration);     // طول کل (ثانیه)
console.log(video.currentTime);  // موقعیت فعلی
console.log(video.paused);
console.log(video.volume);       // 0 تا 1
video.volume = 0.5;
video.muted = true;

// رویدادها:
video.addEventListener("timeupdate", () => {
    const progress = video.currentTime / video.duration * 100;
    console.log(`پیشرفت: ${progress}%`);
});

video.addEventListener("ended", () => console.log("پایان"));
video.addEventListener("loadedmetadata", () => {
    console.log("طول:", video.duration);
});

// تمام‌صفحه:
video.requestFullscreen();

Audio API — پخش ساده

const audio = new Audio("music.mp3");
audio.play();
audio.pause();
audio.volume = 0.3;
audio.loop = true;

// یا با تگ:
// <audio src="..." controls></audio>

Web Audio API — پردازش صدا

// AudioContext — مرکز پردازش:
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

// ساخت اسیلاتور — تولید صدا:
const oscillator = audioCtx.createOscillator();
const gain = audioCtx.createGain();  // کنترل بلندی

oscillator.type = "sine";            // نوع موج
oscillator.frequency.value = 440;    // فرکانس — لا

// اتصال: oscillator → gain → خروجی:
oscillator.connect(gain);
gain.connect(audioCtx.destination);

// پخش:
oscillator.start();
gain.gain.value = 0.1;  // ۱۰٪ بلندی

// تغییر فرکانس:
setTimeout(() => oscillator.frequency.value = 880, 1000);  // یک اکتاو بالا

// توقف:
setTimeout(() => oscillator.stop(), 2000);

Web Audio — تحلیل طیف

// اتصال میکروفن و نمایش طیف:
navigator.mediaDevices.getUserMedia({ audio: true })
    .then(stream => {
        const source = audioCtx.createMediaStreamSource(stream);
        const analyser = audioCtx.createAnalyser();

        analyser.fftSize = 256;
        source.connect(analyser);

        const bufferLength = analyser.frequencyBinCount;
        const dataArray = new Uint8Array(bufferLength);

        function draw() {
            requestAnimationFrame(draw);
            analyser.getByteFrequencyData(dataArray);

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const barWidth = canvas.width / bufferLength;

            dataArray.forEach((value, i) => {
                const barHeight = value / 255 * canvas.height;
                ctx.fillStyle = `rgb(${value}, 50, 150)`;
                ctx.fillRect(i * barWidth, canvas.height - barHeight,
                             barWidth - 1, barHeight);
            });
        }
        draw();
    });

WebGL — سه‌بعدی

برای گرافیک سه‌بعدی شتاب‌دار سخت‌افزاری — پیچیده اما قدرتمند:

const gl = canvas.getContext("webgl");

// شیدر ساده — نقطه قرمز:
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, `
    void main() {
        gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
        gl_PointSize = 10.0;
    }
`);
gl.compileShader(vertexShader);

// معمولاً از Three.js استفاده می‌شود:
// import * as THREE from "three";
// const scene = new THREE.Scene();
// const camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000);
// const renderer = new THREE.WebGLRenderer();
برای WebGL عملی، کتابخانه Three.js را یاد بگیرید — WebGL خام بسیار Low-Level است.

جمع‌بندی

کارابزار
رسم دوبعدیCanvas 2D
آیکون/نمودارSVG
پخش مدیاVideo/Audio API
تولید/فیلتر صداWeb Audio API
سه‌بعدیWebGL / Three.js
انیمیشنrequestAnimationFrame

این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.

ابزارهای مرتبط