Создание инструмента «Ластик объекта» в приложении «Белая доска»Javascript

Форум по Javascript
Ответить
Anonymous
 Создание инструмента «Ластик объекта» в приложении «Белая доска»

Сообщение Anonymous »

Я создаю приложение для доски, подобное exelidraw. Я пытаюсь создать инструмент ластик с использованием элемента Canvas, который при столкновении с любой фигурой или рисунком полностью удаляет их, как в excalidraw.
Я пробовал установить свойство globalCompositeOperation CanvasAPI в значение Destination-out, но этот подход удалит фигуру (или рисунок) попиксельно, как в msPaint. Но мне нужен подход на основе объектов, когда ластик удаляет всю фигуру (или рисунок) при столкновении с фигурой (или рисунком) в любой точке.
Ниже приведен код того, как я подход на основе пикселей, который я использовал для создания функциональности ластика.
(просто грубый код для логики ластика)
type Shape = {type: "eraser"; points: {x: number; y: number;}[]};

export class Game {

private canvas: HTMLCanvasElement;
private ctx: CanvasRenderingContext2D;
private existingShapes: Shape[];
private clicked: boolean;
private startX = 0;
private startY = 0;
private selectedTool: Tool = "eraser";
private currentPencilStroke: { x: number; y:number }[] = []

constructor(canvas: HTMLCanvasElement) {

this.canvas = canvas;
this.ctx = canvas.getContext("2d")!;
this.existingShapes = [];
this.clicked = false;
this.init();
this.initHandlers();
this.initMouseHandlers();
}

destroy() {
this.canvas.removeEventListener("mousedown", this.mouseDownHandler);
this.canvas.removeEventListener("mouseup", this.mouseUpHandler);
this.canvas.removeEventListener("mousemove", this.mouseMoveHandler);
}

// ClearCanvas(){} -> Clears everything; Redraws the permanent shapes; Draw the current preview shape

clearCanvas() {
this.ctx.globalCompositeOperation = "source-over";

// Clears the entire canvas:
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

// Sets the background to black:
this.ctx.fillStyle = "rgba(0, 0, 0)";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

// Redraws Existing Shapes

this.existingShapes.map((shape) => {

this.ctx.globalCompositeOperation = "source-over"
this.ctx.strokeStyle = "rgba(255, 255, 255)";

// Drawing logic of each shape type
if(shape.type === "eraser"){
this.ctx.strokeStyle = "rgba(0, 0, 0)";
this.ctx.lineWidth = 20
if(shape.points && shape.points.length > 1){
this.ctx.beginPath();
this.ctx.moveTo(shape.points[0].x, shape.points[0].y);
shape.points.forEach(point => {
this.ctx.lineTo(point.x, point.y);
});
this.ctx.stroke();
}
}
});
}

// mouseDownHandler: User presses the mouse button; shapes begin to draw; Records where the user started to clicking

mouseDownHandler = (e: MouseEvent) => {
this.clicked = true;
this.startX = e.clientX;
this.startY = e.clientY;
if (this.selectedTool === "eraser") {
this.currentPencilStroke = [{x: this.startX, y: this.startY}]
}
};

// mouseUpHandler: When user release the mouse button, it finalizes the shape and saves it permanently

mouseUpHandler = (e: MouseEvent) => {

this.clicked = false;
const width = e.clientX - this.startX;
const height = e.clientY - this.startY;
const selectedTool = this.selectedTool;
let shape: Shape | null = null;

if(selectedTool === "eraser" && this.currentPencilStroke.length > 1) {

shape = {

type: "eraser",
points: this.currentPencilStroke
}
this.currentPencilStroke = [];
}

// mouseMoveHandler: While user drag the mouse it shows live preview of the shape.

mouseMoveHandler = (e: MouseEvent) => {
if (this.clicked) {

const width = e.clientX - this.startX;
const height = e.clientY - this.startY;
this.clearCanvas();
this.ctx.strokeStyle = "rgba(255, 255, 255)";
const selectedTool: Tool = this.selectedTool;

if(selectedTool === "eraser") {

this.currentPencilStroke.push({x: e.clientX, y: e.clientY})
this.ctx.globalCompositeOperation = "source-over"
this.ctx.strokeStyle = "rgba(0, 0, 0)";
this.ctx.lineWidth = 20
this.ctx.beginPath();
this.ctx.moveTo(this.currentPencilStroke[0].x, this.currentPencilStroke[0].y)
this.currentPencilStroke.forEach(point => {
this.ctx.lineTo(point.x, point.y)
});
this.ctx.stroke()
this.ctx.globalCompositeOperation = "source-over"
}
}
};

initMouseHandlers() {

this.canvas.addEventListener("mousedown", this.mouseDownHandler);
this.canvas.addEventListener("mouseup", this.mouseUpHandler);
this.canvas.addEventListener("mousemove", this.mouseMoveHandler);
}
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... pplication
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»