canvas-react-easy 1.0.7 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Border.js +17 -4
- package/dist/components/Tools.js +3 -2
- package/dist/tools/ImageTool.js +7 -9
- package/dist/tools/Text.js +10 -6
- package/dist/tools/TextHoverTool.js +43 -0
- package/dist/tools/Tool.js +13 -0
- package/dist/types/components/Border.d.ts +5 -3
- package/dist/types/components/Tools.d.ts +5 -1
- package/dist/types/tools/Text.d.ts +2 -0
- package/dist/types/tools/TextHoverTool.d.ts +13 -0
- package/dist/types/tools/Tool.d.ts +5 -0
- package/package.json +1 -1
- package/src/components/Border.tsx +22 -5
- package/src/components/Tools.tsx +7 -5
- package/src/tools/ImageTool.ts +8 -10
- package/src/tools/Text.ts +19 -12
- package/src/tools/TextHoverTool.ts +58 -0
- package/src/tools/Tool.ts +15 -0
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect } from "react";
|
|
3
3
|
import Tools from "./Tools";
|
|
4
4
|
import Canvas from "./Canvas";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
5
|
+
import toolState from "../store/ToolState";
|
|
6
|
+
import CanvasState from "../store/CanvasState";
|
|
7
|
+
import { TextHoverTool } from "../tools/TextHoverTool";
|
|
8
|
+
const Border = ({ userName = "Гость" }) => {
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
var _a;
|
|
11
|
+
// активируем инструмент "имя пользователя" сразу после монтирования
|
|
12
|
+
if (CanvasState.canvas) {
|
|
13
|
+
(_a = toolState.tool) === null || _a === void 0 ? void 0 : _a.clearEvents();
|
|
14
|
+
const tool = new TextHoverTool(CanvasState.canvas, userName);
|
|
15
|
+
tool.listen();
|
|
16
|
+
toolState.setTool(tool);
|
|
17
|
+
}
|
|
18
|
+
}, [userName]);
|
|
19
|
+
return (_jsxs("div", { style: { position: "relative" }, children: [_jsx(Tools, { userName: userName }), _jsx(Canvas, {})] }));
|
|
20
|
+
};
|
|
8
21
|
export default Border;
|
package/dist/components/Tools.js
CHANGED
|
@@ -6,7 +6,8 @@ import { Rectangle } from "../tools/Rectangle";
|
|
|
6
6
|
import { Circle } from "../tools/Circle";
|
|
7
7
|
import { TextTool } from "../tools/Text";
|
|
8
8
|
import { ImageTool } from "../tools/ImageTool";
|
|
9
|
-
const Tools = () => {
|
|
9
|
+
const Tools = ({ userName = "Гость" }) => {
|
|
10
|
+
// универсальный выбор инструмента
|
|
10
11
|
const selectTool = (ToolClass) => {
|
|
11
12
|
var _a, _b;
|
|
12
13
|
if (!CanvasState.canvas)
|
|
@@ -18,6 +19,6 @@ const Tools = () => {
|
|
|
18
19
|
(_b = tool.listen) === null || _b === void 0 ? void 0 : _b.call(tool); // если инструмент имеет метод listen
|
|
19
20
|
toolState.setTool(tool);
|
|
20
21
|
};
|
|
21
|
-
return (_jsxs("div", { style: { marginBottom: "10px" }, children: [_jsx("button", { onClick: () => selectTool(Brush), children: "\u041A\u0438\u0441\u0442\u044C" }), _jsx("button", { onClick: () => selectTool(Rectangle), children: "\u041F\u0440\u044F\u043C\u043E\u0443\u0433\u043E\u043B\u044C\u043D\u0438\u043A" }), _jsx("button", { onClick: () => selectTool(Circle), children: "\u041A\u0440\u0443\u0433" }), _jsx("button", { onClick: () => selectTool(TextTool), children: "\u0422\u0435\u043A\u0441\u0442" }), _jsx("button", { onClick: () => selectTool(ImageTool), children: "\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435" })] }));
|
|
22
|
+
return (_jsxs("div", { style: { marginBottom: "10px", display: "flex", gap: "5px" }, children: [_jsx("button", { onClick: () => selectTool(Brush), children: "\u041A\u0438\u0441\u0442\u044C" }), _jsx("button", { onClick: () => selectTool(Rectangle), children: "\u041F\u0440\u044F\u043C\u043E\u0443\u0433\u043E\u043B\u044C\u043D\u0438\u043A" }), _jsx("button", { onClick: () => selectTool(Circle), children: "\u041A\u0440\u0443\u0433" }), _jsx("button", { onClick: () => selectTool(TextTool), children: "\u0422\u0435\u043A\u0441\u0442" }), _jsx("button", { onClick: () => selectTool(ImageTool), children: "\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435" })] }));
|
|
22
23
|
};
|
|
23
24
|
export default Tools;
|
package/dist/tools/ImageTool.js
CHANGED
|
@@ -15,21 +15,19 @@ export class ImageTool extends Tool {
|
|
|
15
15
|
}
|
|
16
16
|
listen() {
|
|
17
17
|
const handler = (e) => {
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
18
|
+
const evt = e;
|
|
19
|
+
const canvas = evt.target;
|
|
20
|
+
const x = evt.pageX - canvas.offsetLeft;
|
|
21
|
+
const y = evt.pageY - canvas.offsetTop;
|
|
21
22
|
const url = prompt("Введите ссылку на изображение");
|
|
22
23
|
if (!url)
|
|
23
24
|
return;
|
|
24
25
|
const img = new Image();
|
|
25
26
|
img.src = url;
|
|
26
|
-
img.onload = () =>
|
|
27
|
-
|
|
28
|
-
};
|
|
29
|
-
// удаляем обработчик после первого использования
|
|
30
|
-
canvas.removeEventListener("mousedown", handler);
|
|
27
|
+
img.onload = () => this.ctx.drawImage(img, x, y);
|
|
28
|
+
this.clearEvents(); // удаляем обработчики после использования
|
|
31
29
|
};
|
|
32
|
-
this.
|
|
30
|
+
this.addListener("mousedown", handler);
|
|
33
31
|
}
|
|
34
32
|
onClickHandler(e) {
|
|
35
33
|
return __awaiter(this, void 0, void 0, function* () {
|
package/dist/tools/Text.js
CHANGED
|
@@ -2,21 +2,25 @@ import Tool from "./Tool";
|
|
|
2
2
|
export class TextTool extends Tool {
|
|
3
3
|
constructor(canvas) {
|
|
4
4
|
super(canvas);
|
|
5
|
+
this.fontSize = 24; // размер шрифта в пикселях
|
|
6
|
+
this.fontFamily = "Arial"; // шрифт по умолчанию
|
|
5
7
|
this.listen();
|
|
6
8
|
}
|
|
7
9
|
listen() {
|
|
8
10
|
const handler = (e) => {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
11
|
+
const evt = e;
|
|
12
|
+
const canvas = evt.target;
|
|
13
|
+
const x = evt.pageX - canvas.offsetLeft;
|
|
14
|
+
const y = evt.pageY - canvas.offsetTop;
|
|
12
15
|
const text = prompt("Введите текст");
|
|
13
16
|
if (text) {
|
|
17
|
+
// Устанавливаем шрифт перед рисованием
|
|
18
|
+
this.ctx.font = `${this.fontSize}px ${this.fontFamily}`;
|
|
14
19
|
this.ctx.fillText(text, x, y);
|
|
15
20
|
}
|
|
16
|
-
|
|
17
|
-
target.removeEventListener("mousedown", handler);
|
|
21
|
+
this.clearEvents();
|
|
18
22
|
};
|
|
19
|
-
this.
|
|
23
|
+
this.addListener("mousedown", handler);
|
|
20
24
|
}
|
|
21
25
|
onClickHandler(e) {
|
|
22
26
|
const target = e.target;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import Tool from "./Tool";
|
|
2
|
+
export class TextHoverTool extends Tool {
|
|
3
|
+
constructor(canvas, userName) {
|
|
4
|
+
super(canvas);
|
|
5
|
+
this.fontSize = 18;
|
|
6
|
+
this.fontFamily = "Arial";
|
|
7
|
+
this.color = "black";
|
|
8
|
+
this.userName = userName;
|
|
9
|
+
// Создаём overlay-канвас поверх основного
|
|
10
|
+
this.overlayCanvas = document.createElement("canvas");
|
|
11
|
+
this.overlayCanvas.width = canvas.width;
|
|
12
|
+
this.overlayCanvas.height = canvas.height;
|
|
13
|
+
this.overlayCanvas.style.position = "absolute";
|
|
14
|
+
this.overlayCanvas.style.left = canvas.offsetLeft + "px";
|
|
15
|
+
this.overlayCanvas.style.top = canvas.offsetTop + "px";
|
|
16
|
+
this.overlayCanvas.style.pointerEvents = "none"; // мышь проходит через него
|
|
17
|
+
canvas.parentElement.appendChild(this.overlayCanvas);
|
|
18
|
+
this.overlayCtx = this.overlayCanvas.getContext("2d");
|
|
19
|
+
}
|
|
20
|
+
listen() {
|
|
21
|
+
const moveHandler = (evt) => {
|
|
22
|
+
const e = evt; // кастим к MouseEvent
|
|
23
|
+
// Очищаем overlay
|
|
24
|
+
this.overlayCtx.clearRect(0, 0, this.overlayCanvas.width, this.overlayCanvas.height);
|
|
25
|
+
// Координаты мыши относительно канваса
|
|
26
|
+
const x = e.pageX - this.canvas.offsetLeft;
|
|
27
|
+
const y = e.pageY - this.canvas.offsetTop;
|
|
28
|
+
// Рисуем имя чуть выше курсора
|
|
29
|
+
this.overlayCtx.font = `${this.fontSize}px ${this.fontFamily}`;
|
|
30
|
+
this.overlayCtx.fillStyle = this.color;
|
|
31
|
+
this.overlayCtx.fillText(this.userName, x, y - 20);
|
|
32
|
+
};
|
|
33
|
+
this.addListener("mousemove", moveHandler);
|
|
34
|
+
}
|
|
35
|
+
clearEvents() {
|
|
36
|
+
super.clearEvents();
|
|
37
|
+
// Удаляем overlay с DOM
|
|
38
|
+
if (this.overlayCanvas.parentElement) {
|
|
39
|
+
this.overlayCanvas.parentElement.removeChild(this.overlayCanvas);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export default TextHoverTool;
|
package/dist/tools/Tool.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
export default class Tool {
|
|
2
2
|
constructor(canvas) {
|
|
3
3
|
this.canvas = canvas;
|
|
4
|
+
this.events = [];
|
|
4
5
|
this.ctx = canvas.getContext("2d");
|
|
6
|
+
this.events = [];
|
|
5
7
|
this.clearEvents();
|
|
6
8
|
}
|
|
9
|
+
// сохраняем слушатели, чтобы потом удалять
|
|
10
|
+
addListener(type, handler) {
|
|
11
|
+
this.canvas.addEventListener(type, handler);
|
|
12
|
+
this.events.push({ type, handler });
|
|
13
|
+
}
|
|
7
14
|
clearEvents() {
|
|
15
|
+
// удаляем все зарегистрированные слушатели
|
|
16
|
+
this.events.forEach(({ type, handler }) => {
|
|
17
|
+
this.canvas.removeEventListener(type, handler);
|
|
18
|
+
});
|
|
19
|
+
this.events = [];
|
|
20
|
+
// очищаем стандартные свойства
|
|
8
21
|
this.canvas.onmousedown = null;
|
|
9
22
|
this.canvas.onmouseup = null;
|
|
10
23
|
this.canvas.onmousemove = null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Tool from "./Tool";
|
|
2
|
+
export declare class TextHoverTool extends Tool {
|
|
3
|
+
userName: string;
|
|
4
|
+
fontSize: number;
|
|
5
|
+
fontFamily: string;
|
|
6
|
+
color: string;
|
|
7
|
+
private overlayCanvas;
|
|
8
|
+
private overlayCtx;
|
|
9
|
+
constructor(canvas: HTMLCanvasElement, userName: string);
|
|
10
|
+
listen(): void;
|
|
11
|
+
clearEvents(): void;
|
|
12
|
+
}
|
|
13
|
+
export default TextHoverTool;
|
|
@@ -2,5 +2,10 @@ export default class Tool {
|
|
|
2
2
|
canvas: HTMLCanvasElement;
|
|
3
3
|
constructor(canvas: HTMLCanvasElement);
|
|
4
4
|
ctx: CanvasRenderingContext2D;
|
|
5
|
+
events: Array<{
|
|
6
|
+
type: string;
|
|
7
|
+
handler: EventListener;
|
|
8
|
+
}>;
|
|
9
|
+
addListener(type: string, handler: EventListener): void;
|
|
5
10
|
clearEvents(): void;
|
|
6
11
|
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
2
|
import Tools from "./Tools";
|
|
3
3
|
import Canvas from "./Canvas";
|
|
4
|
+
import toolState from "../store/ToolState";
|
|
5
|
+
import CanvasState from "../store/CanvasState";
|
|
6
|
+
import { TextHoverTool } from "../tools/TextHoverTool";
|
|
7
|
+
|
|
8
|
+
interface BorderProps {
|
|
9
|
+
userName?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Border: React.FC<BorderProps> = ({ userName = "Гость" }) => {
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
// активируем инструмент "имя пользователя" сразу после монтирования
|
|
15
|
+
if (CanvasState.canvas) {
|
|
16
|
+
toolState.tool?.clearEvents();
|
|
17
|
+
const tool = new TextHoverTool(CanvasState.canvas, userName);
|
|
18
|
+
tool.listen();
|
|
19
|
+
toolState.setTool(tool);
|
|
20
|
+
}
|
|
21
|
+
}, [userName]);
|
|
4
22
|
|
|
5
|
-
const Border = observer(() => {
|
|
6
23
|
return (
|
|
7
|
-
<div>
|
|
8
|
-
<Tools />
|
|
24
|
+
<div style={{ position: "relative" }}>
|
|
25
|
+
<Tools userName={userName} />
|
|
9
26
|
<Canvas />
|
|
10
27
|
</div>
|
|
11
28
|
);
|
|
12
|
-
}
|
|
29
|
+
};
|
|
13
30
|
|
|
14
31
|
export default Border;
|
package/src/components/Tools.tsx
CHANGED
|
@@ -7,8 +7,12 @@ import { Circle } from "../tools/Circle";
|
|
|
7
7
|
import { TextTool } from "../tools/Text";
|
|
8
8
|
import { ImageTool } from "../tools/ImageTool";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface ToolsProps {
|
|
11
|
+
userName?: string;
|
|
12
|
+
}
|
|
11
13
|
|
|
14
|
+
const Tools: React.FC<ToolsProps> = ({ userName = "Гость" }) => {
|
|
15
|
+
// универсальный выбор инструмента
|
|
12
16
|
const selectTool = (ToolClass: any) => {
|
|
13
17
|
if (!CanvasState.canvas) return;
|
|
14
18
|
|
|
@@ -19,17 +23,15 @@ const Tools = () => {
|
|
|
19
23
|
const tool = new ToolClass(CanvasState.canvas);
|
|
20
24
|
tool.listen?.(); // если инструмент имеет метод listen
|
|
21
25
|
toolState.setTool(tool);
|
|
22
|
-
};
|
|
26
|
+
};
|
|
23
27
|
|
|
24
|
-
|
|
25
28
|
return (
|
|
26
|
-
<div style={{ marginBottom: "10px" }}>
|
|
29
|
+
<div style={{ marginBottom: "10px", display: "flex", gap: "5px" }}>
|
|
27
30
|
<button onClick={() => selectTool(Brush)}>Кисть</button>
|
|
28
31
|
<button onClick={() => selectTool(Rectangle)}>Прямоугольник</button>
|
|
29
32
|
<button onClick={() => selectTool(Circle)}>Круг</button>
|
|
30
33
|
<button onClick={() => selectTool(TextTool)}>Текст</button>
|
|
31
34
|
<button onClick={() => selectTool(ImageTool)}>Изображение</button>
|
|
32
|
-
|
|
33
35
|
</div>
|
|
34
36
|
);
|
|
35
37
|
};
|
package/src/tools/ImageTool.ts
CHANGED
|
@@ -7,25 +7,23 @@ export class ImageTool extends Tool {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
listen() {
|
|
10
|
-
const handler = (e:
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
10
|
+
const handler = (e: Event) => {
|
|
11
|
+
const evt = e as MouseEvent;
|
|
12
|
+
const canvas = evt.target as HTMLCanvasElement;
|
|
13
|
+
const x = evt.pageX - canvas.offsetLeft;
|
|
14
|
+
const y = evt.pageY - canvas.offsetTop;
|
|
14
15
|
|
|
15
16
|
const url = prompt("Введите ссылку на изображение");
|
|
16
17
|
if (!url) return;
|
|
17
18
|
|
|
18
19
|
const img = new Image();
|
|
19
20
|
img.src = url;
|
|
20
|
-
img.onload = () =>
|
|
21
|
-
this.ctx.drawImage(img, x, y);
|
|
22
|
-
};
|
|
21
|
+
img.onload = () => this.ctx.drawImage(img, x, y);
|
|
23
22
|
|
|
24
|
-
// удаляем
|
|
25
|
-
canvas.removeEventListener("mousedown", handler);
|
|
23
|
+
this.clearEvents(); // удаляем обработчики после использования
|
|
26
24
|
};
|
|
27
25
|
|
|
28
|
-
this.
|
|
26
|
+
this.addListener("mousedown", handler);
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
async onClickHandler(e: MouseEvent) {
|
package/src/tools/Text.ts
CHANGED
|
@@ -5,20 +5,27 @@ export class TextTool extends Tool {
|
|
|
5
5
|
super(canvas);
|
|
6
6
|
this.listen();
|
|
7
7
|
}
|
|
8
|
+
fontSize: number = 24; // размер шрифта в пикселях
|
|
9
|
+
fontFamily: string = "Arial"; // шрифт по умолчанию
|
|
8
10
|
|
|
9
11
|
listen() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
const handler = (e: Event) => {
|
|
13
|
+
const evt = e as MouseEvent;
|
|
14
|
+
const canvas = evt.target as HTMLCanvasElement;
|
|
15
|
+
const x = evt.pageX - canvas.offsetLeft;
|
|
16
|
+
const y = evt.pageY - canvas.offsetTop;
|
|
17
|
+
|
|
18
|
+
const text = prompt("Введите текст");
|
|
19
|
+
if (text) {
|
|
20
|
+
// Устанавливаем шрифт перед рисованием
|
|
21
|
+
this.ctx.font = `${this.fontSize}px ${this.fontFamily}`;
|
|
22
|
+
this.ctx.fillText(text, x, y);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this.clearEvents();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
this.addListener("mousedown", handler);
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
onClickHandler(e: MouseEvent) {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Tool from "./Tool";
|
|
2
|
+
|
|
3
|
+
export class TextHoverTool extends Tool {
|
|
4
|
+
userName: string;
|
|
5
|
+
fontSize: number = 18;
|
|
6
|
+
fontFamily: string = "Arial";
|
|
7
|
+
color: string = "black";
|
|
8
|
+
|
|
9
|
+
private overlayCanvas!: HTMLCanvasElement;
|
|
10
|
+
private overlayCtx!: CanvasRenderingContext2D;
|
|
11
|
+
|
|
12
|
+
constructor(canvas: HTMLCanvasElement, userName: string) {
|
|
13
|
+
super(canvas);
|
|
14
|
+
this.userName = userName;
|
|
15
|
+
|
|
16
|
+
// Создаём overlay-канвас поверх основного
|
|
17
|
+
this.overlayCanvas = document.createElement("canvas");
|
|
18
|
+
this.overlayCanvas.width = canvas.width;
|
|
19
|
+
this.overlayCanvas.height = canvas.height;
|
|
20
|
+
this.overlayCanvas.style.position = "absolute";
|
|
21
|
+
this.overlayCanvas.style.left = canvas.offsetLeft + "px";
|
|
22
|
+
this.overlayCanvas.style.top = canvas.offsetTop + "px";
|
|
23
|
+
this.overlayCanvas.style.pointerEvents = "none"; // мышь проходит через него
|
|
24
|
+
canvas.parentElement!.appendChild(this.overlayCanvas);
|
|
25
|
+
|
|
26
|
+
this.overlayCtx = this.overlayCanvas.getContext("2d")!;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
listen() {
|
|
30
|
+
const moveHandler = (evt: Event) => {
|
|
31
|
+
const e = evt as MouseEvent; // кастим к MouseEvent
|
|
32
|
+
|
|
33
|
+
// Очищаем overlay
|
|
34
|
+
this.overlayCtx.clearRect(0, 0, this.overlayCanvas.width, this.overlayCanvas.height);
|
|
35
|
+
|
|
36
|
+
// Координаты мыши относительно канваса
|
|
37
|
+
const x = e.pageX - this.canvas.offsetLeft;
|
|
38
|
+
const y = e.pageY - this.canvas.offsetTop;
|
|
39
|
+
|
|
40
|
+
// Рисуем имя чуть выше курсора
|
|
41
|
+
this.overlayCtx.font = `${this.fontSize}px ${this.fontFamily}`;
|
|
42
|
+
this.overlayCtx.fillStyle = this.color;
|
|
43
|
+
this.overlayCtx.fillText(this.userName, x, y - 20);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
this.addListener("mousemove", moveHandler);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
clearEvents() {
|
|
50
|
+
super.clearEvents();
|
|
51
|
+
// Удаляем overlay с DOM
|
|
52
|
+
if (this.overlayCanvas.parentElement) {
|
|
53
|
+
this.overlayCanvas.parentElement.removeChild(this.overlayCanvas);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default TextHoverTool;
|
package/src/tools/Tool.ts
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
export default class Tool {
|
|
2
2
|
constructor(public canvas: HTMLCanvasElement) {
|
|
3
3
|
this.ctx = canvas.getContext("2d")!;
|
|
4
|
+
this.events = [];
|
|
4
5
|
this.clearEvents();
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
ctx: CanvasRenderingContext2D;
|
|
9
|
+
events: Array<{ type: string; handler: EventListener }> = [];
|
|
10
|
+
|
|
11
|
+
// сохраняем слушатели, чтобы потом удалять
|
|
12
|
+
addListener(type: string, handler: EventListener) {
|
|
13
|
+
this.canvas.addEventListener(type, handler);
|
|
14
|
+
this.events.push({ type, handler });
|
|
15
|
+
}
|
|
8
16
|
|
|
9
17
|
clearEvents() {
|
|
18
|
+
// удаляем все зарегистрированные слушатели
|
|
19
|
+
this.events.forEach(({ type, handler }) => {
|
|
20
|
+
this.canvas.removeEventListener(type, handler);
|
|
21
|
+
});
|
|
22
|
+
this.events = [];
|
|
23
|
+
|
|
24
|
+
// очищаем стандартные свойства
|
|
10
25
|
this.canvas.onmousedown = null;
|
|
11
26
|
this.canvas.onmouseup = null;
|
|
12
27
|
this.canvas.onmousemove = null;
|