• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Урок по созданию Drawing Tools'ов

  • Автор темы 1ive
  • Дата начала
1

1ive

Эта статья научит вас шаг за шагом, разработке простого веб-приложения для рисования с помощью HTML5 "canvas" и JavaScript.
Целью данной статьи является исследование процесса создания простого приложения, по ходу Вы узнаете:

Как создать динамический HTML5 "холст"
Каковы возможности будущего холста
Совместимость браузеров с HTML5


Определяем цели:

Давайте создадим веб-приложение, где пользователь сможет динамически рисовать на холсте HTML5.

Что будет использовать пользователь (простите за тавталогию)?
Книжка-раскраска приходит на ум, а это означает, что нужны нам как минимум мелки.
Наш следующий инструмент – карандаш.

Хотя в реальном мире такое маловероятно, но, я думаю, что мы должны быть в состоянии стереть мелки.
И поэтому третьим нашим инструментом будет ластик.

И потому, что я всегда был поклонником Sharpie, наш последний инструмент будет маркер.

Для каждого инструмента нужно дать возможность выбрать цвет (за исключением, может быть, нашего ластика)

Не будем сильно все нагружать и дадим нашим пользователем 4 различных цвета на выбор.

Точно также дадим нашим пользователем по 4 различных размера для маркера и мелка

Итак наше приложение должно иметь следующее:

-3 инструмента: карандаш, маркер, ластик
-4 цвета на выбор
-4 размера на выбор

Так как мы делаем книжку-раскраску, должна быть, собственно картинка.

Подготовка HTML5 Canvas: разметка

Нам нужны только линии разметки, а все остальное будет в скрипте.
Код:
<canvas id="canvasInAPerfectWorld" width="490" height="220"></canvas>
Небольшое отступление...
HTML5 все еще является новой технологией и некоторые браузеры не поддерживают тега canvas, так что давайте использовать подобную разметку:
Код:
<div id="canvasDiv"></div>

Подготовка HTML5 Canvas: скрипты

