آموزش Canvas در HTML رایگان – به زبان ساده و گام به گام
آموزش Canvas در HTML از اهمیت بالایی برخوردار است چرا که، Canvas به عنوان یک عنصر HTML برای رسم گرافیک (نگارهسازی | Draw Graphics) به وسیله اسکریپتنویسی (معمولا با جاوا اسکریپت) مورد استفاده قرار میگیرد. با آموزش Canvas میتوان نمودار رسم کرد، تصاویر را ادغام کرد و تصاویر متحرک (انیمیشن) ساده و نسبتاً پیچیده ایجاد کرد. در مطلب «آموزش Canvas در HTML» سعی شده است موضوعات و سرفصلهای اصلی و بنیادی در خصوص آموزش Canvas به صورت گام به گام و با بیانی ساده ارائه شود.
Canvas چیست ؟
Canvas یکی از محبوبترین ویژگیها و امکانات HTML5 است. توسعهدهندگان از Canvas برای ساخت وباپلیکیشنهای فاخر استفاده میکنند. HTML یک زبان نشانهگذاری است که امکان ایجاد و ساخت بخشها (Section)، پاراگرافها، عنوانها، لینکها و سایر موارد را برای صفحات وب و برنامههای کاربردی فراهم میکند. کاربران میتوانند از وبسایتهای ساخته شده با Canvas بدون نیاز به افزونههای مرورگر مثل ادوبی فلش پلیر استفاده کنند.
اکثر مرورگرهای امروزی مثل کروم، فایرفاکس، سافاری، اوپرا (Opera) و اینترنت اکسپلورر نسخه نُه و ده از Canvas پشتیبانی میکنند. عنصر Canvas در HTML برای رسم نگاره (گرافیک | Graphic) در حین اجرا (On The Fly) با استفاده از جاوا اسکریپت (JavaScript) استفاده میشود. عنصر Canvas تنها یک محفظه نگهدارنده (Container) برای نگاره است. برای رسم نگاره باید از جاوا اسکریپت استفاده کرد. Canvas دارای متدهای (Method) بسیاری برای رسم خطسیر (Path)، محفظه (Box)، دایره، متن و افزودن عکس است.
تاریخچه Canvas
جهت درک اهمیت آموزش Canvas داشتن اطلاعاتی در خصوص تاریخچه آن میتواند مفید باشد. Canvas در ابتدا توسط شرکت اپل برای استفاده در قطعه وبکیت (WebKit) مکاواس ده (Mac OS X) در اوایل سال 1383 با هدف بهبود اپلیکیشنهایی مثل ویجتهای Dashboard و مرورگر سافاری معرفی شد.
Canvas در نسخه ۱/۸ مرورگرهای Gecko در سال ۱۳۸۴ و در مرورگر اوپرا در سال 1385 به کار گرفته شد و توسط کارگروه تعیین تکنولوژی نحوه استفاده از ابرمتن وب (Web Hypertext Application Technology Working Group | WHATWG) برای مشخصات نسل بعدی فناوریهای وب استانداردسازی شد. امروزه، تمامی مرورگرهای برجسته از Canvas پشتیبانی میکنند.
پیش نیاز های Canvas چیست ؟
آشنایی با HTML و جاوا اسکریپت پیشنیازهای اساسی Canvas هستند. قبل از شروع آموزش Canvas باید پیشنیازهای لازم را فرا گرفت. همانطور که بیان شد، Canvas یک عنصر در HTML5 است. بنابراین، آشنایی با HTML و خصوصاً HTML5 به عنوان پیشنیاز، قبل از شروع آموزش Canvas ضروری است.
همچنین، همانطور که در ابتدا توضیح داده شد، از جاوا اسکریپت برای ترسیم نگارهها در محفظه نگهدارنده Canvas استفاده میشود. بنابراین، واضح است که قبل از آموزش Canvas باید آشنایی کافی با جاوا اسکریپت وجود داشته باشد.
جاوا اسکریپت چیست ؟
جاوا اسکریپت (JavaScript | JS) یک زبان برنامهنویسی است که امکان پیادهسازی ویژگیهای پیچیده را در صفحات وب فراهم میکند. جاوا اسکریپت به کاربران اجازه میدهد با صفحات وب تعامل داشته باشند. از فریموُرکهای متعدد جاوا اسکریپت برای ساخت اپلیکیشنهای وب و موبایل استفاده میشود. همچنین، JavaScript برای ساخت وبسرورها، توسعه کاربردهای مرتبط با سرور و توسعه بازیهای کامپیوتری نیز به کار گرفته میشود.
Canvas برای چه کاری استفاده میشود ؟
به طور رسمی، Canvas یک طرح بیتی (Bitmap) مبتنی بر وضوح تصویر (resolution) است که میتوان از آن برای پردازش نمودارها، نگارههای بازی یا تصاویر بصری در حین اجرا استفاده کرد. به بیان ساده، با کمک یک عنصر Canvas متشکل از جاوا اسکریپت و HTML5، میتوان اشکال دوبعدی و تصاویر بیتمپ را پردازش کرد. یک صفحه وب، ممکن است حاوی چند عنصر Canvas باشد. هر Canvas دارای یک شناسه است که با استفاده از این شناسه میتوان از طریق جاوا اسکریپت به آن دسترسی پیدا کرد.
هر عنصر Canvas دارای یک زمینه (Context) دو بعدی است. این زمینه، حاوی تعدادی شیٔ، خصوصیت (Properties) و متُد است. برای رسم روی یک Canvas، باید به زمینه آن ارجاع داده شود. زمینه، دسترسی به تنظیمات و متدهای آن Canvas را فراهم میکند. هر عنصر Canvas، دو موقعیت x و y دارد که x مختصات افقی و y مختصات عمودی است. تصویر زیر مختصات Canvas را نمایش میدهد.
تفاوت Canvas با SVG چیست؟
در آموزش Canvas درک تفاوتها میان عنصرهای SVG و Canvas اهمیت دارد. SVG یک قالب گرافیکی برداری مبتنی بر XML است. میتوان با استفاده از CSS به SVG استایل (سبک | Style) اضافه کرد و همچنین، با استفاده از SVG DOM میتوان رفتار پویا (رفتار دینامیک | Dynamic Behavior) افزود.
از طرف دیگر، Canvas مبتنی بر bitmap است و امکان رسم نگارهها و اشکال را از طریق جاوا اسکریپت فراهم میکند. به مانند SVG، میتوان استایلها و رفتارهای دینامیک را به Canvas نیز اضافه کرد. در ادامه، برخی دلایل برتری Canvas نسبت به SVG فهرست شده است.
- وقتی صحبت از رسم نگارههای پیچیده میشود، Canvas سریعتر عمل میکند.
- در مورد Canvas میتوان تصاویر را ذخیره کرد؛ درحالیکه، در SVG این کار امکانپذیر نیست.
- همه چیز در Canvas به صورت یک پیکسل (Pixel) است.
اما، SVG برتریهایی هم دارد که در ادامه فهرست شده است.
- با توجه به اینکه SVG مستقل از رزلوشن است، میتواند در صفحه نمایشها با رزولوشنهای متفاوت اندازه را تطبیق دهد.
- در SVG به دلیل اینکه ماهیت XML وجود دارد، فرآیند هدف قرار دادن عنصرهای مختلف آسانتر است.
- SVG در انیمیشنهای پیچیده به خوبی عمل میکند.
بهتر است از کدامیک استفاده شود؟
برای توسعه نگارههای (Graphics) وابسته به رزلوشن تعاملی (Interactive) و مبتنی بر بردار (Vector-Based)، بهتر است SVG را انتخاب کرد. اگر نیاز به پردازش بسیار سریع نگارهها وجود داشته باشد، مثلاً در بازیهای کامپیوتری، یا تمایلی به کار با XML وجود نداشته باشد، میتوان از Canvas استفاده کرد.
Canvas و شتاب سختافزاری
با وجود مرورگرهای دارای قابلیت شتاب سختافزاری (Hardware Acceleration) به اندازه کافی رضایت توسعهدهندگان جلب میشود. زیرا این مرورگرها، تصاویر و انیمیشنهای Canvas را با سرعت مناسبی برای کاربران پردازش میکنند و تجربه کاربری (User Experience) مطلوبی پدید میآورند. در نگاهی عمیقتر، میتوان به این مسئله اشاره کرد که کامپیوترهای دسکتاپ امروزی علاوهبر داشتن CPU (واحد پردازش مرکزی | Central Processing Unit) دارای GPU (واحد پردازش گرافیکی | Graphical Processing Unit) نیز هستند.
بنابراین، وقتی زمان پردازش تصاویر و انیمیشنهای سریع فرا میرسد، عملیات لازم به وسیله GPU انجام شده و پس از آن، CPU به انجام باقی وظایف ادامه میدهد. حاصل این همکاری، عملکرد گرافیکی شتابیافته (Accelerated Graphics Performance) است. در حال حاضر نسخههای بهروز کروم، فایرفاکس و اینترنت اکسپلورر از این قابلیت پشتیبانی میکنند.
API دو بعدی Canvas
API (واسط برنامهنویسی کاربردی | Aplication Programing Interface) دو بُعدی Canvas، این امکان را به وجود میآورد که روی یک عنصر Canvas، تصاویر را ترسیم و عکسها را مدیریت کرد. برای ارجاع به زمینه Canvas، از متُد getContext استفاده میشود. این متد تنها یک پارامتر به نام «2d» دارد. هر Canvas دارای زمینه مربوط به خودش است.
بنابراین، اگر در یک صفحه چند عنصر Canvas وجود داشته باشد، باید برای هر یک از زمینههایی که قصد کار با آنها وجود دارد، امکان ارجاع وجود داشته باشد. متد getContext یک زمینه ترسیم را روی Canvas بازمیگرداند. به غیر از getContext تعداد زیادی توابع و متدهای دیگر نیز در API دو بُعدی Canvas در دسترس است (توابع یک شیٔ در جاوا اسکریپت متُد نامیده میشوند). برخی از متدهای قابل توجه Canvas در ادامه فهرست شدهاند.
متدهای مهم Canvas
در این بخش از مطلب آموزش Canvas برخی از متدهای مهم و قابل توجه Canvas دستهبندی و معرفی شدهاند.
توابع تغییر شکل
دو تابع تغییر شکل (Transformation Function) شاخص فهرست شده است.
- scale: امکان مقیاسدهی یک زمینه را ایجاد میکند.
- rotate: امکان تغییر جهت مختصات x و y در یک زمینه را فراهم میکند.
توابع وضعیت
دو تابع وضعیت (State Function) کلیدی به صورت زیر است.
- save: ذخیره وضعیت فعلی یک زمینه
- restore: امکان بازیابی وضعیت یک زمینه را از یک حالت ذخیره شده قبلی فراهم میسازد.
توابع متنی
چند تابع متنی مهم در Canvas، در ادامه فهرست شده است:
- font: فونت یک زمینه را دریافت یا تنظیم (اعمال) میکند.
- fillText: یک رشته متنی را در موقعیت تعیین شده رسم میکند.
- measureText: عرض یک متن مورد نظر را اندازهگیری میکند.
در بخش آموزش Canvas توضیحات بیشتری در خصوص اکثر این متدها داده شده و همچنین جهت درک و یادگیری بهتر، مثالهایی برای هر کدام ارائه شده است.
کار با Canvas
تا اینجا در روند آموزش Canvas آشنایی لازم با مفاهیم ابتدایی حاصل شد.
اکنون، سایر جنبهها و موارد استفاده Canvas در ادامه فهرست میشوند.
- کار با API متنی (Text API) برای Canvas
- نگارهها (گرافیکهای) WebGL سه بعدی با Canvas
- API تمام صفحه (Full Screen API)
- انواع ترکیب لایهها (Blend Mode) در Canvas
- متد مربوط به تعریف جلوهای که از همپوشانی (Overlay) دو لایه در یک عنصر Canvas و اشکال CSS Canvas
- متد مربوط به استفاده از HTML5 Canvas به عنوان یک تصویر پسزمینه (Backdrop)
تمرکز اصلی مطلب آموزش Canvas در زمینه استفاده از آن در HTML است و مفاهیم مقدماتی در این خصوص به صورت گامبه گام و به زبان ساده ارائه شدهاند.
راهاندازی Canvas
برای راهاندازی یک Canvas جهت ترسیم، باید یک برچسب Canvas که به آن Canvas Tag گفته میشود، در HTML اضافه و یک زمینه دو بُعدی به آن تخصیص داده شود. تمام عملیات ترسیم در داخل زمینه صورت میگیرد. در ادامه مطلب آموزش Canvas نحوه راهاندازی آن به طور کامل شرح داده خواهد شد.
نکاتی قبل از شروع آموزش Canvas
استفاده از عنصر Canvas در HTML چندان دشوار نیست، اما باید درک ابتدایی از HTML و جاوا اسکریپت وجود داشته باشد. عنصر Canvas در برخی از مرورگرهای قدیمیتر پشتیبانی نمیشود؛ اما در نسخههای اخیر همه مرورگرهای شاخص تحت پشتیبانی است. اندازه پیشفرض Canvas سیصد پیکسل در صد و پنجاه پیکسل است (عرض x ارتفاع).
اما میتوان با استفاده از صفتهای (Attribute) ارتفاع (height) و عرض (Width) در HTML اندازههای دلخواه برای آن تعریف کرد. به منظور رسم نگاره در Canvas از یک شیٔ Context جاوا اسکریپت استفاده میشود که در حین اجرا، نگاره ایجاد میکند.
آموزش Canvas
در این بخش از مطلب، به آموزش Canvas در HTML به صورت گامبهگام پرداخته شده است. آموزش Canvas با نگاهی به عنصر Canvas در HTML آغاز میشود.
کاربرد ساده و ابتدایی Canvas
در این بخش نحوه راهاندازی یک زمینه (Context | بافت) دو بعدی و رسم اولین مثال ارائه شده است.
عنصر <canvas>
قالب یک عنصر <canvas> به صورت زیر است:
1<canvas id="tutorial" width="150" height="150"></canvas>
در نگاه اول، یک برچسب Canvas شبیه به یک عنصر <img> به نظر میرسد. تنها تفاوت واضح برچسبهای Canvas و img در این است که برچسب <canvas> صفتهای src و alt را ندارد. در واقع، عنصر Canvas تنها دارای دو صفت width و height است. هر دوی این صفتها اختیاری (Optional) هستند و میتوان آنها را با استفاده از امکانات DOM (مدل شیٔگرای سند | Document Object Model) تنظیم کرد. وقتی هیچ صفت width و height مشخص نشده باشد، عرض Canvas به صورت پیشفرض ۳۰۰ پیکسل و ارتفاع آن ۱۵۰ پیکسل خواهد بود.
همچنین، در صورت تمایل میتوان اندازه عنصر Canvas را با CSS تنظیم کرد. اما در حین پردازش (Rendering)، تصویر مقیاسبندی (Scale) میشود تا با اندازه طرحبندی (layout) خود مطابقت داشته باشد. اگر تنظیم اندازه با CSS از نسبت Canvas اولیه تبعیت نکند، از حالت طبیعی خود خارج و دارای اعوجاج (Distortion) خواهد شد.
- نکته: اگر پردازشها دارای اعوجاج به نظر میرسند، باید سعی داشت صفتهای width و height به صراحت در <canvas> مشخص شوند و از CSS استفاده نشود.
صفت id مختص عنصر Canvas نیست؛ بلکه، یکی از صفتهای سراسری HTML است که میتواند به هر عنصر HTML همچون عنصر class اعمال شود. همیشه بهتر است یک صفت id تعریف شود تا بتوان به راحتی یک عنصر را در اسکریپت پیدا کرد. عنصر Canvas میتواند درست مثل هر تصویر عادی دارای صفتهای طراحی مانند margin (حاشیه)، border (لبه) و background (پسزمینه) باشد. اگر چه، این قواعد تأثیری روی طرح اصلی داخل Canvas نخواهد داشت. وقتی هیچ قاعده طراحی (Styling Rule) به Canvas اعمال نشده باشد، در ابتدا به طور کامل ناپیدا (نورگذران | Transparent) خواهد بود.
استفاده از محتوای جایگزین در Canvas
عنصر Canvas نسبت به برچسب img و همچنین عناصر Video و Audio یا Pictures متفاوت است. میتوان به راحتی برای مرورگرهای قدیمی که از Canvas پشتیبانی نمیکنند، محتوای جایگزین (Fallback Content) تعریف کرد. از جمله چنین مرورگرهایی، میتوان به نسخههای قبل از نسخه نُه در Internet Explorer اشاره کرد.
فراهم کردن محتوای جایگزین به راحتی انجام میشود؛ فقط باید محتوای مربوطه را داخل عنصر Canvas قرار داد. مرورگرهایی که از Canvas پشتیبانی نمیکنند، Container را در نظر نخواهند گرفت و محتوای جایگزین داخل آن را پردازش خواهند کرد. از طرف دیگر، مرورگرهایی که از Canvas پشتیبانی میکنند از محتوای داخل Container چشمپوشی و خود Canvas را به طور معمول رندر خواهند کرد.
مثال برای استفاده از محتوای جایگزین در Canvas
برای مثال، میتوان یک توضیح متنی از محتوای Canvas فراهم کرد و یا یک تصویر از محتوای رندر شده به صورت پویا قرار داد. میتواند چیزی مانند کد زیر باشد:
1<canvas id="stockGraph" width="150" height="150">
2 current stock price: $3.15 + 0.15
3</canvas>
4
5<canvas id="clock" width="150" height="150">
6 <img src="images/clock.png" width="150" height="150" alt=""/>
7</canvas>
بنابراین، به جای اینکه به کاربر گفته شود از مرورگر دیگری استفاده کند که Canvas را پشتیبانی میکند، متن جایگزین مفید و یا یک زیرشاخه DOM میتواند مفیدتر باشد و Canvas را برای کاربران دسترسپذیرتر کند.
برچسب الزامی <canvas/>
به دلیل وجود امکان جایگزینی، برخلاف عنصر <img>، برچسب پایانی (<canvas/>) در عنصر Canvas الزامی است. اگر این برچسب وجود نداشته باشد، باقی سند به عنوان محتوای جایگزین شناخته میشود و نمایش داده نخواهد شد.
اگر به محتوای جایگزین نیازی نباشد، یک عنصر ساده به صورت زیر، با همه مرورگرها به طور کامل سازگاری خواهد داشت:
1<canvas id="foo" ...></canvas>
زمینه پردازش
عنصر Canvas یک سطح ترسیم با اندازه ثابت ایجاد میکند که یک یا بیش از یک زمینه پردازش (Rendering Context) را نمایش میدهد. این زمینههای پردازش برای دستکاری محتوای نشان داده شده استفاده میشوند. در مطلب آموزش Canvas بیشتر روی زمینه پردازش دو بعدی تمرکز شده است. سایر زمینهها ممکن است انواع پردازش متفاوتی ارائه بدهند؛ برای مثال، WebGL از یک زمینه سه بعدی بر مبنای OpenGL ES استفاده میکند.
Canvas به صورت پیشفرض خالی (Blank) است. برای اینکه چیزی نمایش داده شود، ابتدا باید دسترسی زمینه پردازش به یک اسکریپت داده شده و سپس ترسیم را روی آن زمینه انجام داد. عنصر Canvas دارای یک متُد (method | تابع شیٔ) به نام ()getContext است. این متد برای دریافت زمینه پردازش و توابع ترسیم آن استفاده میشود. ()getContext یک پارامتر دریافت میکند که نوع زمینه یا contextType نام دارد. برای نگارههای دوبعدی، باید مشخصه «2d» در فراخوانی متُد لحاظ شود تا بتوان یک واسط CanvasRenderingContext2D را دریافت کرد:
1var canvas = document.getElementById('tutorial');
2var ctx = canvas.getContext('2d');
خط اول در کد بالا، نقطه اتصال (Node | نود) را از DOM استخراج میکند. این نود، نمایانگر عنصر Canvas است که به وسیله فراخوانی متد ()document.getElementById بدست میآید. با داشتن نود عنصر، میتوان با استفاده از متد ()getContext به زمینه ترسیم (Canvas) دسترسی پیدا کرد.
بررسی پشتیبانی مرورگر از Canvas
محتوای جایگزین در مرورگرهایی نمایش داده میشوند که از Canvas پشتیبانی نمیکنند. با استفاده از اسکریپت و کدنویسی نیز میتوان پشتیبانی یک مرورگر از Canvas را آزمود. این کار را میتوان با بررسی وجود داشتن متد ()getContext انجام داد. در نتیجه، قطعه کد بالا تبدیل به چیزی میشود که در ادامه آمده است.
1var canvas = document.getElementById('tutorial');
2
3if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5 // .کدهای رسم در اینجا قرار میگیرند
6} else {
7 // .کدهای مربوط به عدم پشتیبانی از کنواس در اینجا قرار میگیرند
8}
واضح است در صورتی که مرورگر بتواند با استفاده از متد ()getContext محتوای Canvas را دریافت کند و در واقع در گذاره if، شرط canvas.getContext دارای ارزش True باشد، کدهای بعد از آن اجرا و در غیر این صورت کدهای بعد از else اجرا خواهند شد.
قالب استخوانبندی
در این بخش از مطلب آموزش Canvas، یک قالب استخوانبندی (SkeletonTemplate) ساده و ابتدایی ایجاد شده است. این قالب، در مثالی که در ادامه ارائه میشود مورد استفاده قرار خواهد گرفت.
1<!DOCTYPE html>
2<html>
3 <head>
4 <meta charset="utf-8"/>
5 <title>Canvas tutorial</title>
6 <script type="text/javascript">
7 function draw() {
8 var canvas = document.getElementById('tutorial');
9 if (canvas.getContext) {
10 var ctx = canvas.getContext('2d');
11 }
12 }
13 </script>
14 <style type="text/css">
15 canvas { border: 1px solid black; }
16 </style>
17 </head>
18 <body onload="draw();">
19 <canvas id="tutorial" width="150" height="150"></canvas>
20 </body>
21</html>
اسکریپت بالا، شامل تابعی به نام ()draw است. این تابع پس از بارگذاری صفحه، اجرا خواهد شد. این کار به وسیله گوش دادن به رویداد load در سند صورت میگیرد. این تابع و توابع شبیه به آن را میتوان با استفاده از ()window.setInterval() ،window.setTimeout یا هر کنترل کننده رویداد (Event Handler) دیگری فراخوانی کرد. این قالب در عمل به شکل زیر خواهد بود. همانطور که در تصویر زیر ملاحظه میشود، این قالب اولیه خالی و سفید است.
یک مثال ساده Canvas
در این بخش از مطلب آموزش Canvas یک مثال ساده ارائه شده است که در آن دو مستطیل متقاطع ترسیم میشوند. یکی از این مستطیلها دارای فراپیدایی آلفا (شفافیت آلفا | Alpha Transparency) است.
1<!DOCTYPE html>
2<html>
3 <head>
4 <meta charset="utf-8"/>
5 <script type="application/javascript">
6 function draw() {
7 var canvas = document.getElementById('canvas');
8 if (canvas.getContext) {
9 var ctx = canvas.getContext('2d');
10
11 ctx.fillStyle = 'rgb(200, 0, 0)';
12 ctx.fillRect(10, 10, 50, 50);
13
14 ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';
15 ctx.fillRect(30, 30, 50, 50);
16 }
17 }
18 </script>
19 </head>
20 <body onload="draw();">
21 <canvas id="canvas" width="150" height="150"></canvas>
22 </body>
23</html>
خروجی مثال بالا به این صورت است:
ترسیم اشکال با Canvas
تا اینجا در مسیر آموزش Canvas محیط ابتدایی آن راهاندازی شد. اکنون، میتوان به جزئیات نحوه رسم روی Canvas پرداخت. در این بخش، نحوه رسم برخی اشکال در Canvas نظیر مستطیل، مثلث، خط، منحنی و سایر موارد آموزش داده شده است. کار با خطسیر (Path) نیز برای رسم اشیاء بسیار ضروری است که نحوه انجام آن نیز ارائه خواهد شد.
فضای مشبک
قبل از شروع به ترسیم و در این بخش از آموزش Canvas باید فضای مشبک (Grid Space) یا فضای مختصاتی Canvas را شرح داد. قالب استخوانبندی HTML که در بخش قبل ترسیم شد، دارای یک عنصر Canvas با عرض و ارتفاع ۱۵۰ پیکسل بود. در شکل زیر این Canvas با فضای مشبک در پسزمینه ملاحظه میشود.
معمولاً در حالت عادی، یک واحد در فضای مشبک با یک پیکسل در Canvas متناظر است. مبدأ در این فضای مشبک، در بالاترین نقطه سمت چپ و در مختصات قرار گرفته است. موقعیت همه عناصر، نسبت به این مبدأ مشخص میشود. بنابراین، گوشه بالا سمت چپ مربع آبی رنگ، در موقعیتی به اندازه x پیکسل از سمت چپ و y پیکسل از بالا قرار گرفته است. مختصات این موقعیت به صورت نمایش داده میشود.
رسم مستطیل در Canvas
برخلاف SVG، عناصر Canvas تنها از دو شکل ابتدایی و مقدماتی پشتیبانی میکنند: خطسیر و مستطیل. خطسیر یا Path در واقع لیستی از نقاط است که به وسیله خط به هم متصل میشوند. سایر اشکال باید به وسیله ترکیب یک یا بیش از یک خطسیر تولید شوند.
خوشبختانه، دستهای از توابع ترسیم خطسیر وجود دارد که میتوان به وسیله آنها اشکال بسیار پیچیدهای را تولید کرد. ابتدا، در روند آموزش Canvas به ترسیم مستطیل پرداخته میشود. سه تابع برای ترسیم مستطیل روی Canvas وجود دارد:
- (fillRect(x, y, width, height: این تابع، یک مستطیل که داخل آن با رنگ پر شده تولید میکند.
- (strokeRect(x, y, width, height: محیط مرزی یک مستطیل (مستطیل خالی و بدون رنگ) را ترسیم میکند.
- (clearRect(x, y, width, height: یک منطقه (محیط) به شکل مستطیل را شفاف (نور گذران | Transparent) میکند.
همانطور که پیداست، هر یک از این سه تابع پارامترهای یکسانی را دریافت میکنند. x و y موقعیت بالا و سمت چپترین نقطه مستطیل روی Canvas را مشخص میکنند (نسبت به مبدأ). همچنین، پارامترهای width و height اندازه (Size) مستطیل را تعیین میکنند. در ادامه، به صورت یک مثال از سه تابع ذکر شده در بالا استفاده شده است.
مثال شکل مستطیلی
در این بخش از آموزش Canvas در تابع ()draw که در بخش «یک مثال ساده Canvas» معرفی شد، از سه تابع strokeRect ،fillRect و clearRect برای رسم سه مستطیل تودروتو استفاده شده است.
1function draw() {
2 var canvas = document.getElementById('canvas');
3 if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5
6 ctx.fillRect(25, 25, 100, 100);
7 ctx.clearRect(45, 45, 60, 60);
8 ctx.strokeRect(50, 50, 50, 50);
9 }
10}
خروجی این مثال در ادامه نمایش داده شده است.
در این مثال، تابع ()fillRect یک مربع بزرگ با رنگ سیاه با اضلاع ۱۰۰ پیکسلی رسم میکند. سپس، تابع ()clearRect محدوده به اندازه یک مربع پیکسلی در مرکز را پاک میکند. پس از آن، ()strokeRect فراخوانی میشود تا یک خط مرزی به شکل مربع با اندازه پیکسل در داخل مربع پاک شده رسم شود. دو متُد جایگزین دیگر نیز برای ()clearRect موجود است که میتوان از آنها هم استفاده کرد. برخلاف توابع خطسیر که در ادامه آموزش Canvas معرفی خواهند شد، همه این سه تابع مستطیلساز، ترسیم را مستقیماً و بلافاصله در Canvas انجام میدهند.
ترسیم خطسیر در Canvas
در این بخش از آموزش Canvas به خطوط سیر (Paths) پرداخته شده است. همانطور که بیان شد، یک خطسیر از تعدادی نقطه تشکیل میشود که این نقاط، به وسیله تکه خطهایی به هم وصل شدهاند. این خطوط میتوانند اشکال مختلفی داشته باشند؛ میتوانند به صورت منحنیوار و یا صاف باشند.
همچنین، پهنا و رنگ این خطوط میتواند متفاوت باشد. یک خطسیر و یا حتی یک زیرمسیر (Subpath) ممکن است بسته باشد. برای درست کردن شکل با استفاده از خطسیر، باید مراحلی طی شود که در ادامه فهرست شده است.
- خطسیر ایجاد میشود.
- از دستورات ترسیم برای رسم در داخل خطسیر استفاده میشود.
- وقتی خطسیر ایجاد شد، میتوان پهنای آن را تغییر داد و یا آن را رنگ کرد تا در نهایت رندر شود.
توابع خطسیر
در ادامه، فهرستی از توابعی که برای اجرای گامهای بیان شده استفاده میشوند ارائه شده است.
- ()beginPath: یک خطسیر جدید ایجاد میکند. پس از ایجاد خطسیر جدید، دستورات رسم بعدی در داخل خطسیر هدایت میشوند و برای ساخت آن خطسیر مورد استفاده قرار میگیرند.
- متدهای خطسیر (Path Methods): متدهایی جهت تنظیم (ست کردن | Set) خطسیرهای مختلف برای اشیاء
- ()closePath: یک خط مستقیم از نقطه کنونی به نقطه شروع زیرمسیر فعلی اضافه میکند.
- ()stroke: شکل را با برجسته کردن خطوط مرزی آن شکل ترسیم میکند.
- ()fill: با رنگ و پُر کردن محدوده داخل خطسیر، یک شکل یکدست (Solid Shape) ترسیم میکند.
اولین مرحله در ایجاد و ساخت یک خطسیر، فراخوانی تابع ()beginPath است. خطوطسیر به صورت فهرستی از زیرمسیرها (خطوط، قوسها و سایر موارد) ذخیره میشوند که همگی با هم یک شکل (Shape) را تشکیل میدهند. هر بار که این متد فراخوانده میشود، فهرست مربوطه بازنشانی (Reset) میشود و میتوان اشکال جدید ترسیم کرد.
در مرحله دوم، فراخوانی متدهایی انجام میشود که خطسیرهایی که باید ترسیم شوند را مشخص میکنند. مرحله سوم که اختیاری است، فراخوانی ()closePath است. این متد سعی میکند شکل را با کشیدن یک خط مستقیم از نقطه فعلی تا نقطه آغاز ببندد. اگر شکل خودش بسته شده باشد یا تنها یک نقطه در لیست خطسیر وجود داشته باشد، این تابع کاری انجام نخواهد داد.
رسم یک مثلث در Canvas
همانطور که بیان شد، رسم شکلهای مختلف در Canvas، تنها با استفاده از مستطیل و خطسیر امکانپذیر است. در این بخش از آموزش Canvas با استفاده از خطسیر، یک مثلث ترسیم شده است. کد مربوط به ایجاد مثلث در ادامه آمده است.
1function draw() {
2 var canvas = document.getElementById('canvas');
3 if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5
6 ctx.beginPath();
7 ctx.moveTo(75, 50);
8 ctx.lineTo(100, 75);
9 ctx.lineTo(100, 25);
10 ctx.fill();
11 }
12}
خروجی قطعه کد بالا (تابع draw) به صورت زیر است.
جابهجایی قلم در Canvas
یک تابع بسیار کاربردی که در واقع چیزی رسم نمیکند اما، به جزئی از لیست خطسیر تبدیل میشود، تابع ()moveTo است. میتوان عملکرد این تابع را همانند برداشتن قلم یا مداد از یک نقطه روی کاغذ و قرار دادن آن روی نقطه دیگری در نظر گرفت. (moveTo(x, y قلم را به مختصات تعیین شده توسط $x$ و $y$ انتقال میدهد.
وقتی Canvas راهاندازی اولیه شده باشد یا در واقع تابع ()beginPath فراخوانی شود، معمولاً از تابع ()moveTo برای قرار دادن نقطه شروع در جای دیگر استفاده میشود. همچنین، از ()moveTo برای رسم خطسیرهای غیرمتصل استفاده میشود. به عنوان مثال، قطعه کد زیر، با استفاده از متدهای ()moveTo و ()arc یک صورتک خندان (Smiley Face) تولید میکند.
1function draw() {
2 var canvas = document.getElementById('canvas');
3 if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5
6 ctx.beginPath();
7 ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // Outer circle
8 ctx.moveTo(110, 75);
9 ctx.arc(75, 75, 35, 0, Math.PI, false); // Mouth (clockwise)
10 ctx.moveTo(65, 65);
11 ctx.arc(60, 65, 5, 0, Math.PI * 2, true); // Left eye
12 ctx.moveTo(95, 65);
13 ctx.arc(90, 65, 5, 0, Math.PI * 2, true); // Right eye
14 ctx.stroke();
15 }
16}
تصویر خروجی قطعه کد بالا به صورت زیر است:
رسم خط در Canvas
برای رسم خطوط مستقیم از متد ()lineTo استفاده میشود. فراخوانی (lineTo(x, y، یک خط از موقعیت فعلی به موقعیت مشخص شده با و ، رسم میکند. دو آرگومان و در این متد، مختصات نقطه انتهایی خط هستند.
نقطه آغازین وابسته به خطسیرهای رسم شده قبلی است. به این صورت که، نقطه انتهایی خطسیر قبلی، متناظر با نقطه آغازین برای خطسیر بعدی خواهد بود. همچنین، میتوان محل نقطه آغازین را با استفاده از متد ()moveTo تغییر داد.
مثال رسم خط در canvas
در مثال زیر، دو مثلث رسم میشود که یکی رنگ شده و دیگری تنها دارای خطوط مرزی است.
1function draw() {
2
3var canvas = document.getElementById('canvas');
4
5if (canvas.getContext) {
6
7var ctx = canvas.getContext('2d');
8
9// Filled triangle
10
11ctx.beginPath();
12
13ctx.moveTo(25, 25);
14
15ctx.lineTo(105, 25);
16
17ctx.lineTo(25, 105);
18
19ctx.fill();
20
21// Stroked triangle
22
23ctx.beginPath();
24
25ctx.moveTo(125, 125);
26
27ctx.lineTo(125, 45);
28
29ctx.lineTo(45, 125);
30
31ctx.closePath();
32
33ctx.stroke();
34
35}
36
37}
تصویر گرفته شده از صفحه نمایش برای خروجی قطعه کد بالا به صورت زیر است:
تفاوت میان مثلث رنگ شده و مثلث سفید در کد قابل ملاحظه است. همانطور که بیان شد، وقتی یک خطسیر رنگآمیزی میشود، به صورت خودکار بسته خواهد شد اما وقتی تنها خطوط مرزی آن رسم میشود، باید با استفاده از متد ()closePath خطسیر را بست. در غیر اینصورت، تنها دو خط مستقیم رسم شده و مثلث به طور کامل رسم نمیشد.
رسم قوس در Canvas
برای رسم قوس (Arc) یا دایره از متدهای ()arc یا ()arcTo استفاده میشود. در ادامه، هر یک از این متدها و نحوه فرخوانی آنها به همراه مؤلفههای مربوطه ارائه داده شده است.
(arc(x, y, radius, startAngle, endAngle, anticlockwise
قوسی را رسم میکند که مرکز آن در موقعیت قرار گرفته و شعاع آن است و با زاویه startAngle شروع شده و در زاویه endAngle خاتمه مییابد. قوس در جهت anticlockwise (خلاف چرخش عقربههای ساعت) امتداد پیدا میکند. به صورت پیشفرض، جهت ساعتگرد است.
(arcTo(x1, y1, x2, y2, radius
یک قوس با نقاط کنترلی و شعاع داده شده رسم میکند و به وسیله یک خط مستقیم به نقطه قبلی متصل میشود.
مثال رسم قوس در Canvas
اکنون، در قالب یک مثال یک متد arc فراخوانی خواهد شد که شش پارامتر به صورت زیر دریافت میکند:
- و مختصات مرکز دایرهای هستند که باید رسم شود.
- radius شعاع دایره است.
- پارامترهای startAngle و endAngle نقاط ابتدایی و انتهایی قوس را بر حسب رادیان در امتداد منحنی دایره تعریف میکنند (این پارامترها نسبت به محور اندازهگیری میشوند).
- پارامتر anticlockwise یک مقدار دودویی است. در صورتی که مقدار آن یک یا True باشد، قوس در جهت خلاف گردش عقربههای ساعت رسم میشود و در غیر این صورت، قوس به صورت ساعتگرد رسم خواهد شد.
مثالی که در ادامه آمده است، نسبت به مثالهای ارائه شده قبل از آن کمی پیچیدهتر است. در این مثال ۱۲ قوس مختلف رسم میشود که هر یک زوایا و رنگآمیزی متفاوتی دارند. برای هر قوس، یک مسیر جدید با فراخوانی ()beginPath ایجاد شده است. در کدها، هر یک از پارامترهای مربوط به قوس برای سادگی بیشتر در یک متغیر قرار داده شدهاند که میتوان از این کار در پروژههای واقعی صرفنظر کرد. مقادیر radius و startAngle ثابت هستند.
endAngle از ۱۸۰ درجه (نیمدایره) در ستون اول شروع میشود و با گامهای ۹۰ درجهای در ستون آخر به یک دایره کامل ختم میشود. گذاره مربوط به پارامتر anticlockwise باعث میشود که سطرهای اول و سوم به صورت قوسهای ساعتگرد و سطرهای دوم و چهارم به صورت قوسهای پادساعتگرد رسم شوند. در نهایت، گزاره if موجب میشود که قوسهای نیمه بالایی تنها با خطوط مرزی و قوسهای نیمه پایینی به صورت رنگ شده رسم شوند.
1function draw() {
2 var canvas = document.getElementById('canvas');
3 if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5
6 for (var i = 0; i < 4; i++) {
7 for (var j = 0; j < 3; j++) {
8 ctx.beginPath();
9 var x = 25 + j * 50; // x coordinate
10 var y = 25 + i * 50; // y coordinate
11 var radius = 20; // Arc radius
12 var startAngle = 0; // Starting point on circle
13 var endAngle = Math.PI + (Math.PI * j) / 2; // End point on circle
14 var anticlockwise = i % 2 !== 0; // clockwise or anticlockwise
15
16 ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
17
18 if (i > 1) {
19 ctx.fill();
20 } else {
21 ctx.stroke();
22 }
23 }
24 }
25 }
26}
تصویر خروجی تولید شده به وسیله قطعه کد بالا به صورت زیر است:
منحنیهای بِزیه
نو دیگری از خطسیر، منحنیهای بزیه (Bézier curves) است که در گونههای درجه دو و سه در دسترس هستند. از این منحنیها، عموماً برای رسم شکلهای پیچیده طبیعی (Organic) استفاده میشود.
(quadraticCurveTo(cp1x, cp1y, x, y
این متد، یک منحنی بزیه درجه دو را از محل فعلی قلم تا نقطه انتهایی مشخص شده با و و با استفاده از نقطه کنترلی cp1x و cp1y رسم میکند.
(bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y
یک منحنی بزیه درجه سه از نقطه فعلی تا نقطه پایانی مشخص شده با و و با استفاده از نقاط کنترلی (cp1x , cp1y) و (cp2x , cp2y) رسم میکند.
تفاوت میان منحنیهای بزیه درجه دو و سه
تفاوت میان این دو را میتوان در بهترین حالت با استفاده از تصویر زیر توصیف کرد. یک منحنی بزیه درجه دو دارای نقطه ابتدایی و انتهایی (نقاط آبی) و تنها یک نقطه کنترلی است (که به وسیله نقطه قرمز رنگ نشان داده شده). در حالی که، یک منحی بزیه درجه سه از دو نقطه کنترلی استفاده میکند. پارامترهای و در هر دوی این متدها مختصات نقطه انتهایی هستند. cp1x و cp1y مختصات نقاط کنترلی اول و cp2x و cp2y مختصات تقطه کنترلی دوم هستند.
استفاده از منحنیهای بزیه درجه دو و سه میتواند تا حدودی چالشبرانگیز باشد. چرا که، برخلاف نرمافزار ترسیم برداری Adobe Illustrator، بازخورد بصری مستقیمی نسبت به موارد انجام شده وجود ندارد. این کار رسم شکلهای پیچیده را بسیار دشوار میکند. در مثال پیشرو چند شکل طبیعی ساده رسم خواهد شد. در این مثالها چیز خیلی دشواری وجود ندارد. در هر دو مورد، منحنیها پشت سر هم رسم میشوند، که حاصل آن یک شکل کامل است.
مثال منحنی بزیه درجه دو
در این مثال، از چند منحنی درجه دو بزیه برای تولید یک Speech Balloon استفاده شده است. کد مربوطه در ادامه آمده است.
1function draw() {
2 var canvas = document.getElementById('canvas');
3 if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5
6 // Quadratric curves example
7 ctx.beginPath();
8 ctx.moveTo(75, 25);
9 ctx.quadraticCurveTo(25, 25, 25, 62.5);
10 ctx.quadraticCurveTo(25, 100, 50, 100);
11 ctx.quadraticCurveTo(50, 120, 30, 125);
12 ctx.quadraticCurveTo(60, 120, 65, 100);
13 ctx.quadraticCurveTo(125, 100, 125, 62.5);
14 ctx.quadraticCurveTo(125, 25, 75, 25);
15 ctx.stroke();
16 }
17}
خروجی قطعه کد بالا به صورت زیر است:
مثال منحنی بزیه درجه سه
در این مثال یک شکل قلب با استفاده از منحنیهای بزیه درجه سه رسم شده است.
1function draw() {
2 var canvas = document.getElementById('canvas');
3 if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5
6 // Cubic curves example
7 ctx.beginPath();
8 ctx.moveTo(75, 40);
9 ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
10 ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
11 ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
12 ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
13 ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
14 ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
15 ctx.fill();
16 }
17}
تصویر خروجی قطعه کد بالا در ادامه آمده است.
متد ()rect
علاوه بر سه روش بیان شده در بالا که شکلهای مستطیلی را به صورت مستقیم روی Canvas رسم میکنند، متد ()rect نیز یک خطسیر مستطیلی به خطسیر باز موجود اضافه میکند.
(rect(x, y, width, height
یک مستطیل رسم میکند که بالاترین نقطه سمت چپ در آن با مختصات به همراه عرض width و ارتفاع height مشخص میشود. قبل از اینکه این متد اجرا شود، متد ()moveTo با پارامترهای به صورت خودکار فراخوانی میشود. به بیان دیگر، موقعیت فعلی قلم به صورت خودکار به مختصات پیشفرض بازنشانی میشود.
شیٔهای خطسیر دو بعدی
همانطور که در مثال اخیر ملاحظه شد، ممکن است تعداد خطسیرها و دستورات ترسیم زیادی برای رسم روی Canvas وجود داشته باشد و کدها طولانی شوند.
برای سادهسازی کد و بهبود عملکرد، شیٔ خطسیر دوبعدی (Path2D) در نسخههای اخیر مرورگرها در دسترس قرار گرفته که امکان ذخیرهسازی و ضبط این دستورات ترسیم را فراهم میکنند. میتوان با استفاده از آن، یک خطسیر را مجدد و به سرعت رسم کرد. در ادامه، نحوه ساخت یک شیٔ Path2D توضیح داده شده است.
()Path2D
واحد سازنده ()Path2D یک شیٔ خطسیر دوبعدی جدید را باز میگرداند. میتوان به صورت انتخابی یک خطسیر دیگر را به عنوان آرگومان به همراه Path2D فراخوانی کرد که این کار یک رونوشت از آن خطسیر ایجاد میکند. همچنین، میتوان یک رشته حاوی دادههای یک خطسیر SVG را به عنوان آرگومان در فراخوانی ()Path2D به کار گرفت.
1new Path2D(); // شیٔ خط سیر خالی
2new Path2D(path); // رونوشت از یک خطسیر دیگر
3new Path2D(d); // خطسیر از خطسیر دادههای خطسیر اسویجی
تمام متدهای خطسیر نظیر moveTo ،rect ،arc یا quadraticCurveTo و سایر مواردی که پیش از این معرفی شدند در شیٔهای Path2D در دسترس هستند. همچنین، Path2D API روشی برای ادغام خطسیرها با استفاده از متد addPath فراهم کرده است. این امکان به عنوان مثال برای زمانی مناسب است که قصد ساخت چند شیٔ از تعداد زیادی قطعه (Component) وجود داشته باشد. نحوه فراخوانی متد addPath به صورت زیر است:
1Path2D.addPath(path [, transform])
مثال Path2D در Canvas
در این مثال، یک مربع و یک دایره ایجاد میشود. هر دو آنها به عنوان یک شیٔ Path2D با هدف بهکارگیری در استفادههای بعدی ذخیره میشوند. در Path2D API جدید، بسیاری از متدها بهروزرسانی شدهاند تا به صورت انتخابی یک شیٔ Path2D را برای استفاده بهجای خطسیر فعلی بپذیرند.
در اینجا به عنوان مثال، از stroke و fill به همراه یک آرگومان خطسیر برای رسم هر دو شیٔ روی Canvas استفاده شده است. کد مربوطه در ادامه آمده است.
1function draw() {
2 var canvas = document.getElementById('canvas');
3 if (canvas.getContext) {
4 var ctx = canvas.getContext('2d');
5
6 var rectangle = new Path2D();
7 rectangle.rect(10, 10, 50, 50);
8
9 var circle = new Path2D();
10 circle.arc(100, 35, 25, 0, 2 * Math.PI);
11
12 ctx.stroke(rectangle);
13 ctx.fill(circle);
14 }
15}
خروجی قطعه کد بالا به صورت زیر است:
استفاده از خطسیر SVG
یکی دیگر از امکانات API جدید Path2D استفاده از دادههای خطسیر SVG برای مقداردهی به خطسیرها در Canvas است. این قابلیت، امکان انتقال دادههای خطسیر و استفاده مجدد از آنها را هم در SVG و هم در Canvas فراهم میسازد.
در ادامه، مثالی برای یادگیری نحوه استفاده از خطسیر SVG آمده است.
1var p = new Path2D('M10 10 h 80 v 80 h -80 Z');
در خط کد بالا، خطسیر به نقطه منتقل میشود و سپس، در جهت افقی به اندازه ۸۰ نقطه به سمت راست حرکت میکند (h 80). پس از آن، ۸۰ نقطه به سمت پایین حرکت میکند (v 80). بعد از آن، ۸۰ نقطه به سمت چپ (h -80) و در آخر به محل شروع بازمیگردد (z).
اضافه کردن استایلها و رنگها
در بخش مربوط به ترسیم شکلها، تنها از استایلها و خطوط پیشفرض استفاده شد. در این بخش از آموزش Canvas از امکانات و تنظیمات در دسترس Canvas برای افزودن جذابیت بیشتر به شکلها و ترسیمها استفاده شده است. نحوه اضافه کردن رنگهای مختلف، استایلهای خط، گرادیان، الگو و سایه به ترسیمها آموزش داده شده است.
رنگ ها در Canvas
تا اینجا در آموزش Canvas فقط متدهایی برای ترسیم زمینهها (Context) ارائه شده است. اگر مقصود، اضافه کردن رنگ به یک شکل باشد میتوان از دو خصوصیت (Property) مهم fillStyle و strokeStyle استفاده کرد. در ادامه، توضیحاتی در مورد هر یک از این خصوصیتها فهرست شده است.
- fillStyle = color : با استفاده از آن میتوان استایلی را تنظیم کرد که در زمان رنگآمیزی شکلها بهکار گرفته میشود.
- strokeStyle = color : با استفاده از آن میتوان استایل مورد نظر برای خطوط مرزی شکلها را تعیین کرد.
color رشتهای است که بیانگر یک برچسب <color> در CSS، یک شیٔ گرادیان یا یک شیٔ الگووار است. رنگ مشکی به عنوان رنگ پیشفرض برای خطوط مرزی و رنگآمیزی داخل شکلها تنظیم شده که مقدار این رنگ در CSS به صورت 000000# است. رشتههای مورد قبول، طبق مشخصات باید مقادیر برچسب <color> در CSS باشند. هر خط کد در مثال زیر، روشهای مختلف تنظیم رنگ نارنجی را نشان میدهد.
1// these all set the fillStyle to 'orange'
2
3ctx.fillStyle = 'orange';
4ctx.fillStyle = '#FFA500';
5ctx.fillStyle = 'rgb(255, 165, 0)';
6ctx.fillStyle = 'rgba(255, 165, 0, 1)';
یک مثال برای fillStyle
در این مثال، از دو حلقه for برای رسم یک مستطیل مشبک (Grid | شبکه شطرنجی) استفاده شده است. که هر مربع کوچک رنگ متفاوتی دارد. تصویر حاصل شده پس از کدها ارائه شده است. دو متغیر $i$ و $j$ جهت تولید رنگ RGB برای هر مربع کوچک استفاده شده است. این دو متغیر، تنها رنگهای قرمز و سبز را تغییر میدهند.
کانال آبی مقدار ثابتی برای همه مربعها دارد. با تغییر هر یک از کانالهای RGB، میتوان انواع طیفهای رنگ را تولید کرد. با افزایش تکرار حلقهها، میتوان به چیزی شبیه به طیف رنگی مورد استفاده در فتوشاپ رسید. در ادامه، کد مربوط به این مثال ارائه شده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 for (var i = 0; i < 6; i++) {
4 for (var j = 0; j < 6; j++) {
5 ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ', ' +
6 Math.floor(255 - 42.5 * j) + ', 0)';
7 ctx.fillRect(j * 25, i * 25, 25, 25);
8 }
9 }
10}
نتیجه چیزی شبیه به تصویر زیر است.
استایل های خط
خصوصیتهای بسیاری برای استایل دادن به خطها وجود دارد که برخی از آنها در این بخش از آموزش Canvas فهرست شدهاند.
- lineWidth = value: میتوان با استفاده از آن، پهنای خطوطی که در آینده رسم خواهند شد را تعیین کرد.
- lineCap = type: با تنظیم این خصوصیت میتوان نمای (ظاهر) انتهای خطوط را تعیین کرد.
- lineJoin = type: تنظیم ظاهر نقاط گوشهای، جایی که خطوط به هم میرسند.
مثال پهنای خطوط
این خصوصیت (Property) ضخامت خط را تنظیم میکند. مقادیر باید اعداد مثبت باشند. به صورت پیشفرض، مقدار آن یک واحد (1.0) است. پهنای خط ضخامت خط مرزی در مرکز یک خطسیر است. به بیان دیگر، محدودهای که ترسیم شده تا نیمی از عرض خط در دو طرف خطسیر امتداد دارد.
به دلیل اینکه مختصات Canvas مستقیماً به پیکسلها ارجاع نمیدهد باید دقت خاصی برای رسیدن به خطوط افقی و عمودی برجسته و شکیل لحاظ شود. در مثال زیر، ده خط مستقیم با ضخامتهایی که به ترتیب زیاد میشوند ترسیم شده است. ضخامت سمت چپترین خط برابر با یک واحد است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 for (var i = 0; i < 10; i++) {
4 ctx.lineWidth = 1 + i;
5 ctx.beginPath();
6 ctx.moveTo(5 + i * 14, 5);
7 ctx.lineTo(5 + i * 14, 140);
8 ctx.stroke();
9 }
10}
عکس از صفحه نمایش برای خروجی کد بالا در ادامه ارائه شده است.
الگوها در Canvas
برای ایجاد یک الگو (Pattern) میتوان از تعدادی حلقه استفاده کرد اما، یک روش بسیار سادهتر برای ایجاد و تولید الگوها وجود دارد. این روش در واقع، استفاده از متُد ()createPattern است. این متد، به صورت (createPattern(image, type فراخوانی میشود که حاصل آن، ایجاد یک شیٔ الگو Canvas است.
مؤلفه image یک CanvasImageSource یا منبع تصویر Canvas است. type نیز یک رشته است که مشخص میکند چطور باید از تصویر استفاده شود. در ادامه توضیحات بیشتری در خصوص مؤلفه type ارائه شده است.
مؤلفه type در createPattern
type تعیین میکند چطور باید از یک عکس برای ایجاد الگوی مورد نظر استفاده کرد. مقدار type باید یکی از مقادیر رشتهای زیر باشد.
- repeat: عکس مربوطه را هم در جهت افقی و هم عمودی Tile (فرش | تکرار) میکند.
- repeat-x: عکس مربوطه را فقط به صورت افقی Tile میکند.
- repeat-y: عکس مربوطه را فقط به صورت عمودی Tile میکند.
- no-repeat: عکس را Tile نمیکند و فقط یک بار از عکس استفاده میشود.
از این متد برای ایجاد یک شیٔ CanvasPattern استفاده میشود که بسیار مشابه متدهای گرادیان است. پس از ایجاد یک الگو، میتوان آن را به خاصیتهای fillStyle و strokeStyle نسبت داد. برای مثال:
1var img = new Image();
2img.src = 'someimage.png';
3var ptrn = ctx.createPattern(img, 'repeat');
- نکته: مشابه متد ()drawImage، باید اطمینان حاصل کرد که عکس مورد استفاده قبل از فراخوانی متد createPattern بارگذاری شده باشد. در غیر این صورت، الگو به درستی رسم نخواهد شد.
مثال ایجاد الگو در Canvas
در این مثال از آموزش Canvas یک الگو برای تخصیص به خصوصیت fillStyle ساخته شده است. تنها نکته قابل اشاره در مورد این مثال، کاربرد ناظر (Handler | رسیدگی کننده) «onload» است.
این ناظر برای اطمینان از بارگذاری شدن عکس قبل از تخصیص به الگو استفاده میشود. در ادامه، کد مربوط به مثالی از ایجاد الگو در Canvas ارائه شده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3
4 // create new image object to use as pattern
5 var img = new Image();
6 img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
7 img.onload = function() {
8
9 // create pattern
10 var ptrn = ctx.createPattern(img, 'repeat');
11 ctx.fillStyle = ptrn;
12 ctx.fillRect(0, 0, 150, 150);
13
14 }
15}
خروجی قطعه کد بالا به صورت زیر است:
سایه در Canvas
استفاده از سایهها تنها شامل چهار خصوصیت میشود. این خصوصیتها، در ادامه به همراه توضیحاتی فهرست شده است.
- shadowOffsetX = float: این خصوصیت، فاصله افقی که از شیٔ امتداد مییابد را تعیین میکند. این مقدار به وسیله ماتریس تبدیل (Transformation Matrix) تحت تأثیر قرار نمیگیرد. مقدار پیشفرض آن صفر است.
- shadowOffsetY = float: فاصله عمودی که از شیٔ امتداد مییابد را تعیین میکند. این مقدار به وسیله ماتریس تبدیل تحت تأثیر قرار نمیگیرد. مقدار پیشفرض آن صفر است.
- shadowBlur = float: اندازه جلوه محوکننده (Blurring Effect) را تعیین میکند؛ این مقدار، با تعدادی پیکسل مطابقت دارد و به وسیله ماتریس تبدیل تحت تأثیر قرار نمیگیرد. مقدار پیشفرض آن نیز صفر است.
- shadowColor = color: یک مقدار رنگ CSS که رنگ جلوه سایه (Shadow Effect) را تعیین میکند. به صورت پیشفرض کاملاً شفاف و سیاه رنگ است.
خصوصیتهای shadowOffsetX و shadowOffsetY، فاصلهای را مشخص میکند که سایهها باید از شیٔ در جهتهای X و Y امتداد پیدا کنند. از مقادیر منفی برای امتداد سایه به سمت بالا یا چپ استفاده میشود. مقادیر مثبت نیز برای امتداد سایه به سمت پایین یا راست به کار میروند.
مثال متن سایهدار با Canvas
در این مثال از آموزش Canvas یک رشته متنی با جلوه سایهوار ترسیم میشود. کد مربوطه در ادامه ارائه شده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3
4 ctx.shadowOffsetX = 2;
5 ctx.shadowOffsetY = 2;
6 ctx.shadowBlur = 2;
7 ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
8
9 ctx.font = '20px Times New Roman';
10 ctx.fillStyle = 'Black';
11 ctx.fillText('Sample String', 5, 30);
12}
عکس صفحه نمایش مربوط به خروجی کد تولید متن سایهدار به صورت زیر است.
ترسیم متن در بخشهای بعدی مطلب آموزش Canvas با بررسی خصوصیت «font» و متُد «fillText» ارائه شده است.
قوانین رنگ آمیزی در Canvas
وقتی از خصوصیت fill (یا clip و isPointInPath) استفاده میشود، میتوان به صورت اختیاری یک قانون رنگآمیزی (Fill Rule) اضافه کرد. به وسیله این قانون رنگآمیزی، میتوان تعیین کرد که آیا یک نقطه در داخل یک خطسیر قرار گرفته یا در خارج آن و بنابراین، آیا رنگ خواهد شد یا خیر.
این امکان زمانی کاربردی خواهد بود که یک خطسیر خودش را قطع کند و یا در داخل خطسیر دیگری (تودرتو | Nested) باشد. دو قانون را میتوان به fill نسبت داد:
- "nonzero" : به وسیله آن میتوان تعیین کرد که آیا یک نقطه خاص در داخل یک منحنی بسته قرار گرفته است یا خیر. این قانون به صورت پیشفرض تنظیم شده است.
- "evenodd": به وسیله آن میتوان تعیین کرد که چطور یک شکل گرافیکی با بیش از یک طرح بسته رنگآمیزی شود.
در مثال زیر از قانون evenodd استفاده شده است:
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 ctx.beginPath();
4 ctx.arc(50, 50, 30, 0, Math.PI * 2, true);
5 ctx.arc(50, 50, 15, 0, Math.PI * 2, true);
6 ctx.fill('evenodd');
7}
همانطور در کدها مشخص است، در این مثال، دو دایره تودرتو رسم شده که بر اساس قانون evenodd، دایره خارجی با رنگ پیشفرض مشکی رنگآمیزی شده و دایره کوچکتر داخلی بدون رنگ است. تصویر خروجی در ادامه نشان داده شده است.
پس از یادگیری نحوه اضافه کردن استایلها و رنگآمیزی در این بخش، اکنون در ادامه آموزش Canvas به نحوه رسم (نوشتن) متن روی بوم نقاشی (Canvas) پرداخته شده است.
متن در Canvas
زمینه پردازش کنوس (Canvas Rendering Context) دو متد برای رندر کردن متن دارد. این دو متد در ادامه همراه با توضیحات مربوطه فهرست شدهاند.
- ([fillText(text, x, y, [maxWidth: یک متن داده شده را در موقعیت مینویسد (رسم میکند).
- ([strokeText(text, x, y, [maxWidth: میزان ضخامت حاشیه یک متن داده شده را در موقعیت تنظیم میکند. دارای حالت انتخابی ضخامت حداکثر برای ترسیم است.
مثال متن در Canvas
در قطعه کد زیر، متن با استفاده از استایل رنگآمیزی (fillStyle) پیشفرض رنگ شده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 ctx.font = '48px serif';
4 ctx.fillText('Hello world', 10, 50);
5}
در خط سوم کد بالا، فونت و اندازه متن و در خط بعدی، محتوای متن و موقعیت آن در Canvas با استفاده از متد fillText تعیین شده است. تصویر خروجی در ادامه ملاحظه میشود.
استایل متن در Canvas
در مثال بالا، از خصوصیت «font» برای بزرگتر کردن اندازه متن نسبت به اندازه پیشفرض استفاده شد.
خصوصیتهای بیشتری برای تنظیم نحوه نمایش متن در Canvas وجود دارد که در این بخش از آموزش Canvas فهرست شدهاند.
- font = value: استایل محتوای متنی است که برای رسم متن استفاده میشود. این رشته از سینتکسی (نحو | Syntax) مشابه خصوصیت فونت در CSS استفاده میکند. فونت پیشفرض sans-serif با اندازه 10px است.
- textAlign = value: تنظیمات مربوط به ترازبندی (Alignment) است. مقادیر ممکن برای این خصوصیت start ،end ،left ،right یا center میباشند. مقدار پیشفرض آن، start در نظر گرفته شده است.
- textBaseline = value: این خصوصیت، مربوط به تنظیمات ترازبندی خط مبنا (Baseline) است. مقادیر ممکن برای آن، top ،hanging ،middle ،alphabetic ،ideographic و bottom است. مقدار پیشفرض آن alphabetic است.
- direction = value: برای جهتدهی به کار میرود. مقادیر ممکن برای خصوصیت جهتدهی شامل ltr ،rtl و inherit میشود. مقدار پیش فرض نیز، inherit در نظر گرفته شده است.
ممکن است خصوصیتهایی که در بالا فهرست شدهاند برای افرادی که با CSS کار کردهاند آشنا به نظر برسد. تصویر زیر از WHATWG [+] خطوط مبنای مختلفی که به وسیله خصوصیت textBaseline پشتیبانی میشوند را نشان میدهد.
مثال خط مبنای متن در Canvas
در کد زیر، نوع خصوصیت خط مبنا (textBaseline) به صورت آویخته ('hanging') انتخاب شده است. میتوان با تغییر نوع خط مبنا و استفاده از سایر حالتهای آن، تغییرات ایجاد شده را در خروجی مشاهده کرد.
1ctx.font = '48px serif';
2ctx.textBaseline = 'hanging';
3ctx.strokeText('Hello world', 0, 100);
خروجی کد بالا به صورت زیر است:
استفاده از تصاویر در Canvas
تا به اینجای کار در مطلب آموزش Canvas در HTML، اشکال به صورت دستی ساخته و استایلهایی به آنها اضافه شده است. یکی از ویژگیهای جالب در Canvas، امکان استفاده از تصاویر است. تصاویر را میتوان برای ترکیب عکس به صورت پویا (Dynamic Photo Compositing)، پسزمینه نمودارها، شبح در بازیهای کامپیوتری و سایر موارد بهکار گرفت.
میتوان از تصاویر مختلف با فرمتهایی که مرورگر بتواند پشتیبانی کند مثل، GIF، PNG یا JPEG استفاده کرد. همچنین، میتوان از تصاویر عناصر Canvas دیگری که در همان صفحه تولید شده، به عنوان منبع استفاده کرد. وارد کردن تصاویر به یک Canvas اساساً یک فرایند دو مرحلهای است. این فرایند در ادامه فهرست شده است.
- ارجاع دادن به یک شیٔ HTMLImageElement و یا یک عنصر Canvas دیگر به عنوان منبع؛ همچنین میتوان با استفاده از URL از یک عکس استفاده کرد.
- ترسیم عکس مربوطه روی Canvas با استفاده از تابع ()drawImage
در ادامه آموزش Canvas نحوه قرار دادن تصاویر (عکسها) روی Canvas آموزش داده شده است.
انتخاب منبع تصاویر
واسط برنامهنویسی کاربردی Canvas، میتواند از هر یک از انواع دادهای که در ادامه فهرست شدهاند به عنوان منبع تصویر استفاده کند.
- HTMLImageElement: اینها تصاویری هستند که با استفاده از واحد سازنده ()Image مثل عنصر <img> ایجاد میشوند.
- SVGImageElement: اینها عکسهایی هستند که با استفاده از عنصر <image> جاسازی میشوند.
- HTMLVideoElement: با استفاده از یک عنصر <video> اچتیامال به عنوان منبع تصویر، فریم (Frame) مربوطه را از ویدئو بر میدارد و از آن به عنوان یک تصویر استفاده میکند.
- HTMLCanvasElement: میتوان از یک عنصر Canvas دیگر به عنوان منبع تصویر استفاده کرد.
منابع فهرست شده در بالا، همگی به عنوان نوع CanvasImageSource شناخته میشوند. راههای بسیاری برای به کار گرفتن عکسها در یک Canvas وجود دارد که در ادامه آموزش Canvas در HTML، به هر کدام از این روشها پرداخته شده است.
استفاده از تصاویر همان صفحه
میتوان یک ارجاع به تصاویر همان صفحهای که Canvas در آن قرار گرفته با استفاده از یکی از روشهای زیر انجام داد.
- استفاده از مجموعه document.images
- استفاده از متد ()document.getElementsByTagName
- در صورت داشتن شناسه عکسی که قصد استفاده از آن وجود دارد، میتوان از ()document.getElementById برای بازیابی آن تصویر خاص استفاده کرد.
استفاده از تصاویر سایر دامنهها
با استفاده از صفت crossorigin یک عنصر <img> (که به وسیله خصوصیت HTMLImageElement.crossOrigin منعکس شده است)، میتوان درخواست مجوز برای بارگذاری یک تصویر از دامنه دیگری را جهت استفاده در فراخوانی ()drawImage انجام داد. اگر میزبان دامنه مربوطه اجازه دسترسی میان دامنهای به تصویر را صادر کرد، میتوان از آن تصویر در Canvas مورد نظر بدون خدشهدار کردن (Taint کردن) آن استفاده کرد.
در غیر این صورت، استفاده از آن تصویر موجب آلوده و خدشهدار شدن Canvas خواهد شد. یک Canvas خدشهدار یا آلوده به کنوسی گفته میشود که به هر دلیلی، دیگر ایمنی لازم را ندارد و هر گونه تلاشی برای بازیابی دادهها از Canvas موجب بروز اختلال (Exception) میشود.
استفاده از دیگر عنصرهای Canvas
درست مثل تصاویر عادی، میتوان از یک Canvas خاص با استفاده از متدهای ()document.getElementsByTagName و ()document.getElementById به دیگر عناصر Canvas دسترسی پیدا کرد. باید اطمینان حاصل شود که قبل از استفاده از Canvas منبع در Canvas مقصد، چیزی در آن رسم شده باشد. یکی از استفادههای کاربردیتر این قابلیت، میتواند استفاده از یک عنصر Canvas ثانویه به عنوان نمای کوچک شده (Thumbnail) مربوط به یک Canvas بزرگ دیگر باشد.
ساخت یک تصویر از بیخ و بن
روش دیگر، ایجاد اشیاء HTMLImageElement در یک اسکریپت است. برای انجام این کار، میتوان به راحتی از سازنده ()Image به صورت زیر استفاده کرد.
1var img = new Image(); // Create new img element
2img.src = 'myImage.png'; // Set source path
وقتی کد بالا اجرا شود، تصویر شروع به بارگذاری (Loading) میکند. اگر قبل از پایان بارگذاری، تصویر با ()drawImage فراخوانی شود، هیچ کاری انجام نخواهد شد و حتی در مرورگرهای قدیمیتر ممکن است اختلال ایجاد شود. بنابراین، باید مطمئن شد که از یک رویداد بارگذاری به صورت زیر استفاده شود تا فراخوانی قبل از بارگذاری تصویر اتفاق نیوفتد.
1var img = new Image(); // Create new img element
2img.addEventListener('load', function() {
3 // execute drawImage statements here
4}, false);
5img.src = 'myImage.png'; // Set source path
میتواند رویکرد خوبی باشد اگر تنها از یک تصویر خارجی استفاده شود. اما، در صورتی که نیاز به پیگیری بیش از یک عکس وجود داشته باشد، باید روش هوشمندانهتری را در پیش گرفت. پرداختن به روشهای پیش-بارگذاری (Pre-Loading Tactic) خارج از حیطه این مطلب است، اما باید این مسئله را در نظر داشت.
تعبیه یک تصویر به وسیله داده ها : URL
یک روش دیگر برای استفاده از تصاویر، از طریق «data:url» است. Data URLها امکان تعریف یک تصویر را به صورت یک رشته با کارکترهای کدگذاری شده مبنای ۶۴ مستقیماً در کد به وجود میآورند. در کد زیر، یک تصویر با استفاده از Data URL ایجاد شده است:
1var img = new Image(); // Create new img element
2img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
مزیتها و معایب استفاده از Data URL
یکی از برتریهای دیتا URLها این است که تصویر تولید شده بلافاصله و بدون رفت و برگشت به سرور در دسترس خواهد بود. یک مزیت احتمالی دیگر نیز این است که میتوان تمام کدهای CSS ،JavaScript ،HTML و تصاویر را در یک فایل گنجاند که باعث میشود حمل و نقل آن به محل دیگر آسان شود. برخی از معایب این روش این است که تصویر در حافظه نهان ذخیره (Cache) نشده و همچنین، در مورد تصاویر بزرگتر، URL کدگذاری شده میتواند بسیار طولانی شود.
رسم تصاویر در Canvas
در مثالی که در ادامه آمده، از یک تصویر خارجی به عنوان پسزمینهای برای یک نمودار خطی استفاده شده است. استفاده از پسزمینه میتواند باعث کوتاهتر شدن اسکریپت (کُدها) شود. چرا که با این کار، میتوان نیاز به کدنویسی برای تولید پسزمینه را از بین برد. در این مثال، تنها از یک تصویر استفاده شده است.
بنابراین، کنترلکننده رویداد «Load» برای اجرای گزاره ترسیم (Drawing Statement) به کار گرفته شده است. متُد ()drawImage تصویر پسزمینه را در مختصات قرار میدهد. این مختصات در بالا و سمت چپترین نقطه قرار گرفته است. در ادامه، کدهای مربوط به رسم یک نمودار به عنوان مثال ارائه شده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 var img = new Image();
4 img.onload = function() {
5 ctx.drawImage(img, 0, 0);
6 ctx.beginPath();
7 ctx.moveTo(30, 96);
8 ctx.lineTo(70, 66);
9 ctx.lineTo(103, 76);
10 ctx.lineTo(170, 15);
11 ctx.stroke();
12 };
13 img.src = 'https://mdn.mozillademos.org/files/5395/backdrop.png';
14}
نمودار حاصل شده از کد بالا، به صورت زیر است.
تبدیل در Canvas
در بخشهای ابتدایی آموزش Canvas درباره صفحه مشبک و فضای مختصاتی Canvas توضیحاتی ارائه شد. تا اینجا، تنها از فضای مشبک پیشفرض استفاده شد و اندازه کلی Canvas براساس نیاز تغییر داده شد. اما، با استفاده از تبدیل (Transformation)، روشهای بهتر و قدرتمندتری برای ترجمه موقعیت از محل ابتدایی به یک محل جدید، چرخاندن صفحه مشبک و حتی تغییر اندازه آن امکانپذیر خواهند بود.
ذخیره و بازیابی حالت
قبل از اینکه به متُدهای تبدیل پرداخته شود، بهتر است دو متد دیگر را معرفی کرد. این دو متُد، زمانی که قصد تولید ترسیمهای بسیار پیچیده وجود داشته باشد، ضروری بهنظر میرسند. در ادامه، این دو متد به همراه توضیحات لازم ارائه شده است.
- ()save: کل وضعیت فعلی Canvas را ذخیره میکند.
- ()restore: آخرین وضعیت ذخیره شده Canvas را بازیابی میکند.
وضعیتهای Canvas در یک پشته ذخیره میشوند. هر بار که متد ()save فراخوانی میشود، وضعیت فعلی ترسیم در بالای پشته قرار داده میشود. یک وضعیت ترسیم، شامل مواردی است که در ادامه فهرست شدهاند.
- تبدیلهایی که اعمال شدهاند (برای مثال translate ،rotate و scale)
- مقادیر فعلی صفتهای strokeStyle ،fillStyle ،globalAlpha ،lineWidth ،lineCap ،lineJoin ،miterLimit lineDashOffset ،shadowOffsetX ،shadowOffsetY ،shadowBlur ،shadowColor ،globalCompositeOperation ،font ،textAlign ،textBaseline ،direction ،imageSmoothingEnabled
- مسیر بُرش (Clipping Path)
میتوان متُد ()save را به تعداد دفعات دلخواه فراخوانی کرد. هر بار که متد ()restore فراخوانی میشود، آخرین وضعیت ذخیره شده از پشته خارج میشود و تمام تنظیمات ذخیره شده بازیابی میشوند.
مثال حالت ذخیره و بازیابی در Canvas
در این مثال سعی شده است که نحوه کارکرد پشته وضعیت ترسیم، به وسیله رسم مجموعهای از مستطیلهای متوالی نمایش داده شود. کد مربوط به این مثال در ادامه آمده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3
4 ctx.fillRect(0, 0, 150, 150); // Draw a rectangle with default settings
5 ctx.save(); // Save the default state
6
7 ctx.fillStyle = '#09F'; // Make changes to the settings
8 ctx.fillRect(15, 15, 120, 120); // Draw a rectangle with new settings
9
10 ctx.save(); // Save the current state
11 ctx.fillStyle = '#FFF'; // Make changes to the settings
12 ctx.globalAlpha = 0.5;
13 ctx.fillRect(30, 30, 90, 90); // Draw a rectangle with new settings
14
15 ctx.restore(); // Restore previous state
16 ctx.fillRect(45, 45, 60, 60); // Draw a rectangle with restored settings
17
18 ctx.restore(); // Restore original state
19 ctx.fillRect(60, 60, 30, 30); // Draw a rectangle with restored settings
20}
تصویر خروجی تولید شده بهوسیله کد بالا در ادامه آمده است.
اولین قدم، رسم یک مستطیل بزرگ با تنظیمات پیشفرض است. سپس، این وضعیت ذخیره میشود و تغییرات رنگآمیزی اعمال میشود. پس از آن، مستطیل آبی رنگ کوچکتر رسم و وضعیت، ذخیره میشود. مجدداً برخی تنظیمات رسم تغییر داده شده و سومین مستطیل شفاف رسم میشود. تا اینجا، کارها بسیار شبیه به مواردی است که در بخشهای قبل انجام شده است. اگرچه، وقتی اولین گزاره بازیابی (Restore) فراخوانی میشود، آخرین وضعیت ترسیم از بالای پشته حذف و تنظیمات بازیابی شده است.
اگر وضعیت به وسیله متد ()save ذخیره نشده بود، برای بازگشت به وضعیت قبلی تغییر رنگ داخلی و شفافیت باید به صورت دستی انجام میشد. این کار برای دو خصوصیت کار سادهای است اما، اگر خصوصیتهای بیشتری وجود داشته باشد، کدنویسی به سرعت بسیار طولانی خواهد شد. وقتی دومین گزاره ()restore فراخوانی میشود، وضعیت ابتدایی (وضعیت مربوط به قبل از اولین فراخوانی برای ذخیره) بازیابی شده و آخرین مربع مجدد به رنگ مشکی ترسیم خواهد شد.
ترجمه در Canvas
در این بخش از آموزش Canvas به اولین متد تبدیل به نام ()translate پرداخته شده است. این متد برای تغییر محل Canvas و مبدأ آن به یک نقطه دیگر در صفحه مشبک استفاده میشود. در فراخوانی (translate(x, y، ورودی مشخص کننده فاصله افقی انتقال و مشخص کننده میزان انتقال جدول مشبک در جهت عمودی است.
بهتر است وضعیت فعلی Canvas قبل از انجام هر گونه تبدیلی ذخیره شود. در اکثر موارد، بسیار راحتتر است که برای بازگشت به وضعیت اولیه، به جای انجام یک ترجمه برعکس (Reverse Translation)، متد restore فراخوانی شود. همچنین در صورتی که ترجمه در داخل یک حلقه در حال انجام است، چون رسم در خارج لبه Canvas انجام شده، ممکن است بخشی از رسم از دست برود.
یک مثال ترجمه در Canvas
این مثال، برخی از فواید ترجمه مبدأ مختصات Canvas را نشان میدهد. بدون متد ()translate، تمام مربعها در موقعیت یکسان رسم خواهند شد. همچنین، متد ()translate این آزادی عمل را به وجود میآورد که بدون نیاز به تنظیم مختصات به صورت دستی در تابع ()fillRect، مربع مربوطه را در هر جایی از Canvas قرار داد. این کار باعث میشود مسئله تا حدودی ساده، قابل درک و کاربردیتر شود.
در تابع ()draw، تابع ()fillRect نُه بار با استفاده از دو حلقه for فراخوانی شده است. در هر حلقه، Canvas ترجمه، مربع رسم و Canvas به وضعیت اولیه بازگردانده شده است. باید توجه شود که فراخوانی ()fillRect هر بار چطور از مختصات یکسانی با تکیه بر ()translate برای تنظیم موقعیت رسم استفاده میکند. کد مربوط به مثال ترجمه در ادامه آمده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 for (var i = 0; i < 3; i++) {
4 for (var j = 0; j < 3; j++) {
5 ctx.save();
6 ctx.fillStyle = 'rgb(' + (51 * i) + ', ' + (255 - 51 * i) + ', 255)';
7 ctx.translate(10 + j * 50, 10 + i * 50);
8 ctx.fillRect(0, 0, 25, 25);
9 ctx.restore();
10 }
11 }
12}
تصویر خروجی مربوط به کد بالا به صورت زیر است:
چرخش
در این بخش از آموزش Canvas دومین متد تبدیل، یعنی ()rotate معرفی شده است. از این متد برای چرخش Canvas حول مبدأ فعلی استفاده میشود.
(rotate(angle
با فراخوانی تابع Rotate، چرخش Canvas به صورت ساعتگرد و حول مبدأ فعلی به اندازه زاویه رادیان تعیین شده به وسیله ورودی angle انجام میشود. نقطه مرکزی چرخش همواره مبدأ Canvas خواهد بود. برای تغییر نقطه مرکزی چرخش، باید Canvas را با استفاده از متد ()translate جابهجا کرد.
مثال چرخش در Canvas
در این مثال، ابتدا از متد ()rotate برای چرخش یک مربع از مبدأ Canvas انجام شده و سپس، چرخش با کمک متد ()translate به مرکز مربع انتقال یافته است.
یادآوری: زاویهها نه بر حسب درجه بلکه، بر حسب رادیان است. برای تبدیل درجه به رادیان از فرمول زیر استفاده میشود:
کد مربوط به مثال چرخش در Canvas در ادامه آمده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3
4 // left rectangles, rotate from canvas origin
5 ctx.save();
6 // blue rect
7 ctx.fillStyle = '#0095DD';
8 ctx.fillRect(30, 30, 100, 100);
9 ctx.rotate((Math.PI / 180) * 25);
10 // grey rect
11 ctx.fillStyle = '#4D4E53';
12 ctx.fillRect(30, 30, 100, 100);
13 ctx.restore();
14
15 // right rectangles, rotate from rectangle center
16 // draw blue rect
17 ctx.fillStyle = '#0095DD';
18 ctx.fillRect(150, 30, 100, 100);
19
20 ctx.translate(200, 80); // translate to rectangle center
21 // x = x + 0.5 * width
22 // y = y + 0.5 * height
23 ctx.rotate((Math.PI / 180) * 25); // rotate
24 ctx.translate(-200, -80); // translate back
25
26 // draw grey rect
27 ctx.fillStyle = '#4D4E53';
28 ctx.fillRect(150, 30, 100, 100);
29}
برای چرخاندن مربع حول مرکز خودش، ابتدا مرکز Canvas با استفاده از متد Translate به مرکز مربع منتقل میشود و سپس، چرخش Canvas انجام میشود. پس از آن، Canvas مجدد به نقطه ترجمه شده و بعد مربع رسم میشود. تصویر مربوط به خروجی کد بالا در ادامه آمده است.
مقیاس گذاری در Canvas
در این بخش از آموزش Canvas متد تبدیل دیگری به نام مقیاسگذاری (Scaling) معرفی میشود. از مقیاسگذاری برای افزایش یا کاهش واحدهای مشبک Canvas استفاده میشود. از آن برای رسم شکلها و طرحهای بیتی تقلیل یافته یا بزرگ شده استفاده میشود.
(scale(x, y
با فراخوانی این متد، واحدهای Canvas در راستای افقی به اندازه و در راستای عمودی به میزان تغییر مقیاس داده میشوند. هر دو پارامتر اعداد حقیقی هستند. مقادیر کوچکتر از اندازه واحد را کاهش و مقادیر بزرگتر از اندازه آن را افزایش میدهند. به ازای مقادیر و برابر با یک، اندازه واحدها تغییری نمیکند.
با استفاده از اعداد منفی، میتوان محور را معکوس کرد. برای مثال با استفاده از کد زیر، سیستم رایج مختصات دکارتی بدست خواهد آمد که مبدأ آن در پایین و سمت چپترین نقطه Canvas است.
1translate(0,canvas.height); scale(1,-1);
به صورت پیشفرض، یک واحد در Canvas دقیقاً برابر با یک پیکسل است. اگر یک مؤلفه مقیاسگذاری اعمال شود، اندازه هر واحد به پیکسل تغییر خواهد کرد و بنابراین، شکلها با اندازه نصف رسم خواهند شد. به شیوه مشابه، با تغییر مؤلفه مقیاسگذاری به ، اندازه واحد افزایش پیدا خواهد کرد و یک واحد متناظر با دو پیکسل خواهد بود. این مسئله منجر به رسم شکلها با اندازه دو برابر خواهد شد.
مثال مقیاسگذاری در Canvas
در این مثال، شکلها با مؤلفههای مقیاسگذاری متفاوت رسم شدهاند. کد مربوطه در ادامه آمده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3
4 // draw a simple rectangle, but scale it.
5 ctx.save();
6 ctx.scale(10, 3);
7 ctx.fillRect(1, 10, 10, 10);
8 ctx.restore();
9
10 // mirror horizontally
11 ctx.scale(-1, 1);
12 ctx.font = '48px serif';
13 ctx.fillText('MDN', -135, 120);
14}
خروجی کد بالا به صورت زیر است:
تبدیل ها در Canvas
در نهایت، متدهای تبدیلی که در ادامه آموزش Canvas معرفی شدهاند، امکان اعمال مستقیم تغییرات در ماتریس تبدیل را فراهم میکنند. این متدها در ادامه معرفی شدهاند.
(transform(a, b, c, d, e, f
فراخوانی این متد، ماتریس تبدیل فعلی را در ماتریسی که به وسیله متغییرهای این متد توصیف میشود، ضرب میکند. ماتریس تبدیل به صورت زیر توصیف میشود:
\begin{array}{ccc} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{array}
پارامترهای این تابع به صورت زیر است:
- (a (m11: مقیاسگذاری افقی
- (b (m12: موربسازی افقی
- (c (m21: موربسازی عمودی
- (d (m22: مقیاسگذاری عمودی
- (e (dx: جابهجایی افقی
- (f (dy: جابهجایی عمودی
(setTransform(a, b, c, d, e, f
این متد، تبدیل فعلی را به ماتریس همانی (ماتریس یکه | Transformation Matrix) بازنشانی (Reset) میکند و متد ()transform را با همان آرگومانها بهکار میگیرد. اساساً، این کار تبدیل فعلی را باطل کرده و سپس، تبدیل تعیین شده را اعمال میکند. همه این موارد در یک مرحله انجام میشوند.
()resetTransform
فراخوانی این متد، تبدیل فعلی را به ماتریس همانی بازنشانی میکند. این متد، مشابه کار (ctx.setTransform(1, 0, 0, 1, 0, 0 را انجام میدهد.
مثال transform و setTransform
در این بخش از مطلب آموزش Canvas مثالی برای متدهای transform و setTransform ارائه میشود. کد مربوط به این مثال در ادامه آمده است.
1function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3
4 var sin = Math.sin(Math.PI / 6);
5 var cos = Math.cos(Math.PI / 6);
6 ctx.translate(100, 100);
7 var c = 0;
8 for (var i = 0; i <= 12; i++) {
9 c = Math.floor(255 / 12 * i);
10 ctx.fillStyle = 'rgb(' + c + ', ' + c + ', ' + c + ')';
11 ctx.fillRect(0, 0, 100, 10);
12 ctx.transform(cos, sin, -sin, cos, 0, 0);
13 }
14
15 ctx.setTransform(-1, 0, 0, 1, 100, 100);
16 ctx.fillStyle = 'rgba(255, 128, 255, 0.5)';
17 ctx.fillRect(0, 50, 100, 100);
18}
تصویر خروجی اسکریپت بالا در ادامه ملاحظه میشود.
جمعبندی
همانطور که بیان شد، Canvas به عنوان یک عنصر HTML برای رسم گرافیک به وسیله اسکریپت نویسی با جاوا اسکریپت مورد استفاده قرار میگیرد. بنابراین، آموزش Canvas در HTML اهمیت بسیار زیادی دارد. با استفاده از برچسب Canvas در HTML میتوان نمودار رسم کرد، تصاویر را ادغام کرد و تصاویر متحرک (انیمیشن) ساده و نسبتاً پیچیده ایجاد کرد.
Canvas این امکان را برای توسعهدهندگان فراهم میکند تا مدیریت دقیقتری روی پردازش و Rendering داشته باشند، اگرچه تمام جزئیات را باید به صورت دستی اداره کنند. بزرگترین مزیت Canvas دقیقاً برخلاف SVG، مدیریت عالی آن در تعداد زیادی اشیاء است. بنابراین، یادگیری آن میتواند بسیار مفید و کاربردی باشد.