Я создаю приложение для доски, подобное 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
Создание инструмента «Ластик объекта» в приложении «Белая доска» ⇐ Javascript
Форум по Javascript
-
Anonymous
1771153955
Anonymous
Я создаю приложение для доски, подобное exelidraw. Я пытаюсь создать инструмент ластик с использованием элемента Canvas, который при столкновении с любой фигурой или рисунком полностью удаляет их, как в excalidraw.
Я пробовал установить свойство globalCompositeOperation CanvasAPI в значение Destination-out, но этот подход удалит фигуру (или рисунок) попиксельно, как в msPaint. Но мне нужен [b]подход на основе объектов[/b], когда ластик удаляет всю фигуру (или рисунок) при столкновении с фигурой (или рисунком) в любой точке.
Ниже приведен код того, как я [b]подход на основе пикселей[/b], который я использовал для создания функциональности ластика.
(просто грубый код для логики [b]ластика[/b])
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);
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79889646/creating-an-object-eraser-tool-in-a-whiteboard-application[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия