Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development

Вивчення Canvas з нуля: Просунуті методи малювання

by
Read Time:10 minsLanguages:
This post is part of a series called Canvas From Scratch.
Canvas From Scratch: Introducing Canvas
Canvas From Scratch: Transformations and Gradients

Ukrainian (українська мова) translation by AlexBioJS (you can also view the original English article)

У попередньому посібнику цієї серії ви дізналися про елемент canvas та основах, потрібних для малювання на ньому. У цій статті я продемонструю деякі більш просунуті методи малювання.


Підготовлюємо сторінку

Ми будемо використовувати тий самий шаблон HTML, що й у попередньому посібнику, тому відкрийте свій улюблений редактор та додайте туди наступний код:

Це всього-на-всього базова HTML-сторінка з елементом canvas та деяким кодом JavaScript, що виконується одразу після завантаження моделі DOM (* Document Object Model – об'єктна модель документа. Тут і надалі примітка перекладача). Нічого фантастичного тут нема.


Малюємо кола

В останньому посібнику я показав вам, як малювати базові фігури та шляхи (* послідовність ліній на «полотні»); у цій статті я покажу вам, як впоратися з більш складним завданням – малюванням кіл. Це не так просто, як могло би здатися, проте при цьому зовсім нічого складного нема.

У Сanvas нема методу, що дозволяє вам намалювати коло за допомогою одного рядка коду, як у випадку з малюванням прямокутників (метод fillRect). Замість цього ми повинні малювати кола за допомогою шляху, що прорисовується за допомогою методу arc; коло – всього-на-всього дуга, величина угла якої складає 360 градусів. Це так, оскільки кола – дуже складні фігури, і в методі arc передбачено все потрібне для малювання будь-яких його сегментів. Наприклад ви могли би захотіти намалювати тільки півколо. Метод arc дозволяє вам це здійснити. Ви би могли навіть  використовувати разом метод arc та стандартні прямі шляхи для прорисовування кусочків піци та четвертин кола.

Я поясню вам скоро, як працює метод arc, але поки давайте намалюємо коло завдяки додаванню наступного коду нижче змінної ctx:

За допомогою нього буде прорисовано коло, розташоване трохи далі верхнього лівого кута полотна:

Здається, все просто, чи не так? Так воно і є, проте давайте розглянемо більш детально, що відбувається.

Метод arc всього приймає шість аргументів:

  • Перший – координата x початкової точки (центр кола).
  • Другий – координата y початкової точки.
  • Третій – радіус кола.
  • Четвертий – початковий кут кола.
  • П'ятий – кінцевий кут кола.
  • Та шостий - напрям, у якому буде прорисовано коло (якщо true, то коло буде прорисовано проти годинникової стрілки, якщо false –  за годинниковою стрілкою).

У всевдокоді (* мова, що нагадує мову програмування і яку використовують для опису структури програми) метод arc з його аргументами виглядав би наступний чином:

Перші три аргументи говорять самі за себе, як і останній, проте як щодо початкового та кінцевого кутів? Давайте поясню.

Як я згадав раніше, кола – просто дуги, величина кута яких складає 360 градусів. У Сanvas дугою вважається крива лінія, що починається на деякій відстані від початкової точки, тобто на відстані, що дорівнює величині радіуса. Крива починається з кута, значення якого визначається за допомогою аргументу для задання стартового кута (четвертого), і йде уздовж окружності уявного кола до тих пір, поки не достигне кута, значення якого визначається за допомогою аргументу для задання кінцевого кута (п'ятого). Звучить просто, чи не так?

Можливо, на іллюстрації буде зрозуміліше:

Певне, це виглядає чуднувато, проте все стає на свої місця, тільки-но ви зрозумієте цю цонцепцію.

Кути у Сanvas

На цьому етапі, гадаю, варто відмітити, що кути у Сanvas вимірюються у радіанах (* центральний кут, довжина дуги якого дорівнює радіусу цієї дуги), а не градусах. Це означає, що кути вимірюються від 0 до pi, помноженого на два. Відлік кутів у Сanvas також починають з правого боку, що проілюстровано на наступному зображенні:

Якщо ви зовсім недолюблюєте радіани, то ви можете перерахувати градуси у радіани за допомогою наступної формули на JavaScript:

Вона дуже проста і дуже важлива, якщо ви хочете мати діло з градусами.


Криві Без'є (* відноситься до класу кубічних функцій. Створюється за допомогою мінімум чотирьох точок: двох базових – початку та кінця – і двох проміжних (що називаються керуючими мітками-маніпуляторами), що впливають на форму кривої, але звичайно не лежать на ній безпосередньо)

Роботати з дугами весело та все таке, але їх потенціал доволі обмежений для реалізації тих кривих, що можуть бути створені за допомогою Canvas. Для реалізації більш складних кривих ми звертаємося до методів quadraticCurveTo та  bezierCurveTo для створення кривих Без'є. Ці методи дозваляють вам створювати викривлені шляхи з радіусом, що йде не від центру кривої, а також створювати шляхи з великою кількістю кривих.

Для вказання того, де і як прорисовати криві Без'є, використовуються керуючі мітки-маніпулятори. Наприклад у методі quadraticCurveTo використовується одна мітка-маніпулятор, у той час як в bezierCurveTo – дві. Ознайомтеся з наступною ілюстрацією, щоб зрозуміти, як ці мітки-маніпулятори впливають на вигляд кривої:

Якщо ви вже користувалися векторними графічними редакторами на зразок Adobe Illustrator раніше, то ви, можливо, вже комфортно себе почуваєте при роботі з цими типами кривих.

Давайте перейдемо до написання коду та створимо квадратичну криву Без'є (задається трьома опорними точками). Замініть код для рисування дуги наступним:

У результаті виконання цього коду буде прорисовано кривий шлях, що виглядає подібно тому, що було показано на ілюстрації вище:

Метод quadraticCurveTo приймає чотири аргументи:

  • Перший – координата х мітки-маніпулятора.
  • Другий – координата у мітки-маніпулятора.
  • Третій – координата х кінцевої опорної точки шляху.
  • Четветрй – координата у кінцевої опорної точки шляху.

У псевдокоді метод quadraticCurveTo виглядав би наструпним чином:

Стартова точка – та, в якій у даний момент знаходиться кінцева точка шляху. Наприклад у коді вище ми перемістили стартову точку шляху за допомогою виклику методу moveTo.

Давайте ускладнимо завадання та створимо кубічну криву Без'є. Замініть попередній код наступним:

Завдяки ньому буде прорисовано кривий шлях, що виглядає подібно тому, що зображено на ілюстрації вище:

Метод bezierCurveTo приймає шість аргументів:

  • Преший – координата x першої мітки-маніпулятора.
  • Другий – координата у першої мітки-маніпулятора.
  • Третів – координата х другої мітки-маніпулятора.
  • Четвертий – координата у другої мітки-маніпулятора.
  • П'ятий – координата х кінцевої опорної точки шляху.
  • І шостий – координата у кінцевої опорної точки шляху.

У псевдокоді метод quadraticCurveTo виглядав би наступним чином:

Самі по собі криві Без'є не особливо вражаючі, проте коли вони використовуються разом зі звичайними шляхами або повторно, можна отримати доволі вражаючий результат. Вони дозволяють вам створювати всі варіанти складних та чудових фігур у Сanvas!

Можливо, вам цікаво було би ознайомитися з плагіном Ai->Canvas для Adobe Illustrator, що дозволяє вам експортувати ваш фантастичний векторний малюнок у вигляді коду Сanvas. Він доволі класний та зекономить вам безліч часу!


Стан малювання

У попередньому посібнику цієї серії я докладно описав, як змінити стильове оформлення контурів та заповнених кольором графічних об'єктів і як змінити товщину лінії. Одна з проблем, про яку варто знати, що виникає при зміні цих властивостей, – те, що ви повинні будете вручну змінити кольори та ширину лінії назад, якщо хочете знову використовувати початково задані кольори та ширину лінії. На щастя, як завжди, є кращий спосіб це здійснити; він виконується за допомогою стану малювання.

Стан малювання у Сanvas – по суті елемент стеку (* структура даних – список, додавання та видалення елементів до якого здійснюється за принципом LIFO (Last In, First Out – "останнім прийшов – першим обслугований")), у якому ви можете зберігати поточні стилі та потім знову ними скористатися пізніше.

Це оманливо проста концепція, проте при повному її розумінні перед вами відкриваються надзвичайні можливості. У дійсності, стан малювання містить величезний масив візуальної інформації про полотно, наприклад про матрицю перетворення (* матриця, що містить коефіцієнти рівнянь, згідно з якими виконується перетворення), вирізану область та наступні властивості: globalAlpha, globalCompositeOperation, strokeStyle, fillStyle, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, font, textAlign та  textBaseline. Більшість з них будуть новими для вас, так що не турбуйтеся. Ви навчитеся працювати з трансформаціями та іншими кльовими можливостями на зразок додавання тіней у наступному посібнику.

Зберігання стану малювання

Використовувати стан малювання надзвичано просто, але для повного розуміння цієї концепції може знадобитися деякий час. Замініть код, який додали у попередньому розділі, наступним:

Це і все, що вам потрібно для зберігання стану малювання, – єдиний виклик методу save. Я ж казав, це просто!

Тут ми змінюємо стильове оформлення заповнених кольором графічних об'єктів canvas на синій колір і потім зберігаємо стан малювання, завдяки чому поточний стан додається до стеку, про який я говорив раніше. За налаштуванням стек порожній.

Важливо пам'ятати, що стек працює неначе купа бумаг на вашому столі; перший елемент стеку розташован знизу, а найновіший – на верхівці. Якщо ви знову хочете добратися до першого елементу, то вам для початку доведеться видалити всі елементи поверх нього. Ця система називається FILO (* First In Last Out – «першим прийшов – останнім обслугований») або LIFO, якщо поглянути на неї з іншого боку.

Відновлення стану малювання

Наявність можливості зберегти стан малювання – чудово, проте наявність можливості власне їм знову скористатися – по суті більш корисна. Для цього ми будемо використовувати метод restore.

Додайте наступний код до коду, який додали раніше:

У результаті буде прорисовано ще один прямокутник на полотні, проте у цей раз іншого кольору (червоного):

Поки що все, як звичайно, але що якщо ви хочете повернутися до використання синього кольору та намалювати інший прямокутник? Що ж, ви могли би задати у якості значення стильового оформлення заповнених кольором графічних об'єктів вручну синій колір, проте це було би стомливо. Давайте спробуємо скористатися методом restore та подивимося, що вийде.

Додайте наступний код:

У результаті буде прорисовано ще один прямокутник, проте у цей раз початкового кольору:

Наскільки це було просто? Завдяки виклику restore відбулося витягнення та видалення останнього стану малювання, доданого до стеку, і подальше застосування його до canvas, у результаті чого ви економите безліч часу. Ладно, що ж, можливо у цьому прикладі ви не зекономили силу-силенну часу, проте зекономили би, якщо би змінили значення всіляких властивостей та застосували трансформації на полотні.

Використання великої кількості станів малювання

Тепер ви знаєте, як використовувати стан малювання для випадку, коли зберігається єдиний стан, але що відбудеться при зберіганні великої кількості станів малюваня? Уважі, певне, пам'ятають, що я послався на стек, як на купу бумаг, – останнім прийшов, першим вийшов. Давайте подивимося, як це реалізується у коді.

Оновіть попередній код для додавання зберігання стану малювання після встановлення у якості значення стильового оформлення заповнених кольором графічних об'єктів червоного кольору:

Незважаючи на те що це майже той самий код, як і раніше, все буде по-іншому, оскільки останній стан малювання містить у якості значення всластивості fillStyle червоний колір:

Для того щоб відновити початковий стан (синій колір стильового оформлення заповнених кольором графічних об'єктів), вам буде потрібно викликати метод restore ще раз, так що додайте наступний код:

Завдяки цьому перший елемент стеку буде вибрно, видалено та застосовано до полотна, у результаті чого фігуру буде забарвлено у синій:

За допомогою використання великої кількості станів малювання на зразок цього ви можете зберегти безліч часу. Це доволі винахідливо!


Підведення підсумків

Сподіваюся, я доволі докладно виклав матеріал. Деякі концепції, розглянуті тут, доволі просунуті, і я би рекомендував вам перечитати статтю та поекспериментувати з кодом для кращого розуміння викладеного матеріалу.

У наступному посібнику ви вивчете, як виконувати транформації на полотні і додавати тіні та градієнти. Нас чекає дещо надзвичайне!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.