Чтобы подготовить наш холст мы хотим использовать:
Код:
context = document.getElementById('canvasInAPerfectWorld').getContext("2d");
Однако IE не знает тегов “canvas” и если бы мы в разметки использовали первый вариант — в IE бы это стало местом ошибки.
Вместо этого мы создаем элемент canvas в JS и добавляем его в наш DIV, который назвали canvasDiv
Код:
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', canvasWidth);
canvas.setAttribute('height', canvasHeight);
canvas.setAttribute('id', 'canvas');
canvasDiv.appendChild(canvas);
if(typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
context = canvas.getContext("2d");
Для совместимости с Internet Explorer мы должны подключить дополнительный скрипт: .



Создание простого «холста»

Прежде чем добавлять различные опции, давайте создадим основу нашего приложения.

Оно будет состоять из 4 событий мыши и двух функций: AddClick для записи данных мыши и Redraw, которая будет рисовать согласно этим данным.

Событие MouseDown: Когда пользователь нажимает на холсте мы записываем положение через функцию AddClick в массив.
Мы устанавливаем булевую переменную paint со значением «true» (мы увидим, почему в сек).
Наконец ,обновляем холст функцией Redraw.
Код:
$('#canvas').mousedown(function(e){
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;

paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
Событие Mouse Move: Перемещение нажатой мыши по холсту мы хотим показать как движение кончика маркера по бумаге..
Переменная paint даст нам знать, нажимает ли виртуальный маркер на холст или нет. Если значение параметра paint - “true”, то записываем значение в массив.И снова «Redraw»
Код:
$('#canvas').mousemove(function(e){
if(paint){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
События Mouse Up и Mouse Leave, думаю, объяснять не нужно (название говорит само за себя).
Код:
$('#canvas').mouseup(function(e){
paint = false;
});

$('#canvas').mouseleave(function(e){
paint = false;
});

Функция addClick сохраняет позицию клика.
Код:
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;

function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
Redraw - функция, которая творит чудеса.
Каждый раз, когда вызывается функция холст очищается, и все перерисовывается с нуля.
Конечно, мы могли бы сделать функцию более эффективной заставив ее перерисовывать только изменившиеся элементы, но давайте оставим все как есть.

Установим свойства цвета, формы и ширины. Тогда каждый раз, используя маркер, мы будем рисовать линии.
Код:
function redraw(){
canvas.width = canvas.width; // Clears the canvas

context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;

for(var i=0; i < clickX.length; i++)
{		
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
Вот что у нас получилось:

Добавляем цвета:

Теперь можно дать нашим пользователем несколько цветов для оформления.
Все, что нужно сделать, это объявить несколько глобальных переменных и немного отредактировать функцию Redraw.

Объявите четыре цвета переменных: colorPurple, colorGreen, colorYellow, colorBrown с соответствующими названию значениями цветов, переменную для хранения текущего цвета: curColor, и массив clickColor, в который будет заноситься информация о цвете, выбранном в момент клика.
Код:
var colorPurple = "#cb3594";
var colorGreen = "#659b41";
var colorYellow = "#ffcf33";
var colorBrown = "#986928";

var curColor = colorPurple;
var clickColor = new Array();

Функция AddClick должна изменена для возможности записи выбранного цвета в момент клика.
Код:
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
clickColor.push(curColor);
}
Так как цвет теперь может изменяться, нам необходимо обновить функцию Redraw,
для перерсовки именнов тех цветах, которые выбирал пользователь во время рисования.
Код:
function redraw(){
/* context.strokeStyle = "#df4b26"; */
context.lineJoin = "round";
context.lineWidth = 5;

for(var i=0; i < clickX.length; i++)
{		
context.beginPath();
if(clickDrag[i] && i){
contex.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.strokeStyle = clickColor[i];
context.stroke();
}
}

Теперь все выглядит так:

Добавляем размеры


Так же, как мы добавили цвета, давайте добавим несколько размеров на выбор: "маленький", "нормальный", "большой" и "огромный".

Нам нужно еще несколько глобальных переменных: clickSize и curSize.
Код:
var clickSize = new Array();
var curSize = "normal";
Функция addClick тоже должна быть обновлена для записи размера, выбранного выбранного пользователем на момент клика.
Код:
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
clickColor.push(curColor);
clickSize.push(curSize);

}

Обновление функции Redraw для обработки новых размеров.
Код:
function redraw(){
context.lineJoin = "round";
class="highlight delete">/* context.lineWidth = 5; */
for(var i=0; i < clickX.length; i++)
{		
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.strokeStyle = clickColor[i];
context.lineWidth = radius;
context.stroke();
}
}

С размерами наше приложение будет выглядеть так:

Добавляем инструменты

Итак, мы определились, что нам нужны маркер,мелок и ластик. Три инструмента, Давайте же сделаем их.

Нам будут нужны еще две глобальные переменные: clickTool и curTool.
Код:
var clickTool = new Array();
var curTool = "crayon";
Опять же изменим addClick
Код:
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
if(curTool == "eraser"){
clickColor.push("white");
}else{
clickColor.push(curColor);
}
clickColor.push(curColor);
clickSize.push(curSize);
}

И Redraw
Код:
function redraw(){
context.lineJoin = "round";
for(var i=0; i < clickX.length; i++)
{		
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.strokeStyle = clickColor[i];
context.lineWidth = radius;
context.stroke();
}
if(curTool == "crayon") {
context.globalAlpha = 0.4;
context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight);
}
context.globalAlpha = 1;
}

Инструменты добавлены, можно считать что все уже готово:

Создание книжки-раскраски (если нужен просто Drawing Tool, можно пропустить)

С самого начала мы делали книжку-раскраску, так давайте же добавим самое главное — картинку.


Объявляем переменную outlineImage
Код:
var outlineImage = new Image();
Присваиваем ей путь к изображению
Код:
function prepareCanvas(){
...

outlineImage.src = "images/watermelon-duck-outline.png";

Обновляем функцию Redraw для прорисовки изображения на холсте используя метод drawImage
Код:
function redraw(){
...

context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);
}

После добавления изображения в раскраску получится что-то подобное:

Окончательные детали
Мы почти у цели!
Эти последние детали являются необязательными: ограничить область рисования в прямоугольник на холсте и использовать оставшуюся часть холста для нашего GUI (ака кнопки).

Мы используем будем использовать методы clip, save и restore.Эти методы в настоящее время не поддерживается Internet Explorer.


Последние действие — нарисовать и разместить все эти кнопки так, чтобы получилось красиво.
Здесь я использую стандартные методы JS и, думаю объяснять ничего не придется.




 
V

vital

шикарно. Спасибо, интересно. Пока не прочитал все, но дома обязательно проверю)
 
1

1ive

Старался)
Может еще скринов сделать?
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!