Графический редактор на Canvas и JS + PHP

Пример редактора тапа «Paint» с картинкой-подложкой, на которой можно рисовать мышью с последующей отправкой на сервер.

Основой редактора является элемент <canvas>, также понадобятся кнопки для отмены действий и полной очистки холста.

<a href="#" id="undo">Отменить</a>
<a href="#" id="clear">Очистить</a>

<form id="form" action="" method="post">
	<div class="paint-canvas">
		<canvas id="canvas" width="705" height="353"></canvas>
		<input id="canvas_img" type="hidden" name="canvas_img" value="">
	</div>
	<div class="paint-submit">
		<input type="submit" name="send" value="Отправить форму">
	</div>
</form>
HTML

JS-код редактора (c jQuery):

window.addEventListener("load", function onWindowLoad(){
	var canvas = document.getElementById("canvas");
	var ctx = canvas.getContext("2d");
	var points = [];
	
	// Загрузка изображения в canvas
	var img = new Image();
	img.src = 'https://snipp.ru/demo/730/bg.jpg';	
	img.addEventListener('load', function(){
		ctx.drawImage(img, 0, 0);

		var mouseX = 0;
		var mouseY = 0;
		
		// Стиль линии
		ctx.strokeStyle = 'red';
		ctx.lineWidth = 2; 
		var isDrawing = false;

		// Обработчики рисования мышкой
		canvas.addEventListener('mousedown', function(event) {
			setMouseCoordinates(event);
			isDrawing = true;
			ctx.beginPath();
			ctx.moveTo(mouseX, mouseY);
				
			points.push({
				x: mouseX,
				y: mouseY,
				mode: "begin"
			});
		});

		canvas.addEventListener('mousemove', function(event) {
			setMouseCoordinates(event);
			if(isDrawing){
				ctx.lineTo(mouseX, mouseY);
				ctx.stroke();
			   	points.push({
					x: mouseX,
					y: mouseY,
					mode: "draw"
				});					
			}
		});

		canvas.addEventListener('mouseup', function(event) {
			setMouseCoordinates(event);
			isDrawing = false;
				
			points.push({
				x: mouseX,
				y: mouseY,
				mode: "end"
			});
		});

		function setMouseCoordinates(event) {
			mouseX = event.offsetX;
			mouseY = event.offsetY;
		}

		// Кнопка «Очистить»
		$('#clear').click(function(){
			ctx.clearRect(0, 0, canvas.width, canvas.height);
			ctx.drawImage(img, 0, 0);
			return false;			
		});

		// Функции для кнопки «Отменить»
		function redrawAll() {
			if (points.length == 0) {
				return;
			}
			ctx.clearRect(0, 0, canvas.width, canvas.height);
			ctx.drawImage(img, 0, 0);
			for (var i = 0; i < points.length; i++) {
				var pt = points[i];
				if (pt.mode == "begin") {
					ctx.beginPath();
					ctx.moveTo(pt.x, pt.y);
				}
				ctx.lineTo(pt.x, pt.y);
				if (pt.mode == "end" || (i == points.length - 1)) {
					ctx.stroke();
				}
			}
			ctx.stroke();
		}

		function undoLast() {
			points.pop();
			redrawAll();
		}

		// Кнопка «Отменить»
		var interval;
		$("#undo").mousedown(function(){
			interval = setInterval(undoLast, 50);
		}).mouseup(function(){
			clearInterval(interval);
		}).click(function(){
			return false;			
		});

		$('#form').submit(function(){
			$('#canvas_img').val(canvas.toDataURL("image/jpg"));
			return true;
		});
	});
});
JS

CSS-стили для canvas:

#canvas {
	display: block;
	box-sizing: border-box;
	border: 1px solid #e0e0e0;
	cursor: crosshair;
	margin: 0 0 20px;
}
CSS

Результат:

Сохранение canvas на сервере

При отправки формы, с помощью метода toDataURL содержимое canvas помещается в скрытое поле <input id="canvas_img" type="hidden" name="canvas_img" value=""> в виде строки base64:

data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby....

На сервере остается её декодировать и сохранить в файл:

<?php
if (!empty($_POST['canvas_img'])) {
	$encodedData = explode(",", $_POST['canvas_img']);
	$encodedData = str_replace(' ', '+', $encodedData[1]);
	$decocedData = base64_decode($encodedData); 
	$NewFileName = __DIR__ . '/' . time() . '.jpg';
	file_put_contents($NewFileName, $decocedData);
}
PHP
24.09.2021, обновлено 07.04.2022
7603

Комментарии

, чтобы добавить комментарий.

Другие публикации

Как изменить Favicon сайта из JavaScript
Для замены Favicon во вкладке браузера достаточно у элемента link rel="icon" в атрибуте href указать путь до нового...
12503
+2
Contenteditable – текстовый редактор
Если добавить атрибут contenteditable к элементу, его содержимое становится доступно для редактирования пользователю, а...
43743
+34
Календарь jQuery UI Datepicker
DatePicker – хороший и функциональный плагин для выбора даты, легко настраивается и привязывается к стандартному полю ввода формы.
77610
+5
Перетаскивание элементов Drag and drop (jQuery UI Droppable)
UI Droppable – плагин, который позволяет сделать перетаскивание элементов мышью (Drag&Drop).
8607
0
Генерация счета на оплату PDF PHP
С помощью расширения dompdf можно легко сформировать PDF файл. По сути, dompdf - это конвертер HTML в PDF который...
66053
+33
Бот Телеграм на PHP
Примеры как зарегистрировать бота в Телеграм, описание и взаимодействие с основными методами API.
141482
+44