بخش عمدهای از این مطلب (به جز مستندات drawWindow) به صفحهی اصلی آموزش Canvas منتقل شده است، بنابراین این صفحه نیز به احتمال زیاد به آن قسمت منتقل میشود تا از ایجاد محتوای تکراری جلوگیری شود.
مقدمه
با انتشار فایرفاکس ۱.۵، عنصر جدیدی از HTML برای برنامهنویسی حالت گرافیکی در فایرفاکس به وجود آمد. <canvas>
بر اساس مستندات WHATWG برای Canvas پیادهسازی شده است که خود این مستندات نیز بر پایهی عنصر <canvas>
در مرورگر سافاری از اپل ایجاد شده است. از آن میتوان برای ترسیم نمودار، عنصرهای واسط کاربری و سایر عنصرهای گرافیکی در مرورگر استفاده کرد.
<canvas>
با ایجاد یک سطح ترسیمی با اندازهی ثابت سبب میشود که یک یا چند فضای گرافیکی به وجود بیایند. در این مقاله ما بر روی فضای گرافیکی ۲ بعدی تمرکز میکنیم. برای گرافیک ۳ بعدی، شما باید از فضای گرافیکی WebGL استفاده کنید.
فضای گرافیکی ۲ بعدی
یک نمونهی ساده
برای شروع، با نمونهای ساده که دو مستطیل با فضای مشترک شفاف مشخص شدهاند، آغاز میکنیم:
<html> <head> <script type="application/javascript"> function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect (10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; ctx.fillRect (30, 30, 55, 50); } </script> </head> <body onload="draw()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>
تابع draw
با دریافت عنصر canvas
فضای ۲ بعدی آن را مشخص میکند. شی ctx
میتواند برای رسم گرافیک روی بوم استفاده شود. در این کد، دو مستطیل با تنظیمات fillStyle
و fiilRect
با فضای مشترک شفاف رسم میشوند. fillStyle
دوم از rgba
برای مشخص کردن شفافیت با رنگ مورد نظر، استفاده میکند.
fillRect
برای رسم مستطیل، strokeRect
برای رسم حاشیههای مستطیل و clearRect
برای پاککردن مستطیل استفاده میشوند. برای ایجاد شکلهای پیچیدهتر، از مسیرها استفاده میشود.
استفاده از مسیرها
تابع beginPath
یک مسیر جدید را آغاز میکند و متدهای moveTo
, lineTo
, arcTo
, arc
و از این قبیل، بخشهای مختلفی را به مسیر تعریفشده اضافه میکنند. مسیر ایجاد شده توسط تابع closePath
بسته میشود. زمانی که یک مسیر ایجاد شود، شما میتوانید با fill
یا stroke
فضای داخل یا حاشیهی مسیر را روی بوم رسم کنید.
<html> <head> <script type="application/javascript"> function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "red"; ctx.beginPath(); ctx.moveTo(30, 30); ctx.lineTo(150, 150); // was: ctx.quadraticCurveTo(60, 70, 70, 150); which is wrong. ctx.bezierCurveTo(60, 70, 60, 70, 70, 150); // <- this is right formula for the image on the right -> ctx.lineTo(30, 30); ctx.fill(); } </script> </head> <body onload="draw()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>
فراخوانی هر یک از توابع fill
یا stroke
، روی مسیر فعلی تاثیر میگذارد. اگر دوباره قصد رنگآمیزی یا ایجاد حاشیه در مسیر را داشته باشیم باید مجدد آن را تعریف کنیم.
حالت گرافیکی
صفتهای یک فضای گرافیکی مانند fillStyle
, strokeStyle
, lineWidth
و lineJoin
قسمتی از حالت گرافیکی فعلی هستند. فضای گرافیکی شامل دو متد save
و restore
است که میتوانند برای انتقال حالت کنونی به مجموعهی حالتها یا از مجموعهی حالتها استفاده شوند.
یک نمونهی پیچیدهتر
در ادامه به نمونهای پیچیدهتر میپردازیم که شامل مسیرها، حالت، و همچنین ماتریس انتقال است. متدهای این فضا یعنی translate
, scale
و rotate
برای انتقال ماتریس به کار میروند که تمامی نقطههای ایجاد شده ابتدا توسط این ماتریس منتقل میشوند.
<html> <head> <script type="application/javascript"> function drawBowtie(ctx, fillStyle) { ctx.fillStyle = "rgba(200,200,200,0.3)"; ctx.fillRect(-30, -30, 60, 60); ctx.fillStyle = fillStyle; ctx.globalAlpha = 1.0; ctx.beginPath(); ctx.moveTo(25, 25); ctx.lineTo(-25, -25); ctx.lineTo(25, -25); ctx.lineTo(-25, 25); ctx.closePath(); ctx.fill(); } function dot(ctx) { ctx.save(); ctx.fillStyle = "black"; ctx.fillRect(-2, -2, 4, 4); ctx.restore(); } function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // note that all other translates are relative to this // one ctx.translate(45, 45); ctx.save(); //ctx.translate(0, 0); // unnecessary drawBowtie(ctx, "red"); dot(ctx); ctx.restore(); ctx.save(); ctx.translate(85, 0); ctx.rotate(45 * Math.PI / 180); drawBowtie(ctx, "green"); dot(ctx); ctx.restore(); ctx.save(); ctx.translate(0, 85); ctx.rotate(135 * Math.PI / 180); drawBowtie(ctx, "blue"); dot(ctx); ctx.restore(); ctx.save(); ctx.translate(85, 85); ctx.rotate(90 * Math.PI / 180); drawBowtie(ctx, "yellow"); dot(ctx); ctx.restore(); } </script> </head> <body onload="draw()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>
قطعه کد بالا دو متد drawBowtie
و dot
را که هر کدام ۴ مرتبه فراخوانی شدهاند، دربرمیگیرد. قبل از هر فراخوانی، از متدهای translate
و rotate
برای ایجاد ماتریس انتقال استفاده میشود که به ترتیب نقطه و پاپیون را مکاندهی میکنند. dot
یک مستطیل کوچک به مرکز (0, 0) و drawBowtie
یک پاپیون کوچک را با استفاده از مسیرها و رنگ مورد نظر به وجود میآورد.
هر چه عملیات ماتریس انباشتهتر میشوند، متدهای save
و restore
برای ذخیرهسازی و بازگرداندن حالت گرافیکی استفاده میشوند. چیزی که باید به یاد داشت این است که چرخش همیشه در مسیر فعلی شکل میگیرد یعنی ترتیب translate() rotate() translate()
به یک شکل و ترتیب translate() translate() rotate()
به شکلی دیگر منجر میشوند.
سازگاری با عنصر <canvas> اپل
در اکثر موارد، <canvas>
با نمونهی پیادهسازی شدهی اپل سازگاری دارد. اگرچه چند مورد هستند که باید به آنها توجه کرد.
برچسب پایانی مورد نیاز است
در پیادهسازی سافاری از اپل، <canvas>
عنصری است که مشابه <img>
پیادهسازی شده است، یعنی به برچسب پایانی نیازی ندارد. اگرچه، برای اینکه <canvas>
به صورت گسترده در وب استفاده شود، برخی امکانات برای محتوای بازگشتی بایستی فراهم شوند. از این رو، پیادهسازی موزیلا از این عنصر، نیازمند استفاده از برچسب پایانی است.
اگر به محتوای بازگشتی نیازی نباشد، یک نمونهی ساده مانند <canvas id="foo" ...></canvas>
با هر دو پیادهسازی سافاری و موزیلا سازگاری دارد، با این تفاوت که سافاری برچسب پایانی را در نظر نمیگیرد.
اگر محتوای بازگشتی مورد استفاده قرار گیرد، بایستی از برخی تکنیکهای CSS برای ایجاد آن در سافاری استفاده کرد و همچنین از برخی تکنیکها برای فهماندن این مطلب به IE!
ویژگیهای دیگر
فراهمکردن محتوای وب در داخل Canvas
پیادهسازی موزیلا از canvas
با استفاده از متد drawWindow
گسترش یافته است. این متد تصویری از یک صفحهی
DOM را در داخل canvas رسم میکند. برای نمونه:
Mozilla's canvas
is extended with the drawWindow()
method. This method draws a snapshot of the contents of a DOM window
into the canvas. For example,
ctx.drawWindow(window, 0, 0, 100, 200, "rgb(255,255,255)");
قطعهکد بالا محتوای پنجرهی فعلی را در مستطیلی با ابعاد ذکر شده به پیکسل نسبت به گوشهی بالا و چپ پنچره در یک پیشزمینهی سفید از بوم، رسم میکند. با مشخص کردن "rgba(255,255,255,0)" به عنوان رنگ، محتوا با پیشزمینهی شفاف رسم میشود.
معمولا استفاده از رنگ پیشزمینهای به جز سفید "rgb(255,255,255)" یا شفاف کار درستی نیست چرا که تمامی مرورگرها از این استاندارد برای نمایش صفحات وب استفاده میکنند.
با این روش، ممکن است بتوان یک IFRAME پنهان با محتوای دلخواه (برای نمونه متنی که با CSS سبکدهی شده باشد یا SVG) را در یک بوم رسم کرد، که به این صورت میتوان آن را مقیاسدهی کرد یا چرخاند یا هر عمل دیگری که با انتقالهای فعلی میتوان انجام داد.
Ted Mielczarek با افزونهی tab preview خود در chrome این امکان را فراهم میکند تا بتوان تصویرهای کوچک از وبسایتها را مشاهده کرد، و کد آن نیز در دسترس است.
canvas.drawWindow()
در داخل رخداد onload
سند عمل نمیکند. در فایرفاکس ۳.۵ به بعد، میتوان با استفاده از رخداد MozAfterPaint این حالت را در زمان بارگذاری صفحه پیادهسازی کرد.