предисловие
Я видел инструмент рисования, который поставляется с системой раньше, и это было очень интересно, поэтому я использовал реакцию и холст, чтобы реализовать простой инструмент рисования без реакции.Я в основном использовал реакцию, потому что я написал ее в исходном проекте.
Вот адрес в сети:Paint
Исходный код находится в Библиотеке под проектом:исходный код
выполнить
Функция кисти
<canvas
id="canvas"
onMouseDown={mouseEvent}
onMouseMove={mouseEvent}
onMouseUp={mouseEvent}
>
</canvas>
Сначала добавьте на холстmousedown, mousemove, mouseupТри слушают события.
Когда мышь нажата,isDrawПереключатель включается и выключается, когда мышь поднимается, так что управлениеmousemove, иначе он сработает, как только вы войдете в область холстаmousemoveмероприятие.
Здесь для краткости отслеживается событие mouseEvent, внутри которого, согласноevent.typeзапускать другую логику.
Мазок кисти к мазку идей:
-
Нажмите мышь, чтобы включить переключатель isDraw;
-
Перетащите и удерживайте мышь, чтобы сдвинуть триггер
mousemoveмероприятие -
Запишите информацию о положении щелчка мыши, здесь я использую двумерный массив, запишите ось X и ось Y соответственно.
-
Инициализируйте цвет, толщину и форму кисти
-
Начните рисовать линию, получите информацию о позиции, нарисованную мышью в массиве, и сделайте обводку между каждыми двумя точками, чтобы соединение точка-точка стало линией.
-
мышь вверх,
isDrawвыкл., отключить запускmousemove
Общая идея такова, вот реализация кода:
const mouseEvent = (e) => {
let ctx = canvas2D.getContext('2d')
e.persist()
if (e.type === 'mousedown') {
switch (active) {
case 'spray':
return canvas2D.style.backgroundColor = color
default:
isDraw = true
arr = []
return
}
}
if (e.type === 'mousemove' && isDraw) {
arr.push([e.pageX - canvas2D.offsetLeft, e.pageY - document.querySelector('.admin-box').offsetTop - 40])
switch (active) {
case 'pen':
ctx.strokeStyle = color
ctx.lineJoin = "round";
ctx.lineWidth = 5;
ctx.beginPath();
arr.length > 1 && ctx.moveTo(arr[arr.length - 2][0], arr[arr.length - 2][1]);
ctx.lineTo(arr[arr.length - 1][0], arr[arr.length - 1][1]);
ctx.closePath();
ctx.stroke(); //描边
return
default:
return
}
}
if (e.type === 'mouseup') {
setCanvasUrl(url => {
url.push(canvas2D.toDataURL())
return url
})
isDraw = false
}
}
Резинка
С ластиком здесь немного хитрости: он покрывает цвет кисти фоновым цветом, так что создается впечатление, что он был стерт. Идея такая же, как и идея с кистью, просто измените цвет на цвет фона.
case 'eraser':
ctx.strokeStyle = canvas2D.style.backgroundColor || '#ccc'
ctx.lineJoin = "round";
ctx.lineWidth = 50;
ctx.beginPath();
arr.length > 1 && ctx.moveTo(arr[arr.length - 2][0], arr[arr.length - 2][1]);
ctx.lineTo(arr[arr.length - 1][0], arr[arr.length - 1][1]);
ctx.closePath();
ctx.stroke(); //描边
return
Ведро краски
Это самое простое, получить цвет на доске цветов, заменить цвет фона, и все в порядке.
нарисовать прямоугольник
Чтобы нарисовать прямоугольникclearRectа такжеstrokeRectДва метода, они принимают 4 параметра, это координаты начальной точки X, Y и длина и ширина прямоугольника.
Идеи:
каждый триггерmousemoveНа самом деле рисуются прямоугольники, но мы можем очистить предыдущую область перед тем, как будет нарисован каждый прямоугольник.
clearRectэто очистить следы в прямоугольнике
Похоже, мы нарисовали прямоугольник
case 'rectangle':
let left = arr[0][0]
let top = arr[0][1]
let prewidth = arr.length > 1 && arr[arr.length - 2][0] - left
let preheight = arr.length > 1 && arr[arr.length - 2][1] - top
let width = arr[arr.length - 1][0] - left
let height = arr[arr.length - 1][1] - top
ctx.beginPath();
ctx.lineWidth = "6";
ctx.strokeStyle = "red";
ctx.clearRect(left, top, prewidth, preheight)
ctx.strokeRect(left, top, width, height);
return
Отменить предыдущую функцию
Это использует холстdrawImageа такжеtoDataURLдва метода.
Идеи:
-
После каждой операции пропускайте полотно через
toDataURLМетод IMG Сохранить вверх, чтобы повернуть, нажмите на массив -
Когда вы нажимаете вспомнить, пройдите
drawImageМетод загружает графику холста из последней операции. -
Удалите последние данные массива, чтобы облегчить следующую операцию вызова.
-
Определить, был ли массив опустошен, если он опустошен, операция больше не будет разрешена
код показывает, как показано ниже:
const recallClick = (e) => {
let ctx = canvas2D.getContext('2d')
let step = canvasUrl.length - 1
if (step >= 0) {
step--;
ctx.clearRect(0, 0, 1000, 1000);
let canvasPic = new Image();
canvasPic.src = canvasUrl[step];
canvasPic.addEventListener('load', () => {
ctx.drawImage(canvasPic, 0, 0);
});
setCanvasUrl(canvasUrl => {
canvasUrl.pop()
return canvasUrl
})
} else {
console.log('不能再继续撤销了');
}
}
Функция загрузки
пройти черезtoDataURLПолучите текущую графику CANVAS.
Создайте вкладку A, назначьте ей адрес, выполните загрузку события клика. Эта реализация относительно проста, но это общая идея, или всплывающее окно также может быть изменено в соответствии со сценой.
код показывает, как показано ниже:
const downloadImg = () => {
var url = canvas2D.toDataURL('image/png');
var a = document.createElement('a');
document.body.appendChild(a);
a.href = url;
a.download = '我的绘画';
a.target = '_blank';
a.click();
}
палитра цветов
используется здесьreact-colorплагин.
конец
На этом этапе идея простой чертежной доски ясно объяснена, и вы можете разработать на этой основе больше функций в будущем.
fighting~