گرافیک و چندرسانهای
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
| ویژگی | Canvas | SVG |
|---|---|---|
| نوع | پیکسلی (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 |
این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.