От автора: как Вы знаете в данное время веб-сайты, да и, конечно же, интернет стали настолько популярны, что применяются и решают определенные поставленные задачи практически во всех сферах деятельности человека. Таких как работа, учеба, развлечения, охрана здоровья и т.д. То есть другими словами, если сейчас мы говорим сайт, то мы не предполагаем, что это будет простая страница, на которой отображен текст и некоторое количество изображений. Мы предполагаем некий ресурс, который в той или иной степени обладает определенным функционалом и что то, предлагает или же выполняет для его посетителей. А значит, перед разработчиками постоянно ставят достаточно сложные и интересные задачи, которые приходится решать и поэтому, в этом уроке я хотел бы поделиться с Вами одной из таких задач.
Достаточно недавно, я работал по разработке сервиса связанного с заказами определенных медицинских препаратов, и соответственно для заказа, человек в качестве подтверждения своей личности, должен был оставить некую подпись. Конечно, в самом простейшем случае можно было загрузить картинку с добавленной подписью, но такой вариант не удобен, так как под рукой не всегда есть сканер, поэтому добавление подписи, нужно было сделать online, то есть на лету. Для реализации поставленной задачи я принял решение, использовать инструмент canvas, который как раз позволяет, что то нарисовать в браузере и затем отправить нарисованную фигуру непосредственно на сервер для последующей обработки. Кстати в итоге получился вот такой результат.
Таким образом, в данном уроке мы с Вами реализуем функционал создания изображений на лету, прямиком в браузере.
Теперь несколько слов о том, что такое canvas. Конечно, Вы можете спросить, почему несколько, почему бы в полной мере не осветить данную тему? И ответ банально прост – это нехватка времени, потому как для этого потребуется полноценный видео-курс. Итак, canvas от англ. canvas — “холст” – это элемент спецификации HTML5, который предназначенный для создания растрового двухмерного изображения при помощи JavaScript. И, как правило, используется для рисования графиков для статей и игрового поля в некоторых браузерных играх.
Теперь, давайте рассмотрим, простую HTML страницу, которую мы будем использовать в данном уроке:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"/> <title>Paint</title> </head> <body> <div id = "wrapper"> <canvas id = "paint" width = "500" height = "400"></canvas> <form method = "POST" action = "server.php" enctype = "multipart/form-data"> <input type = "text" id = "canvasData" name = "canvasData" /> <input type = "button" id = "clear" name = "clear" value = "Очистить" /> <input type = "submit" value = "Сохранить" /> </form> </div> </body> <script src="jquery-3.1.1.min.js"></script> <script src="script.js"></script> </html> |
Как Вы видите, все предельно просто. Обратите внимание, что элементу canvas присвоен идентификатор paint, который мы будем использовать, для выбора этого блока при помощи JavaScript. Форма, которая так же присутствует на странице, необходима для отправки изображения на сервер и последующего его сохранения.
При этом, на экране мы увидим следующий результат, если запустить файл в браузере.
Далее переходи в файл script.js и добавим первые строки кода:
1 |
var canvas, tool, context; |
Первым делом объявляем три глобальные переменные:
canvas – для хранения выбранного элементы canvas;
tool — для хранения пользовательского объекта рисования фигуры;
context – для хранения объекта CanvasRenderingContext2D, который необходим для создания 2d фигур.
Затем, опишем, функцию обработчик события load. То есть код данной функции, выполнится только тогда, когда контент страницы, будет полностью загружен.
1 2 3 |
window.addEventListener('load',function() { init(); },false); |
И как Вы видите, все что мы делаем – это вызываем на исполнение функцию init(), которую сейчас же и опишем.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function init() { canvas = document.getElementById('paint'); if(!canvas) { alert('Error'); } if(!canvas.getContext) { alert('Error'); } context = canvas.getContext('2d'); context.strokeStyle = '#000000'; context.lineJoin = 'round'; context.lineWidth = 4; tool = new tool_pencil(); canvas.addEventListener('mousedown',func_canvas,false); canvas.addEventListener('mousemove',func_canvas,false); canvas.addEventListener('mouseup',func_canvas,false); } |
Теперь давайте по порядку разберем, каждую строчку кода, написанной функции. Итак, для начала по идентификатору, выбираем элемент canvas.
1 2 3 4 |
canvas = document.getElementById('paint'); if(!canvas) { alert('Error'); } |
Затем вызываем на исполнение метод getContext(‘2d’) – который возвращает контекст рисования на холсте, или null, если идентификатор контекста не определен. При этом в качестве первого аргумента, передаем строку ‘2d’, тем самым указывая, что нам необходимо получить в качестве результат объект CanvasRenderingContext2D представляющий контекст, для рисования двумерных фигур.
1 2 3 4 |
if(!canvas.getContext) { alert('Error'); } context = canvas.getContext('2d'); |
Далее определяем цвет и толщину линии рисования.
1 2 |
context.strokeStyle = '#000000'; context.lineWidth = 4; |
Функционал отрисовки фигуры, будет сосредоточен в объекте tool, который мы создаем с помощью функции конструктора.
1 |
tool = new tool_pencil(); |
Затем, регистрируем три обработчика событий для процесса создания фигуры.
1 2 3 |
canvas.addEventListener('mousedown',func_canvas,false); canvas.addEventListener('mousemove',func_canvas,false); canvas.addEventListener('mouseup',func_canvas,false); |
Почему три, можете спросить Вы. Собственно, ответ вытекает из самого процесса рисования с помощью мыши. То есть мы, в начале, нажимаем кнопку мыши, затем перемещаем курсор и для окончания отпускаем клавишу. Теперь, давайте опишем функцию конструктор, для создания объекта tool.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
function tool_pencil() { var tool = this; tool.started = false; tool.mousedown = function (event) { context.beginPath(); context.moveTo(event._x, event._y); tool.started = true; } tool.mousemove = function (event) { if(tool.started) { context.lineTo(event._x, event._y); context.stroke(); } } tool.mouseup = function (event) { if(tool.started) { //this.mousemove(event); tool.started = false; imgUpdate(); } } } |
Обратите внимание, что в начале, мы объявляем свойство started, которое будет содержать значение true, в том случае, если рисование было начато. В данной функции, мы определяем три свойства, имена которых полностью совпадают с темы событиями, для которых мы определили функции обработчики. Начало, рисования – нажатие кнопки мыши:
1 2 3 4 5 |
tool.mousedown = function (event) { context.beginPath(); context.moveTo(event._x, event._y); tool.started = true; } |
Как Вы видите, мы обращаемся к переменной context и вызываем метод beginPath(), тем самым задаем начало рисования. Затем вызываем на исполнение метод moveTo(event._x, event._y). То есть задаем начальную точку рисования с координатами, определенными свойствами объекта события event. Ну и, конечно же, свойству tool.started, присваиваем значение true.
Далее описываем процесс перемещения мыши – рисование фигуры:
1 2 3 4 5 6 |
tool.mousemove = function (event) { if(tool.started) { context.lineTo(event._x, event._y); context.stroke(); } } |
Вызываемый метод lineTo(), рисует прямую линию от начальной точки, до координат, передаваемых в качестве аргумента, а это свойства объекта event – как Вы видите. Метод stroke() – делает нарисованную линию видимой. И наконец, завершающий этап рисования – отпускание кнопки мыши.
1 2 3 4 5 6 |
tool.mouseup = function (event) { if(tool.started) { tool.started = false; imgUpdate(); } } |
Собственно здесь, мы присваиваем свойству started, значение false и вызываем на исполнение функцию imgUpdate(), которая обновит код изображения в текстовом поле формы. Теперь необходимо описать функцию обработчик для трех событий формирования фигуры.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function func_canvas(event) { if(event.layerX || event.layerX == 0) { event._x = event.layerX; event._y = event.layerY; } else if(event.offsetX || event.offsetX == 0) { event._x = event.offsetX; event._y = event.offsetY; } var foo = tool[event.type]; if(foo) { foo(event); } } |
В этой функции, мы рассчитываем координаты курсора мыши и записываем их в соответствующие свойства объекта event (объекта сработанного события). Теперь, так как в нашем распоряжении есть объект tool, с тремя методами, имена которых полностью совпадают с событиями, для которых были зарегистрированы обработчики – мы можем, используя тип события, вызвать на исполнение, соответствующий метод объекта tool.
Для обновления кода изображения в поле формы – опишем код функции imgUpdate().
1 2 3 |
function imgUpdate() { document.getElementById('canvasData').value = canvas.toDataURL('image/png'); } |
Для получения кода нарисованного изображения, необходимо вызвать метод toDataURL(), у объекта canvas. Теперь, достаточно сохранить изменения и обновить браузер.
Теперь мы можем нарисовать произвольную фигуру. Для очистки холста, можно зарегистрировать обработчик события для клика мышью по кнопке очистить.
1 2 3 |
document.getElementById('clear').addEventListener('click',function() { context.clearRect(0,0,canvas.width, canvas.height); },false); |
Метод clearRect(), очищает прямоугольную область заданную координатами, переданными в качестве аргументов.
Для сохранения изображения в файл, достаточно отправить код изображения на сервер, где в качестве обработчика, можно использовать следующий скрипт.
1 2 3 4 5 6 |
<?php $img = $_POST['canvasData']; $img = str_replace('data:image/png;base64,', '', $img); $fileData = base64_decode($img); $fileName = 'photo.png'; file_put_contents($fileName, $fileData); |
Вот собственно и все о чем я хотел рассказать Вам в этом уроке. Всего Вам доброго и удачного кодирования.