canvas-drawing-editor 2.0.0 → 2.0.2
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.
|
@@ -12,7 +12,7 @@ const f = {
|
|
|
12
12
|
showColor: !0,
|
|
13
13
|
showMinimap: !0
|
|
14
14
|
};
|
|
15
|
-
class
|
|
15
|
+
class v extends HTMLElement {
|
|
16
16
|
constructor() {
|
|
17
17
|
super(), this.config = { ...f }, this.objects = [], this.selectedId = null, this.tool = "SELECT", this.color = "#000000", this.lineWidth = 3, this.isDragging = !1, this.dragStart = null, this.currentObject = null, this.dragOffset = { x: 0, y: 0 }, this.isTextInputVisible = !1, this.textInputPos = { x: 0, y: 0 }, this.textInputScreenPos = { x: 0, y: 0 }, this.editingTextId = null, this.isResizing = !1, this.resizeHandle = null, this.resizeStartBounds = null, this.resizeOriginalObject = null, this.history = [], this.clipboard = null, this.scale = 1, this.panOffset = { x: 0, y: 0 }, this.isPanning = !1, this.panStart = { x: 0, y: 0 }, this.shadow = this.attachShadow({ mode: "open" }), this.boundHandleResize = this.handleResize.bind(this), this.boundHandleKeyDown = this.handleKeyDown.bind(this), this.boundHandleWheel = this.handleWheel.bind(this);
|
|
18
18
|
}
|
|
@@ -427,7 +427,7 @@ class b extends HTMLElement {
|
|
|
427
427
|
}
|
|
428
428
|
// 画布鼠标抬起
|
|
429
429
|
handleCanvasPointerUp() {
|
|
430
|
-
this.isDragging = !1, this.dragStart = null, this.isResizing = !1, this.resizeHandle = null, this.resizeStartBounds = null, this.resizeOriginalObject = null, this.isPanning = !1, this.currentObject && (this.objects.push(this.currentObject), this.currentObject = null, this.dispatchChangeEvent()), this.renderCanvas(), this.renderMinimap();
|
|
430
|
+
this.isDragging = !1, this.dragStart = null, this.isResizing = !1, this.resizeHandle = null, this.resizeStartBounds = null, this.resizeOriginalObject = null, this.isPanning = !1, this.currentObject && (this.objects.push(this.currentObject), this.currentObject = null, this.dispatchChangeEvent()), this.renderCanvas(), this.renderMinimap(), this.updateUI();
|
|
431
431
|
}
|
|
432
432
|
// 双击编辑文本
|
|
433
433
|
handleCanvasDoubleClick(t) {
|
|
@@ -510,15 +510,15 @@ class b extends HTMLElement {
|
|
|
510
510
|
this.minimapCtx.clearRect(0, 0, t.width, t.height);
|
|
511
511
|
const s = t.width / i.width, e = t.height / i.height, n = Math.min(s, e) * 0.92, a = i.width * n, o = i.height * n, l = (t.width - a) / 2, r = (t.height - o) / 2;
|
|
512
512
|
this.minimapCtx.fillStyle = "#ffffff", this.minimapCtx.fillRect(l, r, a, o), this.minimapCtx.save(), this.minimapCtx.translate(l, r), this.minimapCtx.scale(n, n), this.minimapCtx.translate(this.panOffset.x, this.panOffset.y), this.minimapCtx.scale(this.scale, this.scale), (this.currentObject ? [...this.objects, this.currentObject] : this.objects).forEach((d) => {
|
|
513
|
-
switch (this.minimapCtx.fillStyle = d.color, this.minimapCtx.strokeStyle = d.color, this.minimapCtx.lineWidth = d.lineWidth, this.minimapCtx.setLineDash([]), d.type) {
|
|
513
|
+
switch (this.minimapCtx.fillStyle = d.color, this.minimapCtx.strokeStyle = d.color, this.minimapCtx.lineWidth = Math.max(d.lineWidth, 1), this.minimapCtx.setLineDash([]), d.type) {
|
|
514
514
|
case "RECTANGLE": {
|
|
515
515
|
const c = d;
|
|
516
|
-
this.minimapCtx.
|
|
516
|
+
this.minimapCtx.strokeRect(c.x, c.y, c.width, c.height);
|
|
517
517
|
break;
|
|
518
518
|
}
|
|
519
519
|
case "CIRCLE": {
|
|
520
520
|
const c = d;
|
|
521
|
-
this.minimapCtx.beginPath(), this.minimapCtx.arc(c.x, c.y, c.radius, 0, Math.PI * 2), this.minimapCtx.
|
|
521
|
+
this.minimapCtx.beginPath(), this.minimapCtx.arc(c.x, c.y, c.radius, 0, Math.PI * 2), this.minimapCtx.stroke();
|
|
522
522
|
break;
|
|
523
523
|
}
|
|
524
524
|
case "PATH": {
|
|
@@ -541,10 +541,10 @@ class b extends HTMLElement {
|
|
|
541
541
|
}
|
|
542
542
|
// 小地图点击定位
|
|
543
543
|
handleMinimapClick(t) {
|
|
544
|
-
const i = this.minimapCanvas.getBoundingClientRect(), s = t.clientX - i.left, e = t.clientY - i.top, n = this.minimapCanvas.width / this.canvas.width, a = this.minimapCanvas.height / this.canvas.height, o = Math.min(n, a) * 0.92, l = this.canvas.width * o, r = this.canvas.height * o, h = (this.minimapCanvas.width - l) / 2, d = (this.minimapCanvas.height - r) / 2, c = s - h, p = e - d, u = (c / o - this.panOffset.x) / this.scale,
|
|
544
|
+
const i = this.minimapCanvas.getBoundingClientRect(), s = t.clientX - i.left, e = t.clientY - i.top, n = this.minimapCanvas.width / this.canvas.width, a = this.minimapCanvas.height / this.canvas.height, o = Math.min(n, a) * 0.92, l = this.canvas.width * o, r = this.canvas.height * o, h = (this.minimapCanvas.width - l) / 2, d = (this.minimapCanvas.height - r) / 2, c = s - h, p = e - d, u = (c / o - this.panOffset.x) / this.scale, m = (p / o - this.panOffset.y) / this.scale, g = this.canvas.width / 2, x = this.canvas.height / 2;
|
|
545
545
|
this.panOffset = {
|
|
546
|
-
x:
|
|
547
|
-
y: x / this.scale -
|
|
546
|
+
x: g / this.scale - u,
|
|
547
|
+
y: x / this.scale - m
|
|
548
548
|
}, this.renderCanvas(), this.renderMinimap();
|
|
549
549
|
}
|
|
550
550
|
// 图片上传处理
|
|
@@ -626,30 +626,32 @@ class b extends HTMLElement {
|
|
|
626
626
|
const t = this.shadow.querySelector(".selection-info");
|
|
627
627
|
if (t)
|
|
628
628
|
if (this.selectedId) {
|
|
629
|
-
const
|
|
630
|
-
if (
|
|
631
|
-
const
|
|
629
|
+
const e = this.objects.find((n) => n.id === this.selectedId);
|
|
630
|
+
if (e) {
|
|
631
|
+
const a = {
|
|
632
632
|
RECTANGLE: "矩形",
|
|
633
633
|
CIRCLE: "圆形",
|
|
634
634
|
PATH: "画笔",
|
|
635
635
|
TEXT: "文本",
|
|
636
636
|
IMAGE: "图片"
|
|
637
|
-
}[
|
|
637
|
+
}[e.type] || e.type;
|
|
638
638
|
t.innerHTML = `
|
|
639
|
-
<span class="selection-label">已选择: ${
|
|
639
|
+
<span class="selection-label">已选择: ${a}</span>
|
|
640
640
|
<button class="delete-btn" title="删除">
|
|
641
641
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
642
642
|
<path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/>
|
|
643
643
|
</svg>
|
|
644
644
|
</button>
|
|
645
645
|
`, t.classList.add("visible");
|
|
646
|
-
const
|
|
647
|
-
|
|
646
|
+
const o = t.querySelector(".delete-btn");
|
|
647
|
+
o && o.addEventListener("click", () => this.deleteSelected());
|
|
648
648
|
}
|
|
649
649
|
} else
|
|
650
650
|
t.classList.remove("visible"), t.innerHTML = "";
|
|
651
651
|
const i = this.shadow.querySelector(".undo-btn");
|
|
652
652
|
i && (i.disabled = this.history.length === 0);
|
|
653
|
+
const s = this.shadow.querySelector(".empty-hint");
|
|
654
|
+
s && (s.style.display = this.objects.length === 0 ? "flex" : "none");
|
|
653
655
|
}
|
|
654
656
|
// 渲染 DOM 结构
|
|
655
657
|
render() {
|
|
@@ -658,6 +660,8 @@ class b extends HTMLElement {
|
|
|
658
660
|
<div class="editor-container">
|
|
659
661
|
<!-- 左侧工具栏 -->
|
|
660
662
|
<div class="toolbar">
|
|
663
|
+
${this.createToolButton("SELECT", "select-icon", "选择 (V)")}
|
|
664
|
+
<div class="divider"></div>
|
|
661
665
|
${this.config.showPencil ? this.createToolButton("PENCIL", "pencil-icon", "画笔 (P)") : ""}
|
|
662
666
|
${this.config.showRectangle ? this.createToolButton("RECTANGLE", "rect-icon", "矩形 (R)") : ""}
|
|
663
667
|
${this.config.showCircle ? this.createToolButton("CIRCLE", "circle-icon", "圆形 (O)") : ""}
|
|
@@ -675,7 +679,8 @@ class b extends HTMLElement {
|
|
|
675
679
|
<div class="divider"></div>
|
|
676
680
|
<button class="tool-btn undo-btn" title="撤销 (Ctrl+Z)" disabled>
|
|
677
681
|
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
678
|
-
<path d="
|
|
682
|
+
<path d="M1 4v6h6"/>
|
|
683
|
+
<path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/>
|
|
679
684
|
</svg>
|
|
680
685
|
</button>
|
|
681
686
|
<div class="spacer"></div>
|
|
@@ -773,7 +778,10 @@ class b extends HTMLElement {
|
|
|
773
778
|
// 绑定事件
|
|
774
779
|
bindEvents() {
|
|
775
780
|
this.canvas.addEventListener("mousedown", (h) => this.handleCanvasPointerDown(h)), this.canvas.addEventListener("mousemove", (h) => this.handleCanvasPointerMove(h)), this.canvas.addEventListener("mouseup", () => this.handleCanvasPointerUp()), this.canvas.addEventListener("mouseleave", () => this.handleCanvasPointerUp()), this.canvas.addEventListener("dblclick", (h) => this.handleCanvasDoubleClick(h)), this.canvas.addEventListener("touchstart", (h) => this.handleCanvasPointerDown(h)), this.canvas.addEventListener("touchmove", (h) => this.handleCanvasPointerMove(h)), this.canvas.addEventListener("touchend", () => this.handleCanvasPointerUp()), this.canvas.addEventListener("wheel", this.boundHandleWheel, { passive: !1 }), this.shadow.querySelectorAll(".tool-btn[data-tool]").forEach((h) => {
|
|
776
|
-
h.addEventListener("
|
|
781
|
+
h.addEventListener("mousedown", (d) => {
|
|
782
|
+
d.preventDefault();
|
|
783
|
+
}), h.addEventListener("click", () => {
|
|
784
|
+
this.isTextInputVisible && this.submitText();
|
|
777
785
|
const d = h.getAttribute("data-tool");
|
|
778
786
|
this.setTool(d);
|
|
779
787
|
});
|
|
@@ -798,6 +806,7 @@ class b extends HTMLElement {
|
|
|
798
806
|
// 创建工具按钮 HTML
|
|
799
807
|
createToolButton(t, i, s) {
|
|
800
808
|
const e = {
|
|
809
|
+
"select-icon": '<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>',
|
|
801
810
|
"pencil-icon": '<path d="M17 3a2.85 2.85 0 114 4L7.5 20.5 2 22l1.5-5.5L17 3z"/>',
|
|
802
811
|
"rect-icon": '<rect x="3" y="3" width="18" height="18" rx="2"/>',
|
|
803
812
|
"circle-icon": '<circle cx="12" cy="12" r="10"/>',
|
|
@@ -1136,8 +1145,8 @@ class b extends HTMLElement {
|
|
|
1136
1145
|
`;
|
|
1137
1146
|
}
|
|
1138
1147
|
}
|
|
1139
|
-
typeof window < "u" && !customElements.get("canvas-drawing-editor") && customElements.define("canvas-drawing-editor",
|
|
1148
|
+
typeof window < "u" && !customElements.get("canvas-drawing-editor") && customElements.define("canvas-drawing-editor", v);
|
|
1140
1149
|
export {
|
|
1141
|
-
|
|
1150
|
+
v as CanvasDrawingEditor
|
|
1142
1151
|
};
|
|
1143
1152
|
//# sourceMappingURL=canvas-drawing-editor.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-drawing-editor.es.js","sources":["../src/core/CanvasDrawingEditor.ts"],"sourcesContent":["/**\n * Canvas Drawing Editor - 纯 JavaScript Web Component\n * 无任何框架依赖\n */\n\n// 类型定义\nexport type ToolType = 'SELECT' | 'PENCIL' | 'RECTANGLE' | 'CIRCLE' | 'TEXT' | 'IMAGE';\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface BaseObject {\n id: string;\n type: string;\n x: number;\n y: number;\n color: string;\n lineWidth: number;\n}\n\nexport interface RectObject extends BaseObject {\n type: 'RECTANGLE';\n width: number;\n height: number;\n}\n\nexport interface CircleObject extends BaseObject {\n type: 'CIRCLE';\n radius: number;\n}\n\nexport interface PathObject extends BaseObject {\n type: 'PATH';\n points: Point[];\n}\n\nexport interface TextObject extends BaseObject {\n type: 'TEXT';\n text: string;\n fontSize: number;\n}\n\nexport interface ImageObject extends BaseObject {\n type: 'IMAGE';\n width: number;\n height: number;\n dataUrl: string;\n imageElement?: HTMLImageElement;\n}\n\nexport type CanvasObject = RectObject | CircleObject | PathObject | TextObject | ImageObject;\n\nexport interface EditorConfig {\n title?: string;\n showPencil?: boolean;\n showRectangle?: boolean;\n showCircle?: boolean;\n showText?: boolean;\n showImage?: boolean;\n showZoom?: boolean;\n showDownload?: boolean;\n showExport?: boolean;\n showImport?: boolean;\n showColor?: boolean;\n showMinimap?: boolean;\n}\n\n// 默认配置\nconst defaultConfig: EditorConfig = {\n title: 'Canvas Editor',\n showPencil: true,\n showRectangle: true,\n showCircle: true,\n showText: true,\n showImage: true,\n showZoom: true,\n showDownload: true,\n showExport: true,\n showImport: true,\n showColor: true,\n showMinimap: true,\n};\n\n/**\n * Canvas Drawing Editor Web Component\n */\nexport class CanvasDrawingEditor extends HTMLElement {\n // Shadow DOM\n private shadow: ShadowRoot;\n\n // DOM 元素\n private container!: HTMLDivElement;\n private toolbar!: HTMLDivElement;\n private topBar!: HTMLDivElement;\n private canvasContainer!: HTMLDivElement;\n private canvas!: HTMLCanvasElement;\n private ctx!: CanvasRenderingContext2D;\n private minimapCanvas!: HTMLCanvasElement;\n private minimapCtx!: CanvasRenderingContext2D;\n private textInput!: HTMLInputElement;\n private textInputContainer!: HTMLDivElement;\n\n // 配置\n private config: EditorConfig = { ...defaultConfig };\n\n // 状态\n private objects: CanvasObject[] = [];\n private selectedId: string | null = null;\n private tool: ToolType = 'SELECT';\n private color: string = '#000000';\n private lineWidth: number = 3;\n\n // 交互状态\n private isDragging: boolean = false;\n private dragStart: Point | null = null;\n private currentObject: CanvasObject | null = null;\n private dragOffset: Point = { x: 0, y: 0 };\n\n // 文本输入状态\n private isTextInputVisible: boolean = false;\n private textInputPos: Point = { x: 0, y: 0 };\n private textInputScreenPos: Point = { x: 0, y: 0 };\n private editingTextId: string | null = null;\n\n // 调整大小状态\n private isResizing: boolean = false;\n private resizeHandle: string | null = null;\n private resizeStartBounds: { x: number; y: number; width: number; height: number } | null = null;\n private resizeOriginalObject: CanvasObject | null = null;\n\n // 历史记录\n private history: CanvasObject[][] = [];\n private clipboard: CanvasObject | null = null;\n\n // 缩放状态\n private scale: number = 1;\n private panOffset: Point = { x: 0, y: 0 };\n\n // 平移状态\n private isPanning: boolean = false;\n private panStart: Point = { x: 0, y: 0 };\n\n // 绑定的事件处理器(用于移除监听)\n private boundHandleResize: () => void;\n private boundHandleKeyDown: (e: KeyboardEvent) => void;\n private boundHandleWheel: (e: WheelEvent) => void;\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n \n // 绑定事件处理器\n this.boundHandleResize = this.handleResize.bind(this);\n this.boundHandleKeyDown = this.handleKeyDown.bind(this);\n this.boundHandleWheel = this.handleWheel.bind(this);\n }\n\n // 观察的属性\n static get observedAttributes(): string[] {\n return [\n 'title', 'show-pencil', 'show-rectangle', 'show-circle', 'show-text',\n 'show-image', 'show-zoom', 'show-download', 'show-export', 'show-import',\n 'show-color', 'show-minimap'\n ];\n }\n\n // 生命周期:连接到 DOM\n connectedCallback(): void {\n this.parseAttributes();\n this.render();\n this.setupEventListeners();\n this.initCanvas();\n }\n\n // 生命周期:从 DOM 断开\n disconnectedCallback(): void {\n this.removeEventListeners();\n }\n\n // 生命周期:属性变化\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n this.parseAttributes();\n if (this.container) {\n this.updateUI();\n }\n }\n\n // 解析 HTML 属性\n private parseAttributes(): void {\n this.config = {\n title: this.getAttribute('title') || defaultConfig.title,\n showPencil: this.getAttribute('show-pencil') !== 'false',\n showRectangle: this.getAttribute('show-rectangle') !== 'false',\n showCircle: this.getAttribute('show-circle') !== 'false',\n showText: this.getAttribute('show-text') !== 'false',\n showImage: this.getAttribute('show-image') !== 'false',\n showZoom: this.getAttribute('show-zoom') !== 'false',\n showDownload: this.getAttribute('show-download') !== 'false',\n showExport: this.getAttribute('show-export') !== 'false',\n showImport: this.getAttribute('show-import') !== 'false',\n showColor: this.getAttribute('show-color') !== 'false',\n showMinimap: this.getAttribute('show-minimap') !== 'false',\n };\n }\n\n // 生成唯一 ID\n private generateId(): string {\n return Math.random().toString(36).substr(2, 9);\n }\n\n // 设置事件监听\n private setupEventListeners(): void {\n window.addEventListener('resize', this.boundHandleResize);\n window.addEventListener('keydown', this.boundHandleKeyDown);\n }\n\n // 移除事件监听\n private removeEventListeners(): void {\n window.removeEventListener('resize', this.boundHandleResize);\n window.removeEventListener('keydown', this.boundHandleKeyDown);\n if (this.canvas) {\n this.canvas.removeEventListener('wheel', this.boundHandleWheel);\n }\n }\n\n // 窗口大小变化处理\n private handleResize(): void {\n this.initCanvas();\n }\n\n // 初始化画布\n private initCanvas(): void {\n if (!this.canvasContainer || !this.canvas) return;\n\n // 使用 requestAnimationFrame 确保 DOM 已经渲染\n requestAnimationFrame(() => {\n this.canvas.width = this.canvasContainer.clientWidth;\n this.canvas.height = this.canvasContainer.clientHeight;\n this.renderCanvas();\n this.renderMinimap();\n });\n }\n\n // 获取鼠标在画布上的位置(考虑缩放和平移)\n private getMousePos(e: MouseEvent | TouchEvent): Point {\n const rect = this.canvas.getBoundingClientRect();\n let clientX: number, clientY: number;\n\n if ('touches' in e && e.touches.length > 0) {\n clientX = e.touches[0].clientX;\n clientY = e.touches[0].clientY;\n } else if ('clientX' in e) {\n clientX = e.clientX;\n clientY = e.clientY;\n } else {\n return { x: 0, y: 0 };\n }\n\n const x = (clientX - rect.left - this.panOffset.x) / this.scale;\n const y = (clientY - rect.top - this.panOffset.y) / this.scale;\n return { x, y };\n }\n\n // 获取屏幕坐标(不考虑缩放和平移)\n private getScreenPos(e: MouseEvent | TouchEvent): Point {\n const rect = this.canvas.getBoundingClientRect();\n let clientX: number, clientY: number;\n\n if ('touches' in e && e.touches.length > 0) {\n clientX = e.touches[0].clientX;\n clientY = e.touches[0].clientY;\n } else if ('clientX' in e) {\n clientX = e.clientX;\n clientY = e.clientY;\n } else {\n return { x: 0, y: 0 };\n }\n\n return { x: clientX - rect.left, y: clientY - rect.top };\n }\n\n // 获取对象边界\n private getObjectBounds(obj: CanvasObject): { x: number; y: number; width: number; height: number } {\n switch (obj.type) {\n case 'RECTANGLE':\n case 'IMAGE': {\n const r = obj as RectObject | ImageObject;\n return { x: r.x, y: r.y, width: r.width, height: r.height };\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n return { x: c.x - c.radius, y: c.y - c.radius, width: c.radius * 2, height: c.radius * 2 };\n }\n case 'TEXT': {\n const t = obj as TextObject;\n const width = t.text.length * t.fontSize * 0.6;\n return { x: t.x, y: t.y - t.fontSize, width, height: t.fontSize };\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length === 0) return { x: 0, y: 0, width: 0, height: 0 };\n const minX = Math.min(...p.points.map(pt => pt.x));\n const maxX = Math.max(...p.points.map(pt => pt.x));\n const minY = Math.min(...p.points.map(pt => pt.y));\n const maxY = Math.max(...p.points.map(pt => pt.y));\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n }\n }\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n\n // 检查调整大小手柄\n private getResizeHandleAtPoint(obj: CanvasObject, x: number, y: number): string | null {\n const bounds = this.getObjectBounds(obj);\n const handleSize = 8;\n\n const handles = [\n { name: 'nw', x: bounds.x, y: bounds.y },\n { name: 'ne', x: bounds.x + bounds.width, y: bounds.y },\n { name: 'sw', x: bounds.x, y: bounds.y + bounds.height },\n { name: 'se', x: bounds.x + bounds.width, y: bounds.y + bounds.height },\n ];\n\n for (const handle of handles) {\n if (Math.abs(x - handle.x) <= handleSize && Math.abs(y - handle.y) <= handleSize) {\n return handle.name;\n }\n }\n return null;\n }\n\n // 碰撞检测\n private isHit(obj: CanvasObject, x: number, y: number): boolean {\n switch (obj.type) {\n case 'RECTANGLE': {\n const r = obj as RectObject;\n return x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height;\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n const dist = Math.sqrt(Math.pow(x - c.x, 2) + Math.pow(y - c.y, 2));\n return dist <= c.radius;\n }\n case 'IMAGE': {\n const img = obj as ImageObject;\n return x >= img.x && x <= img.x + img.width && y >= img.y && y <= img.y + img.height;\n }\n case 'TEXT': {\n const t = obj as TextObject;\n return x >= t.x && x <= t.x + (t.text.length * t.fontSize * 0.6) && y >= t.y - t.fontSize && y <= t.y;\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length === 0) return false;\n const minX = Math.min(...p.points.map(pt => pt.x));\n const maxX = Math.max(...p.points.map(pt => pt.x));\n const minY = Math.min(...p.points.map(pt => pt.y));\n const maxY = Math.max(...p.points.map(pt => pt.y));\n return x >= minX && x <= maxX && y >= minY && y <= maxY;\n }\n }\n return false;\n }\n\n // 保存历史\n private saveHistory(): void {\n this.history.push(JSON.parse(JSON.stringify(this.objects)));\n }\n\n // 撤销\n private undo(): void {\n if (this.history.length === 0) return;\n const previousState = this.history.pop();\n if (previousState) {\n this.objects = previousState;\n this.selectedId = null;\n this.renderCanvas();\n this.renderMinimap();\n this.dispatchChangeEvent();\n }\n }\n\n // 删除选中对象\n private deleteSelected(): void {\n if (this.selectedId) {\n this.saveHistory();\n this.objects = this.objects.filter(o => o.id !== this.selectedId);\n this.selectedId = null;\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n }\n }\n\n // 复制选中对象\n private copySelected(): void {\n if (this.selectedId) {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n this.clipboard = JSON.parse(JSON.stringify(selectedObj));\n }\n }\n }\n\n // 粘贴对象\n private pasteObject(): void {\n if (this.clipboard) {\n this.saveHistory();\n const newObj = {\n ...JSON.parse(JSON.stringify(this.clipboard)),\n id: this.generateId(),\n x: this.clipboard.x + 20,\n y: this.clipboard.y + 20\n };\n if (newObj.type === 'PATH' && newObj.points) {\n newObj.points = newObj.points.map((pt: Point) => ({\n x: pt.x + 20,\n y: pt.y + 20\n }));\n }\n this.objects.push(newObj);\n this.selectedId = newObj.id;\n this.clipboard = newObj;\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n }\n }\n\n // 派发变化事件\n private dispatchChangeEvent(): void {\n this.dispatchEvent(new CustomEvent('editor-change', {\n bubbles: true,\n composed: true,\n detail: { objects: this.objects }\n }));\n }\n\n // 键盘事件处理\n private handleKeyDown(e: KeyboardEvent): void {\n if (this.isTextInputVisible) return;\n\n // Ctrl+Z: 撤销\n if ((e.ctrlKey || e.metaKey) && e.key === 'z') {\n e.preventDefault();\n this.undo();\n return;\n }\n\n // Ctrl+C: 复制\n if ((e.ctrlKey || e.metaKey) && e.key === 'c') {\n if (this.selectedId) {\n e.preventDefault();\n this.copySelected();\n }\n return;\n }\n\n // Ctrl+V: 粘贴\n if ((e.ctrlKey || e.metaKey) && e.key === 'v') {\n if (this.clipboard) {\n e.preventDefault();\n this.pasteObject();\n }\n return;\n }\n\n // Delete/Backspace: 删除\n if ((e.key === 'Delete' || e.key === 'Backspace') && this.selectedId) {\n e.preventDefault();\n this.deleteSelected();\n return;\n }\n\n // 快捷键切换工具\n if (!e.ctrlKey && !e.metaKey) {\n switch (e.key.toLowerCase()) {\n case 'v':\n this.setTool('SELECT');\n break;\n case 'p':\n case 'b':\n this.setTool('PENCIL');\n break;\n case 'r':\n this.setTool('RECTANGLE');\n break;\n case 'o':\n this.setTool('CIRCLE');\n break;\n case 't':\n this.setTool('TEXT');\n break;\n case 'escape':\n this.selectedId = null;\n this.hideTextInput();\n this.renderCanvas();\n this.updateUI();\n break;\n }\n }\n }\n\n // 滚轮缩放\n private handleWheel(e: WheelEvent): void {\n e.preventDefault();\n const rect = this.canvas.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n\n const delta = e.deltaY > 0 ? 0.9 : 1.1;\n const newScale = this.scale * delta;\n\n this.zoomAtPoint(newScale, mouseX, mouseY);\n }\n\n // 以指定点为中心缩放\n private zoomAtPoint(newScale: number, centerX: number, centerY: number): void {\n const clampedScale = Math.min(Math.max(newScale, 0.2), 5);\n\n const mouseXBeforeZoom = (centerX - this.panOffset.x) / this.scale;\n const mouseYBeforeZoom = (centerY - this.panOffset.y) / this.scale;\n\n const newPanOffsetX = centerX - mouseXBeforeZoom * clampedScale;\n const newPanOffsetY = centerY - mouseYBeforeZoom * clampedScale;\n\n this.scale = clampedScale;\n this.panOffset = { x: newPanOffsetX, y: newPanOffsetY };\n\n this.renderCanvas();\n this.renderMinimap();\n this.updateZoomDisplay();\n }\n\n // 放大\n private zoomIn(): void {\n const centerX = this.canvas.width / 2;\n const centerY = this.canvas.height / 2;\n this.zoomAtPoint(this.scale * 1.2, centerX, centerY);\n }\n\n // 缩小\n private zoomOut(): void {\n const centerX = this.canvas.width / 2;\n const centerY = this.canvas.height / 2;\n this.zoomAtPoint(this.scale / 1.2, centerX, centerY);\n }\n\n // 重置缩放\n private resetZoom(): void {\n this.scale = 1;\n this.panOffset = { x: 0, y: 0 };\n this.renderCanvas();\n this.renderMinimap();\n this.updateZoomDisplay();\n }\n\n // 更新缩放显示\n private updateZoomDisplay(): void {\n const zoomText = this.shadow.querySelector('.zoom-text');\n if (zoomText) {\n zoomText.textContent = `${Math.round(this.scale * 100)}%`;\n }\n }\n\n // 设置工具\n private setTool(tool: ToolType): void {\n this.tool = tool;\n this.updateToolButtons();\n }\n\n // 更新工具按钮状态\n private updateToolButtons(): void {\n const buttons = this.shadow.querySelectorAll('.tool-btn');\n buttons.forEach(btn => {\n const btnTool = btn.getAttribute('data-tool');\n if (btnTool === this.tool) {\n btn.classList.add('active');\n } else {\n btn.classList.remove('active');\n }\n });\n }\n\n // 隐藏文本输入\n private hideTextInput(): void {\n this.isTextInputVisible = false;\n if (this.textInputContainer) {\n this.textInputContainer.style.display = 'none';\n }\n this.editingTextId = null;\n }\n\n // 显示文本输入\n private showTextInput(screenX: number, screenY: number, text: string = ''): void {\n this.isTextInputVisible = true;\n this.textInputScreenPos = { x: screenX, y: screenY };\n\n if (this.textInputContainer && this.textInput) {\n this.textInputContainer.style.display = 'block';\n this.textInputContainer.style.left = `${screenX}px`;\n this.textInputContainer.style.top = `${screenY - 30}px`;\n this.textInput.value = text;\n this.textInput.style.color = this.color;\n setTimeout(() => {\n this.textInput.focus();\n if (text) this.textInput.select();\n }, 0);\n }\n }\n\n // 提交文本\n private submitText(): void {\n const value = this.textInput?.value?.trim();\n if (value) {\n if (this.editingTextId) {\n const existingObj = this.objects.find(o => o.id === this.editingTextId) as TextObject | undefined;\n if (existingObj && existingObj.text !== value) {\n this.saveHistory();\n existingObj.text = value;\n }\n this.selectedId = this.editingTextId;\n } else {\n this.saveHistory();\n const newObj: TextObject = {\n id: this.generateId(),\n type: 'TEXT',\n x: this.textInputPos.x,\n y: this.textInputPos.y,\n text: value,\n fontSize: 24,\n color: this.color,\n lineWidth: this.lineWidth\n };\n this.objects.push(newObj);\n this.selectedId = newObj.id;\n }\n this.dispatchChangeEvent();\n }\n this.hideTextInput();\n this.setTool('SELECT');\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n }\n\n // 画布鼠标按下\n private handleCanvasPointerDown(e: MouseEvent | TouchEvent): void {\n const { x, y } = this.getMousePos(e);\n const screenPos = this.getScreenPos(e);\n this.dragStart = { x, y };\n this.isDragging = true;\n\n // 如果文本输入可见且不是文本工具,先保存文本\n if (this.isTextInputVisible && this.tool !== 'TEXT') {\n this.submitText();\n }\n\n if (this.tool === 'SELECT') {\n // 检查是否点击调整大小手柄\n if (this.selectedId) {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n const handle = this.getResizeHandleAtPoint(selectedObj, x, y);\n if (handle) {\n this.saveHistory();\n this.isResizing = true;\n this.resizeHandle = handle;\n this.resizeStartBounds = this.getObjectBounds(selectedObj);\n this.resizeOriginalObject = JSON.parse(JSON.stringify(selectedObj));\n return;\n }\n }\n }\n\n // 查找点击的对象\n const clickedObject = [...this.objects].reverse().find(obj => this.isHit(obj, x, y));\n\n if (clickedObject) {\n this.selectedId = clickedObject.id;\n this.dragOffset = { x: x - clickedObject.x, y: y - clickedObject.y };\n this.saveHistory();\n this.updateUI();\n } else {\n // 开始拖拽画布\n this.selectedId = null;\n this.isPanning = true;\n this.panStart = screenPos;\n this.updateUI();\n }\n } else if (this.tool === 'TEXT') {\n // 显示文本输入\n this.textInputPos = { x, y };\n this.showTextInput(screenPos.x, screenPos.y);\n this.isDragging = false;\n } else {\n // 开始绘制图形\n this.saveHistory();\n const id = this.generateId();\n if (this.tool === 'RECTANGLE') {\n this.currentObject = { id, type: 'RECTANGLE', x, y, width: 0, height: 0, color: this.color, lineWidth: this.lineWidth };\n } else if (this.tool === 'CIRCLE') {\n this.currentObject = { id, type: 'CIRCLE', x, y, radius: 0, color: this.color, lineWidth: this.lineWidth };\n } else if (this.tool === 'PENCIL') {\n this.currentObject = { id, type: 'PATH', x, y, points: [{ x, y }], color: this.color, lineWidth: this.lineWidth };\n }\n }\n\n this.renderCanvas();\n }\n\n // 画布鼠标移动\n private handleCanvasPointerMove(e: MouseEvent | TouchEvent): void {\n // 处理画布拖拽\n if (this.isPanning) {\n const screenPos = this.getScreenPos(e);\n const dx = screenPos.x - this.panStart.x;\n const dy = screenPos.y - this.panStart.y;\n this.panOffset = { x: this.panOffset.x + dx, y: this.panOffset.y + dy };\n this.panStart = screenPos;\n this.renderCanvas();\n this.renderMinimap();\n return;\n }\n\n if (!this.isDragging || !this.dragStart) return;\n const { x, y } = this.getMousePos(e);\n\n // 处理调整大小\n if (this.isResizing && this.selectedId && this.resizeHandle && this.resizeStartBounds && this.resizeOriginalObject) {\n const obj = this.objects.find(o => o.id === this.selectedId);\n if (!obj) return;\n\n const dx = x - this.dragStart.x;\n const dy = y - this.dragStart.y;\n let newX = this.resizeStartBounds.x;\n let newY = this.resizeStartBounds.y;\n let newWidth = this.resizeStartBounds.width;\n let newHeight = this.resizeStartBounds.height;\n\n if (this.resizeHandle.includes('e')) newWidth = this.resizeStartBounds.width + dx;\n if (this.resizeHandle.includes('w')) {\n newX = this.resizeStartBounds.x + dx;\n newWidth = this.resizeStartBounds.width - dx;\n }\n if (this.resizeHandle.includes('s')) newHeight = this.resizeStartBounds.height + dy;\n if (this.resizeHandle.includes('n')) {\n newY = this.resizeStartBounds.y + dy;\n newHeight = this.resizeStartBounds.height - dy;\n }\n\n newWidth = Math.max(10, newWidth);\n newHeight = Math.max(10, newHeight);\n\n // 根据对象类型应用变化\n switch (obj.type) {\n case 'RECTANGLE':\n case 'IMAGE':\n (obj as RectObject | ImageObject).x = newX;\n (obj as RectObject | ImageObject).y = newY;\n (obj as RectObject | ImageObject).width = newWidth;\n (obj as RectObject | ImageObject).height = newHeight;\n break;\n case 'CIRCLE': {\n const radius = Math.max(newWidth, newHeight) / 2;\n (obj as CircleObject).x = newX + radius;\n (obj as CircleObject).y = newY + radius;\n (obj as CircleObject).radius = radius;\n break;\n }\n case 'TEXT': {\n const origT = this.resizeOriginalObject as TextObject;\n const scaleFactor = newWidth / this.resizeStartBounds.width;\n (obj as TextObject).x = newX;\n (obj as TextObject).y = newY + newHeight;\n (obj as TextObject).fontSize = Math.max(8, Math.round(origT.fontSize * scaleFactor));\n break;\n }\n case 'PATH': {\n const origP = this.resizeOriginalObject as PathObject;\n const scaleX = newWidth / this.resizeStartBounds.width;\n const scaleY = newHeight / this.resizeStartBounds.height;\n (obj as PathObject).points = origP.points.map(pt => ({\n x: newX + (pt.x - this.resizeStartBounds!.x) * scaleX,\n y: newY + (pt.y - this.resizeStartBounds!.y) * scaleY\n }));\n break;\n }\n }\n\n this.renderCanvas();\n this.renderMinimap();\n return;\n }\n\n // 移动选中对象\n if (this.tool === 'SELECT' && this.selectedId) {\n const obj = this.objects.find(o => o.id === this.selectedId);\n if (obj) {\n if (obj.type === 'PATH') {\n const p = obj as PathObject;\n const dx = x - this.dragStart.x;\n const dy = y - this.dragStart.y;\n p.points = p.points.map(pt => ({ x: pt.x + dx, y: pt.y + dy }));\n this.dragStart = { x, y };\n } else {\n obj.x = x - this.dragOffset.x;\n obj.y = y - this.dragOffset.y;\n }\n this.renderCanvas();\n this.renderMinimap();\n }\n } else if (this.currentObject) {\n // 更新正在绘制的图形\n if (this.currentObject.type === 'RECTANGLE') {\n (this.currentObject as RectObject).width = x - this.currentObject.x;\n (this.currentObject as RectObject).height = y - this.currentObject.y;\n } else if (this.currentObject.type === 'CIRCLE') {\n const radius = Math.sqrt(Math.pow(x - this.currentObject.x, 2) + Math.pow(y - this.currentObject.y, 2));\n (this.currentObject as CircleObject).radius = radius;\n } else if (this.currentObject.type === 'PATH') {\n (this.currentObject as PathObject).points.push({ x, y });\n }\n this.renderCanvas();\n }\n }\n\n // 画布鼠标抬起\n private handleCanvasPointerUp(): void {\n this.isDragging = false;\n this.dragStart = null;\n this.isResizing = false;\n this.resizeHandle = null;\n this.resizeStartBounds = null;\n this.resizeOriginalObject = null;\n this.isPanning = false;\n\n if (this.currentObject) {\n this.objects.push(this.currentObject);\n this.currentObject = null;\n this.dispatchChangeEvent();\n }\n\n this.renderCanvas();\n this.renderMinimap();\n }\n\n // 双击编辑文本\n private handleCanvasDoubleClick(e: MouseEvent): void {\n e.preventDefault();\n const { x, y } = this.getMousePos(e);\n\n const clickedObject = [...this.objects].reverse().find(obj => this.isHit(obj, x, y));\n\n if (clickedObject && clickedObject.type === 'TEXT') {\n const textObj = clickedObject as TextObject;\n this.editingTextId = textObj.id;\n this.textInputPos = { x: textObj.x, y: textObj.y };\n const screenX = textObj.x * this.scale + this.panOffset.x;\n const screenY = textObj.y * this.scale + this.panOffset.y;\n this.showTextInput(screenX, screenY, textObj.text);\n this.setTool('SELECT');\n }\n }\n\n // 渲染画布\n private renderCanvas(): void {\n if (!this.ctx) return;\n\n // 清空画布\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n // 绘制背景\n this.ctx.fillStyle = '#ffffff';\n this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);\n\n // 应用缩放和平移\n this.ctx.save();\n this.ctx.translate(this.panOffset.x, this.panOffset.y);\n this.ctx.scale(this.scale, this.scale);\n\n // 绘制所有对象\n this.objects.forEach(obj => this.drawObject(this.ctx, obj, false));\n\n // 绘制正在创建的对象\n if (this.currentObject) {\n this.drawObject(this.ctx, this.currentObject, false);\n }\n\n // 绘制选中对象的调整手柄\n if (this.selectedId && this.tool === 'SELECT') {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n this.drawSelectionHandles(this.ctx, selectedObj);\n }\n }\n\n this.ctx.restore();\n }\n\n // 绘制单个对象\n private drawObject(ctx: CanvasRenderingContext2D, obj: CanvasObject, isMinimap: boolean): void {\n ctx.beginPath();\n ctx.strokeStyle = obj.color;\n ctx.lineWidth = obj.lineWidth;\n ctx.fillStyle = obj.color;\n\n // 选中高亮(仅主画布)\n if (!isMinimap && obj.id === this.selectedId) {\n ctx.shadowColor = 'rgba(0, 100, 255, 0.5)';\n ctx.shadowBlur = 10;\n } else {\n ctx.shadowBlur = 0;\n }\n\n switch (obj.type) {\n case 'RECTANGLE': {\n const r = obj as RectObject;\n ctx.strokeRect(r.x, r.y, r.width, r.height);\n break;\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n ctx.beginPath();\n ctx.arc(c.x, c.y, c.radius, 0, 2 * Math.PI);\n ctx.stroke();\n break;\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length < 2) break;\n ctx.beginPath();\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n ctx.moveTo(p.points[0].x, p.points[0].y);\n for (let i = 1; i < p.points.length; i++) {\n ctx.lineTo(p.points[i].x, p.points[i].y);\n }\n ctx.stroke();\n break;\n }\n case 'TEXT': {\n const t = obj as TextObject;\n ctx.font = `${t.fontSize}px sans-serif`;\n ctx.fillText(t.text, t.x, t.y);\n break;\n }\n case 'IMAGE': {\n const imgObj = obj as ImageObject;\n if (imgObj.imageElement && imgObj.imageElement.complete) {\n ctx.drawImage(imgObj.imageElement, imgObj.x, imgObj.y, imgObj.width, imgObj.height);\n } else if (imgObj.dataUrl) {\n // 加载图片\n const img = new Image();\n img.onload = () => {\n imgObj.imageElement = img;\n this.renderCanvas();\n };\n img.src = imgObj.dataUrl;\n }\n break;\n }\n }\n }\n\n // 绘制选中手柄\n private drawSelectionHandles(ctx: CanvasRenderingContext2D, obj: CanvasObject): void {\n const bounds = this.getObjectBounds(obj);\n const handleSize = 8;\n\n ctx.shadowBlur = 0;\n ctx.fillStyle = '#3b82f6';\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 2;\n\n // 绘制角落手柄\n const corners = [\n { x: bounds.x, y: bounds.y },\n { x: bounds.x + bounds.width, y: bounds.y },\n { x: bounds.x, y: bounds.y + bounds.height },\n { x: bounds.x + bounds.width, y: bounds.y + bounds.height },\n ];\n\n corners.forEach(corner => {\n ctx.beginPath();\n ctx.rect(corner.x - handleSize / 2, corner.y - handleSize / 2, handleSize, handleSize);\n ctx.fill();\n ctx.stroke();\n });\n\n // 绘制选择边框\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 1;\n ctx.setLineDash([5, 5]);\n ctx.strokeRect(bounds.x, bounds.y, bounds.width, bounds.height);\n ctx.setLineDash([]);\n }\n\n // 渲染小地图\n private renderMinimap(): void {\n if (!this.minimapCtx || !this.config.showMinimap) return;\n\n const minimap = this.minimapCanvas;\n const mainCanvas = this.canvas;\n\n this.minimapCtx.clearRect(0, 0, minimap.width, minimap.height);\n\n // 计算缩放比例\n const scaleX = minimap.width / mainCanvas.width;\n const scaleY = minimap.height / mainCanvas.height;\n const minimapScale = Math.min(scaleX, scaleY) * 0.92;\n\n const canvasW = mainCanvas.width * minimapScale;\n const canvasH = mainCanvas.height * minimapScale;\n const offsetX = (minimap.width - canvasW) / 2;\n const offsetY = (minimap.height - canvasH) / 2;\n\n // 绘制画布区域背景\n this.minimapCtx.fillStyle = '#ffffff';\n this.minimapCtx.fillRect(offsetX, offsetY, canvasW, canvasH);\n\n // 应用主画布的缩放和平移变换\n this.minimapCtx.save();\n this.minimapCtx.translate(offsetX, offsetY);\n this.minimapCtx.scale(minimapScale, minimapScale);\n this.minimapCtx.translate(this.panOffset.x, this.panOffset.y);\n this.minimapCtx.scale(this.scale, this.scale);\n\n // 绘制所有对象\n const allObjects = this.currentObject ? [...this.objects, this.currentObject] : this.objects;\n allObjects.forEach(obj => {\n this.minimapCtx.fillStyle = obj.color;\n this.minimapCtx.strokeStyle = obj.color;\n this.minimapCtx.lineWidth = obj.lineWidth;\n this.minimapCtx.setLineDash([]);\n\n switch (obj.type) {\n case 'RECTANGLE': {\n const r = obj as RectObject;\n this.minimapCtx.fillRect(r.x, r.y, r.width, r.height);\n break;\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n this.minimapCtx.beginPath();\n this.minimapCtx.arc(c.x, c.y, c.radius, 0, Math.PI * 2);\n this.minimapCtx.fill();\n break;\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length > 0) {\n this.minimapCtx.beginPath();\n this.minimapCtx.lineCap = 'round';\n this.minimapCtx.lineJoin = 'round';\n this.minimapCtx.moveTo(p.points[0].x, p.points[0].y);\n p.points.forEach(pt => this.minimapCtx.lineTo(pt.x, pt.y));\n this.minimapCtx.stroke();\n }\n break;\n }\n case 'TEXT': {\n const t = obj as TextObject;\n this.minimapCtx.font = `${t.fontSize}px sans-serif`;\n this.minimapCtx.fillText(t.text, t.x, t.y);\n break;\n }\n case 'IMAGE': {\n const img = obj as ImageObject;\n if (img.imageElement) {\n this.minimapCtx.drawImage(img.imageElement, img.x, img.y, img.width, img.height);\n }\n break;\n }\n }\n });\n\n this.minimapCtx.restore();\n\n // 绘制画布边框\n this.minimapCtx.strokeStyle = '#94a3b8';\n this.minimapCtx.lineWidth = 1;\n this.minimapCtx.strokeRect(offsetX, offsetY, canvasW, canvasH);\n }\n\n // 小地图点击定位\n private handleMinimapClick(e: MouseEvent): void {\n const rect = this.minimapCanvas.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const clickY = e.clientY - rect.top;\n\n const scaleX = this.minimapCanvas.width / this.canvas.width;\n const scaleY = this.minimapCanvas.height / this.canvas.height;\n const minimapScale = Math.min(scaleX, scaleY) * 0.92;\n\n const canvasW = this.canvas.width * minimapScale;\n const canvasH = this.canvas.height * minimapScale;\n const offsetX = (this.minimapCanvas.width - canvasW) / 2;\n const offsetY = (this.minimapCanvas.height - canvasH) / 2;\n\n const relX = clickX - offsetX;\n const relY = clickY - offsetY;\n\n const canvasX = (relX / minimapScale - this.panOffset.x) / this.scale;\n const canvasY = (relY / minimapScale - this.panOffset.y) / this.scale;\n\n const viewportCenterX = this.canvas.width / 2;\n const viewportCenterY = this.canvas.height / 2;\n\n this.panOffset = {\n x: viewportCenterX / this.scale - canvasX,\n y: viewportCenterY / this.scale - canvasY\n };\n\n this.renderCanvas();\n this.renderMinimap();\n }\n\n // 图片上传处理\n private handleImageUpload(e: Event): void {\n const input = e.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) return;\n\n const file = input.files[0];\n const reader = new FileReader();\n\n reader.onload = (event) => {\n const dataUrl = event.target?.result as string;\n const img = new Image();\n img.onload = () => {\n this.saveHistory();\n const maxSize = 300;\n let width = img.width;\n let height = img.height;\n if (width > maxSize || height > maxSize) {\n const ratio = Math.min(maxSize / width, maxSize / height);\n width *= ratio;\n height *= ratio;\n }\n\n const newObj: ImageObject = {\n id: this.generateId(),\n type: 'IMAGE',\n x: 100,\n y: 100,\n width,\n height,\n color: '#000000',\n lineWidth: 1,\n dataUrl,\n imageElement: img\n };\n this.objects.push(newObj);\n this.selectedId = newObj.id;\n this.setTool('SELECT');\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n };\n img.src = dataUrl;\n };\n\n reader.readAsDataURL(file);\n input.value = '';\n }\n\n // 保存 JSON\n private saveJson(): void {\n const data = {\n version: '1.0',\n objects: this.objects.map(obj => {\n const { imageElement, ...rest } = obj as ImageObject;\n return rest;\n })\n };\n const json = JSON.stringify(data, null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'canvas-project.json';\n a.click();\n URL.revokeObjectURL(url);\n }\n\n // 加载 JSON\n private loadJson(e: Event): void {\n const input = e.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) return;\n\n const file = input.files[0];\n const reader = new FileReader();\n\n reader.onload = (event) => {\n try {\n const data = JSON.parse(event.target?.result as string);\n if (data.objects && Array.isArray(data.objects)) {\n this.saveHistory();\n this.objects = data.objects;\n this.selectedId = null;\n\n // 重新加载图片\n this.objects.forEach(obj => {\n if (obj.type === 'IMAGE' && (obj as ImageObject).dataUrl) {\n const img = new Image();\n img.onload = () => {\n (obj as ImageObject).imageElement = img;\n this.renderCanvas();\n this.renderMinimap();\n };\n img.src = (obj as ImageObject).dataUrl;\n }\n });\n\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n }\n } catch (err) {\n console.error('Failed to load JSON:', err);\n }\n };\n\n reader.readAsText(file);\n input.value = '';\n }\n\n // 导出 PNG\n private exportPng(): void {\n // 创建临时画布\n const tempCanvas = document.createElement('canvas');\n tempCanvas.width = this.canvas.width;\n tempCanvas.height = this.canvas.height;\n const tempCtx = tempCanvas.getContext('2d')!;\n\n // 绘制白色背景\n tempCtx.fillStyle = '#ffffff';\n tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);\n\n // 应用缩放和平移\n tempCtx.translate(this.panOffset.x, this.panOffset.y);\n tempCtx.scale(this.scale, this.scale);\n\n // 绘制所有对象\n this.objects.forEach(obj => this.drawObject(tempCtx, obj, true));\n\n // 下载\n const url = tempCanvas.toDataURL('image/png');\n const a = document.createElement('a');\n a.href = url;\n a.download = 'canvas-export.png';\n a.click();\n }\n\n // 更新 UI\n private updateUI(): void {\n // 更新选中状态显示\n const selectionInfo = this.shadow.querySelector('.selection-info');\n if (selectionInfo) {\n if (this.selectedId) {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n const typeLabels: Record<string, string> = {\n 'RECTANGLE': '矩形',\n 'CIRCLE': '圆形',\n 'PATH': '画笔',\n 'TEXT': '文本',\n 'IMAGE': '图片'\n };\n const typeLabel = typeLabels[selectedObj.type] || selectedObj.type;\n selectionInfo.innerHTML = `\n <span class=\"selection-label\">已选择: ${typeLabel}</span>\n <button class=\"delete-btn\" title=\"删除\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\"/>\n </svg>\n </button>\n `;\n selectionInfo.classList.add('visible');\n const deleteBtn = selectionInfo.querySelector('.delete-btn');\n if (deleteBtn) {\n deleteBtn.addEventListener('click', () => this.deleteSelected());\n }\n }\n } else {\n selectionInfo.classList.remove('visible');\n selectionInfo.innerHTML = '';\n }\n }\n\n // 更新撤销按钮状态\n const undoBtn = this.shadow.querySelector('.undo-btn') as HTMLButtonElement;\n if (undoBtn) {\n undoBtn.disabled = this.history.length === 0;\n }\n }\n\n // 渲染 DOM 结构\n private render(): void {\n this.shadow.innerHTML = `\n <style>${this.getStyles()}</style>\n <div class=\"editor-container\">\n <!-- 左侧工具栏 -->\n <div class=\"toolbar\">\n ${this.config.showPencil ? this.createToolButton('PENCIL', 'pencil-icon', '画笔 (P)') : ''}\n ${this.config.showRectangle ? this.createToolButton('RECTANGLE', 'rect-icon', '矩形 (R)') : ''}\n ${this.config.showCircle ? this.createToolButton('CIRCLE', 'circle-icon', '圆形 (O)') : ''}\n ${this.config.showText ? this.createToolButton('TEXT', 'text-icon', '文本 (T)') : ''}\n ${this.config.showImage ? `\n <label class=\"tool-btn\" title=\"插入图片\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/>\n <path d=\"M21 15l-5-5L5 21\"/>\n </svg>\n <input type=\"file\" accept=\"image/*\" class=\"hidden image-input\" />\n </label>\n ` : ''}\n <div class=\"divider\"></div>\n <button class=\"tool-btn undo-btn\" title=\"撤销 (Ctrl+Z)\" disabled>\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M3 7v6h6M3 13a9 9 0 1 0 2.5-6.5L3 7\"/>\n </svg>\n </button>\n <div class=\"spacer\"></div>\n ${this.config.showColor ? `\n <input type=\"color\" class=\"color-picker\" value=\"${this.color}\" title=\"颜色\" />\n ` : ''}\n </div>\n\n <!-- 主区域 -->\n <div class=\"main-area\">\n <!-- 顶部栏 -->\n <div class=\"top-bar\">\n <div class=\"top-bar-left\">\n <h2 class=\"title\">${this.config.title}</h2>\n <div class=\"selection-info\"></div>\n </div>\n <div class=\"top-bar-right\">\n ${this.config.showZoom ? `\n <div class=\"zoom-controls\">\n <button class=\"zoom-btn zoom-out-btn\" title=\"缩小\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"M21 21l-4.35-4.35M8 11h6\"/>\n </svg>\n </button>\n <button class=\"zoom-text\" title=\"重置缩放\">100%</button>\n <button class=\"zoom-btn zoom-in-btn\" title=\"放大\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"M21 21l-4.35-4.35M11 8v6M8 11h6\"/>\n </svg>\n </button>\n </div>\n ` : ''}\n ${(this.config.showExport || this.config.showImport || this.config.showDownload) ? `\n <div class=\"file-controls\">\n ${this.config.showExport ? `\n <button class=\"file-btn save-json-btn\" title=\"保存项目 (JSON)\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M19 21H5a2 2 0 01-2-2V5a2 2 0 012-2h11l5 5v11a2 2 0 01-2 2z\"/>\n <polyline points=\"17 21 17 13 7 13 7 21\"/><polyline points=\"7 3 7 8 15 8\"/>\n </svg>\n </button>\n ` : ''}\n ${this.config.showImport ? `\n <label class=\"file-btn\" title=\"加载项目 (JSON)\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z\"/>\n </svg>\n <input type=\"file\" accept=\".json\" class=\"hidden load-json-input\" />\n </label>\n ` : ''}\n ${this.config.showDownload ? `\n <button class=\"file-btn export-png-btn\" title=\"导出 PNG\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3\"/>\n </svg>\n </button>\n ` : ''}\n </div>\n ` : ''}\n </div>\n </div>\n\n <!-- 画布容器 -->\n <div class=\"canvas-container\">\n <canvas class=\"main-canvas\"></canvas>\n\n ${this.config.showMinimap ? `\n <div class=\"minimap-wrapper\">\n <div class=\"minimap-header\">\n <svg class=\"minimap-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <path d=\"M3 9h18M9 21V9\"/>\n </svg>\n <span>导航</span>\n </div>\n <canvas class=\"minimap-canvas\" width=\"220\" height=\"140\"></canvas>\n </div>\n ` : ''}\n\n <!-- 文本输入 -->\n <div class=\"text-input-container\" style=\"display: none;\">\n <input type=\"text\" class=\"text-input\" placeholder=\"输入文本...\" />\n </div>\n\n <!-- 空画布提示 -->\n <div class=\"empty-hint\">\n <h3>开始创作</h3>\n <p>选择左侧的工具开始绘制</p>\n </div>\n </div>\n </div>\n </div>\n `;\n\n // 获取 DOM 引用\n this.container = this.shadow.querySelector('.editor-container')!;\n this.toolbar = this.shadow.querySelector('.toolbar')!;\n this.topBar = this.shadow.querySelector('.top-bar')!;\n this.canvasContainer = this.shadow.querySelector('.canvas-container')!;\n this.canvas = this.shadow.querySelector('.main-canvas')!;\n this.ctx = this.canvas.getContext('2d')!;\n\n if (this.config.showMinimap) {\n this.minimapCanvas = this.shadow.querySelector('.minimap-canvas')!;\n this.minimapCtx = this.minimapCanvas.getContext('2d')!;\n }\n\n this.textInputContainer = this.shadow.querySelector('.text-input-container')!;\n this.textInput = this.shadow.querySelector('.text-input')!;\n\n // 绑定事件\n this.bindEvents();\n }\n\n // 绑定事件\n private bindEvents(): void {\n // 画布事件\n this.canvas.addEventListener('mousedown', (e) => this.handleCanvasPointerDown(e));\n this.canvas.addEventListener('mousemove', (e) => this.handleCanvasPointerMove(e));\n this.canvas.addEventListener('mouseup', () => this.handleCanvasPointerUp());\n this.canvas.addEventListener('mouseleave', () => this.handleCanvasPointerUp());\n this.canvas.addEventListener('dblclick', (e) => this.handleCanvasDoubleClick(e));\n this.canvas.addEventListener('touchstart', (e) => this.handleCanvasPointerDown(e));\n this.canvas.addEventListener('touchmove', (e) => this.handleCanvasPointerMove(e));\n this.canvas.addEventListener('touchend', () => this.handleCanvasPointerUp());\n this.canvas.addEventListener('wheel', this.boundHandleWheel, { passive: false });\n\n // 工具按钮\n this.shadow.querySelectorAll('.tool-btn[data-tool]').forEach(btn => {\n btn.addEventListener('click', () => {\n const tool = btn.getAttribute('data-tool') as ToolType;\n this.setTool(tool);\n });\n });\n\n // 撤销按钮\n const undoBtn = this.shadow.querySelector('.undo-btn');\n if (undoBtn) {\n undoBtn.addEventListener('click', () => this.undo());\n }\n\n // 颜色选择器\n const colorPicker = this.shadow.querySelector('.color-picker') as HTMLInputElement;\n if (colorPicker) {\n colorPicker.addEventListener('input', (e) => {\n this.color = (e.target as HTMLInputElement).value;\n });\n }\n\n // 图片上传\n const imageInput = this.shadow.querySelector('.image-input');\n if (imageInput) {\n imageInput.addEventListener('change', (e) => this.handleImageUpload(e));\n }\n\n // 缩放按钮\n const zoomInBtn = this.shadow.querySelector('.zoom-in-btn');\n const zoomOutBtn = this.shadow.querySelector('.zoom-out-btn');\n const zoomText = this.shadow.querySelector('.zoom-text');\n if (zoomInBtn) zoomInBtn.addEventListener('click', () => this.zoomIn());\n if (zoomOutBtn) zoomOutBtn.addEventListener('click', () => this.zoomOut());\n if (zoomText) zoomText.addEventListener('click', () => this.resetZoom());\n\n // 文件操作\n const saveJsonBtn = this.shadow.querySelector('.save-json-btn');\n const loadJsonInput = this.shadow.querySelector('.load-json-input');\n const exportPngBtn = this.shadow.querySelector('.export-png-btn');\n if (saveJsonBtn) saveJsonBtn.addEventListener('click', () => this.saveJson());\n if (loadJsonInput) loadJsonInput.addEventListener('change', (e) => this.loadJson(e));\n if (exportPngBtn) exportPngBtn.addEventListener('click', () => this.exportPng());\n\n // 小地图点击\n if (this.minimapCanvas) {\n this.minimapCanvas.addEventListener('click', (e) => this.handleMinimapClick(e));\n }\n\n // 文本输入\n if (this.textInput) {\n this.textInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.submitText();\n } else if (e.key === 'Escape') {\n this.hideTextInput();\n }\n });\n this.textInput.addEventListener('blur', () => {\n if (this.isTextInputVisible) {\n this.submitText();\n }\n });\n }\n }\n\n // 创建工具按钮 HTML\n private createToolButton(tool: ToolType, iconClass: string, title: string): string {\n const icons: Record<string, string> = {\n 'pencil-icon': '<path d=\"M17 3a2.85 2.85 0 114 4L7.5 20.5 2 22l1.5-5.5L17 3z\"/>',\n 'rect-icon': '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>',\n 'circle-icon': '<circle cx=\"12\" cy=\"12\" r=\"10\"/>',\n 'text-icon': '<path d=\"M4 7V4h16v3M9 20h6M12 4v16\"/>',\n };\n const isActive = this.tool === tool;\n return `\n <button class=\"tool-btn ${isActive ? 'active' : ''}\" data-tool=\"${tool}\" title=\"${title}\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n ${icons[iconClass]}\n </svg>\n </button>\n `;\n }\n\n // 获取样式\n private getStyles(): string {\n return `\n :host {\n display: block;\n width: 100%;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n .hidden {\n display: none !important;\n }\n\n .editor-container {\n display: flex;\n width: 100%;\n height: 100%;\n background: #f1f5f9;\n }\n\n /* 工具栏 */\n .toolbar {\n width: 64px;\n background: #ffffff;\n border-right: 1px solid #e2e8f0;\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 12px 8px;\n gap: 4px;\n }\n\n .tool-btn {\n width: 44px;\n height: 44px;\n border: none;\n background: transparent;\n border-radius: 12px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #64748b;\n transition: all 0.2s;\n }\n\n .tool-btn:hover {\n background: #f1f5f9;\n color: #4f46e5;\n }\n\n .tool-btn.active {\n background: #4f46e5;\n color: #ffffff;\n box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3);\n transform: scale(1.05);\n }\n\n .tool-btn:disabled {\n color: #cbd5e1;\n cursor: not-allowed;\n }\n\n .tool-btn:disabled:hover {\n background: transparent;\n color: #cbd5e1;\n }\n\n .icon {\n width: 20px;\n height: 20px;\n }\n\n .divider {\n width: 32px;\n height: 1px;\n background: #e2e8f0;\n margin: 8px 0;\n }\n\n .spacer {\n flex: 1;\n }\n\n .color-picker {\n width: 32px;\n height: 32px;\n border: 2px solid #e2e8f0;\n border-radius: 50%;\n cursor: pointer;\n padding: 0;\n overflow: hidden;\n -webkit-appearance: none;\n }\n\n .color-picker::-webkit-color-swatch-wrapper {\n padding: 0;\n }\n\n .color-picker::-webkit-color-swatch {\n border: none;\n border-radius: 50%;\n }\n\n /* 主区域 */\n .main-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* 顶部栏 */\n .top-bar {\n height: 56px;\n background: #ffffff;\n border-bottom: 1px solid #e2e8f0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 16px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n }\n\n .top-bar-left, .top-bar-right {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .title {\n font-size: 16px;\n font-weight: 600;\n color: #334155;\n }\n\n .selection-info {\n display: none;\n align-items: center;\n gap: 8px;\n background: #eef2ff;\n padding: 4px 12px;\n border-radius: 20px;\n border: 1px solid #c7d2fe;\n }\n\n .selection-info.visible {\n display: flex;\n }\n\n .selection-label {\n font-size: 12px;\n font-weight: 600;\n color: #4f46e5;\n text-transform: uppercase;\n }\n\n .delete-btn {\n background: none;\n border: none;\n color: #ef4444;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .delete-btn:hover {\n color: #dc2626;\n }\n\n .zoom-controls, .file-controls {\n display: flex;\n align-items: center;\n background: #f1f5f9;\n border-radius: 8px;\n padding: 4px;\n }\n\n .zoom-btn, .file-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #475569;\n transition: all 0.2s;\n }\n\n .zoom-btn:hover, .file-btn:hover {\n color: #4f46e5;\n }\n\n .zoom-text {\n padding: 4px 8px;\n font-size: 12px;\n font-weight: 500;\n color: #475569;\n background: transparent;\n border: none;\n cursor: pointer;\n min-width: 50px;\n text-align: center;\n }\n\n .zoom-text:hover {\n color: #4f46e5;\n }\n\n /* 画布容器 */\n .canvas-container {\n flex: 1;\n position: relative;\n background: #f1f5f9;\n overflow: hidden;\n }\n\n .main-canvas {\n position: absolute;\n inset: 0;\n display: block;\n cursor: crosshair;\n touch-action: none;\n }\n\n /* 小地图 */\n .minimap-wrapper {\n position: absolute;\n top: 16px;\n right: 16px;\n z-index: 30;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n padding: 2px;\n }\n\n .minimap-wrapper > * {\n background: #ffffff;\n }\n\n .minimap-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: linear-gradient(to right, #f8fafc, #f1f5f9);\n border-bottom: 1px solid #e2e8f0;\n font-size: 12px;\n font-weight: 600;\n color: #475569;\n border-radius: 10px 10px 0 0;\n }\n\n .minimap-icon {\n width: 12px;\n height: 12px;\n color: #4f46e5;\n }\n\n .minimap-canvas {\n cursor: pointer;\n background: #f8fafc;\n border-radius: 0 0 10px 10px;\n display: block;\n }\n\n .minimap-canvas:hover {\n filter: brightness(1.05);\n }\n\n /* 文本输入 */\n .text-input-container {\n position: absolute;\n z-index: 20;\n }\n\n .text-input {\n padding: 8px 12px;\n border: 2px solid #4f46e5;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n outline: none;\n min-width: 200px;\n font-size: 16px;\n }\n\n /* 空画布提示 */\n .empty-hint {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n opacity: 0.4;\n }\n\n .empty-hint h3 {\n font-size: 24px;\n font-weight: 700;\n color: #94a3b8;\n margin-bottom: 8px;\n }\n\n .empty-hint p {\n color: #94a3b8;\n }\n `;\n }\n}\n\n// 注册 Web Component\nif (typeof window !== 'undefined' && !customElements.get('canvas-drawing-editor')) {\n customElements.define('canvas-drawing-editor', CanvasDrawingEditor);\n}\n"],"names":["defaultConfig","CanvasDrawingEditor","name","oldValue","newValue","e","rect","clientX","clientY","x","y","obj","r","c","t","width","p","minX","pt","maxX","minY","maxY","bounds","handleSize","handles","handle","img","previousState","o","selectedObj","newObj","mouseX","mouseY","delta","newScale","centerX","centerY","clampedScale","mouseXBeforeZoom","mouseYBeforeZoom","newPanOffsetX","newPanOffsetY","zoomText","tool","btn","screenX","screenY","text","_a","_b","value","existingObj","screenPos","clickedObject","id","dx","dy","newX","newY","newWidth","newHeight","radius","origT","scaleFactor","origP","scaleX","scaleY","textObj","ctx","isMinimap","i","imgObj","corner","minimap","mainCanvas","minimapScale","canvasW","canvasH","offsetX","offsetY","clickX","clickY","relX","relY","canvasX","canvasY","viewportCenterX","viewportCenterY","input","file","reader","event","dataUrl","maxSize","height","ratio","data","imageElement","rest","json","blob","url","a","err","tempCanvas","tempCtx","selectionInfo","typeLabel","deleteBtn","undoBtn","colorPicker","imageInput","zoomInBtn","zoomOutBtn","saveJsonBtn","loadJsonInput","exportPngBtn","iconClass","title","icons"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"canvas-drawing-editor.es.js","sources":["../src/core/CanvasDrawingEditor.ts"],"sourcesContent":["/**\n * Canvas Drawing Editor - 纯 JavaScript Web Component\n * 无任何框架依赖\n */\n\n// 类型定义\nexport type ToolType = 'SELECT' | 'PENCIL' | 'RECTANGLE' | 'CIRCLE' | 'TEXT' | 'IMAGE';\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface BaseObject {\n id: string;\n type: string;\n x: number;\n y: number;\n color: string;\n lineWidth: number;\n}\n\nexport interface RectObject extends BaseObject {\n type: 'RECTANGLE';\n width: number;\n height: number;\n}\n\nexport interface CircleObject extends BaseObject {\n type: 'CIRCLE';\n radius: number;\n}\n\nexport interface PathObject extends BaseObject {\n type: 'PATH';\n points: Point[];\n}\n\nexport interface TextObject extends BaseObject {\n type: 'TEXT';\n text: string;\n fontSize: number;\n}\n\nexport interface ImageObject extends BaseObject {\n type: 'IMAGE';\n width: number;\n height: number;\n dataUrl: string;\n imageElement?: HTMLImageElement;\n}\n\nexport type CanvasObject = RectObject | CircleObject | PathObject | TextObject | ImageObject;\n\nexport interface EditorConfig {\n title?: string;\n showPencil?: boolean;\n showRectangle?: boolean;\n showCircle?: boolean;\n showText?: boolean;\n showImage?: boolean;\n showZoom?: boolean;\n showDownload?: boolean;\n showExport?: boolean;\n showImport?: boolean;\n showColor?: boolean;\n showMinimap?: boolean;\n}\n\n// 默认配置\nconst defaultConfig: EditorConfig = {\n title: 'Canvas Editor',\n showPencil: true,\n showRectangle: true,\n showCircle: true,\n showText: true,\n showImage: true,\n showZoom: true,\n showDownload: true,\n showExport: true,\n showImport: true,\n showColor: true,\n showMinimap: true,\n};\n\n/**\n * Canvas Drawing Editor Web Component\n */\nexport class CanvasDrawingEditor extends HTMLElement {\n // Shadow DOM\n private shadow: ShadowRoot;\n\n // DOM 元素\n private container!: HTMLDivElement;\n private toolbar!: HTMLDivElement;\n private topBar!: HTMLDivElement;\n private canvasContainer!: HTMLDivElement;\n private canvas!: HTMLCanvasElement;\n private ctx!: CanvasRenderingContext2D;\n private minimapCanvas!: HTMLCanvasElement;\n private minimapCtx!: CanvasRenderingContext2D;\n private textInput!: HTMLInputElement;\n private textInputContainer!: HTMLDivElement;\n\n // 配置\n private config: EditorConfig = { ...defaultConfig };\n\n // 状态\n private objects: CanvasObject[] = [];\n private selectedId: string | null = null;\n private tool: ToolType = 'SELECT';\n private color: string = '#000000';\n private lineWidth: number = 3;\n\n // 交互状态\n private isDragging: boolean = false;\n private dragStart: Point | null = null;\n private currentObject: CanvasObject | null = null;\n private dragOffset: Point = { x: 0, y: 0 };\n\n // 文本输入状态\n private isTextInputVisible: boolean = false;\n private textInputPos: Point = { x: 0, y: 0 };\n private textInputScreenPos: Point = { x: 0, y: 0 };\n private editingTextId: string | null = null;\n\n // 调整大小状态\n private isResizing: boolean = false;\n private resizeHandle: string | null = null;\n private resizeStartBounds: { x: number; y: number; width: number; height: number } | null = null;\n private resizeOriginalObject: CanvasObject | null = null;\n\n // 历史记录\n private history: CanvasObject[][] = [];\n private clipboard: CanvasObject | null = null;\n\n // 缩放状态\n private scale: number = 1;\n private panOffset: Point = { x: 0, y: 0 };\n\n // 平移状态\n private isPanning: boolean = false;\n private panStart: Point = { x: 0, y: 0 };\n\n // 绑定的事件处理器(用于移除监听)\n private boundHandleResize: () => void;\n private boundHandleKeyDown: (e: KeyboardEvent) => void;\n private boundHandleWheel: (e: WheelEvent) => void;\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n \n // 绑定事件处理器\n this.boundHandleResize = this.handleResize.bind(this);\n this.boundHandleKeyDown = this.handleKeyDown.bind(this);\n this.boundHandleWheel = this.handleWheel.bind(this);\n }\n\n // 观察的属性\n static get observedAttributes(): string[] {\n return [\n 'title', 'show-pencil', 'show-rectangle', 'show-circle', 'show-text',\n 'show-image', 'show-zoom', 'show-download', 'show-export', 'show-import',\n 'show-color', 'show-minimap'\n ];\n }\n\n // 生命周期:连接到 DOM\n connectedCallback(): void {\n this.parseAttributes();\n this.render();\n this.setupEventListeners();\n this.initCanvas();\n }\n\n // 生命周期:从 DOM 断开\n disconnectedCallback(): void {\n this.removeEventListeners();\n }\n\n // 生命周期:属性变化\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n this.parseAttributes();\n if (this.container) {\n this.updateUI();\n }\n }\n\n // 解析 HTML 属性\n private parseAttributes(): void {\n this.config = {\n title: this.getAttribute('title') || defaultConfig.title,\n showPencil: this.getAttribute('show-pencil') !== 'false',\n showRectangle: this.getAttribute('show-rectangle') !== 'false',\n showCircle: this.getAttribute('show-circle') !== 'false',\n showText: this.getAttribute('show-text') !== 'false',\n showImage: this.getAttribute('show-image') !== 'false',\n showZoom: this.getAttribute('show-zoom') !== 'false',\n showDownload: this.getAttribute('show-download') !== 'false',\n showExport: this.getAttribute('show-export') !== 'false',\n showImport: this.getAttribute('show-import') !== 'false',\n showColor: this.getAttribute('show-color') !== 'false',\n showMinimap: this.getAttribute('show-minimap') !== 'false',\n };\n }\n\n // 生成唯一 ID\n private generateId(): string {\n return Math.random().toString(36).substr(2, 9);\n }\n\n // 设置事件监听\n private setupEventListeners(): void {\n window.addEventListener('resize', this.boundHandleResize);\n window.addEventListener('keydown', this.boundHandleKeyDown);\n }\n\n // 移除事件监听\n private removeEventListeners(): void {\n window.removeEventListener('resize', this.boundHandleResize);\n window.removeEventListener('keydown', this.boundHandleKeyDown);\n if (this.canvas) {\n this.canvas.removeEventListener('wheel', this.boundHandleWheel);\n }\n }\n\n // 窗口大小变化处理\n private handleResize(): void {\n this.initCanvas();\n }\n\n // 初始化画布\n private initCanvas(): void {\n if (!this.canvasContainer || !this.canvas) return;\n\n // 使用 requestAnimationFrame 确保 DOM 已经渲染\n requestAnimationFrame(() => {\n this.canvas.width = this.canvasContainer.clientWidth;\n this.canvas.height = this.canvasContainer.clientHeight;\n this.renderCanvas();\n this.renderMinimap();\n });\n }\n\n // 获取鼠标在画布上的位置(考虑缩放和平移)\n private getMousePos(e: MouseEvent | TouchEvent): Point {\n const rect = this.canvas.getBoundingClientRect();\n let clientX: number, clientY: number;\n\n if ('touches' in e && e.touches.length > 0) {\n clientX = e.touches[0].clientX;\n clientY = e.touches[0].clientY;\n } else if ('clientX' in e) {\n clientX = e.clientX;\n clientY = e.clientY;\n } else {\n return { x: 0, y: 0 };\n }\n\n const x = (clientX - rect.left - this.panOffset.x) / this.scale;\n const y = (clientY - rect.top - this.panOffset.y) / this.scale;\n return { x, y };\n }\n\n // 获取屏幕坐标(不考虑缩放和平移)\n private getScreenPos(e: MouseEvent | TouchEvent): Point {\n const rect = this.canvas.getBoundingClientRect();\n let clientX: number, clientY: number;\n\n if ('touches' in e && e.touches.length > 0) {\n clientX = e.touches[0].clientX;\n clientY = e.touches[0].clientY;\n } else if ('clientX' in e) {\n clientX = e.clientX;\n clientY = e.clientY;\n } else {\n return { x: 0, y: 0 };\n }\n\n return { x: clientX - rect.left, y: clientY - rect.top };\n }\n\n // 获取对象边界\n private getObjectBounds(obj: CanvasObject): { x: number; y: number; width: number; height: number } {\n switch (obj.type) {\n case 'RECTANGLE':\n case 'IMAGE': {\n const r = obj as RectObject | ImageObject;\n return { x: r.x, y: r.y, width: r.width, height: r.height };\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n return { x: c.x - c.radius, y: c.y - c.radius, width: c.radius * 2, height: c.radius * 2 };\n }\n case 'TEXT': {\n const t = obj as TextObject;\n const width = t.text.length * t.fontSize * 0.6;\n return { x: t.x, y: t.y - t.fontSize, width, height: t.fontSize };\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length === 0) return { x: 0, y: 0, width: 0, height: 0 };\n const minX = Math.min(...p.points.map(pt => pt.x));\n const maxX = Math.max(...p.points.map(pt => pt.x));\n const minY = Math.min(...p.points.map(pt => pt.y));\n const maxY = Math.max(...p.points.map(pt => pt.y));\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n }\n }\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n\n // 检查调整大小手柄\n private getResizeHandleAtPoint(obj: CanvasObject, x: number, y: number): string | null {\n const bounds = this.getObjectBounds(obj);\n const handleSize = 8;\n\n const handles = [\n { name: 'nw', x: bounds.x, y: bounds.y },\n { name: 'ne', x: bounds.x + bounds.width, y: bounds.y },\n { name: 'sw', x: bounds.x, y: bounds.y + bounds.height },\n { name: 'se', x: bounds.x + bounds.width, y: bounds.y + bounds.height },\n ];\n\n for (const handle of handles) {\n if (Math.abs(x - handle.x) <= handleSize && Math.abs(y - handle.y) <= handleSize) {\n return handle.name;\n }\n }\n return null;\n }\n\n // 碰撞检测\n private isHit(obj: CanvasObject, x: number, y: number): boolean {\n switch (obj.type) {\n case 'RECTANGLE': {\n const r = obj as RectObject;\n return x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height;\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n const dist = Math.sqrt(Math.pow(x - c.x, 2) + Math.pow(y - c.y, 2));\n return dist <= c.radius;\n }\n case 'IMAGE': {\n const img = obj as ImageObject;\n return x >= img.x && x <= img.x + img.width && y >= img.y && y <= img.y + img.height;\n }\n case 'TEXT': {\n const t = obj as TextObject;\n return x >= t.x && x <= t.x + (t.text.length * t.fontSize * 0.6) && y >= t.y - t.fontSize && y <= t.y;\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length === 0) return false;\n const minX = Math.min(...p.points.map(pt => pt.x));\n const maxX = Math.max(...p.points.map(pt => pt.x));\n const minY = Math.min(...p.points.map(pt => pt.y));\n const maxY = Math.max(...p.points.map(pt => pt.y));\n return x >= minX && x <= maxX && y >= minY && y <= maxY;\n }\n }\n return false;\n }\n\n // 保存历史\n private saveHistory(): void {\n this.history.push(JSON.parse(JSON.stringify(this.objects)));\n }\n\n // 撤销\n private undo(): void {\n if (this.history.length === 0) return;\n const previousState = this.history.pop();\n if (previousState) {\n this.objects = previousState;\n this.selectedId = null;\n this.renderCanvas();\n this.renderMinimap();\n this.dispatchChangeEvent();\n }\n }\n\n // 删除选中对象\n private deleteSelected(): void {\n if (this.selectedId) {\n this.saveHistory();\n this.objects = this.objects.filter(o => o.id !== this.selectedId);\n this.selectedId = null;\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n }\n }\n\n // 复制选中对象\n private copySelected(): void {\n if (this.selectedId) {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n this.clipboard = JSON.parse(JSON.stringify(selectedObj));\n }\n }\n }\n\n // 粘贴对象\n private pasteObject(): void {\n if (this.clipboard) {\n this.saveHistory();\n const newObj = {\n ...JSON.parse(JSON.stringify(this.clipboard)),\n id: this.generateId(),\n x: this.clipboard.x + 20,\n y: this.clipboard.y + 20\n };\n if (newObj.type === 'PATH' && newObj.points) {\n newObj.points = newObj.points.map((pt: Point) => ({\n x: pt.x + 20,\n y: pt.y + 20\n }));\n }\n this.objects.push(newObj);\n this.selectedId = newObj.id;\n this.clipboard = newObj;\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n }\n }\n\n // 派发变化事件\n private dispatchChangeEvent(): void {\n this.dispatchEvent(new CustomEvent('editor-change', {\n bubbles: true,\n composed: true,\n detail: { objects: this.objects }\n }));\n }\n\n // 键盘事件处理\n private handleKeyDown(e: KeyboardEvent): void {\n if (this.isTextInputVisible) return;\n\n // Ctrl+Z: 撤销\n if ((e.ctrlKey || e.metaKey) && e.key === 'z') {\n e.preventDefault();\n this.undo();\n return;\n }\n\n // Ctrl+C: 复制\n if ((e.ctrlKey || e.metaKey) && e.key === 'c') {\n if (this.selectedId) {\n e.preventDefault();\n this.copySelected();\n }\n return;\n }\n\n // Ctrl+V: 粘贴\n if ((e.ctrlKey || e.metaKey) && e.key === 'v') {\n if (this.clipboard) {\n e.preventDefault();\n this.pasteObject();\n }\n return;\n }\n\n // Delete/Backspace: 删除\n if ((e.key === 'Delete' || e.key === 'Backspace') && this.selectedId) {\n e.preventDefault();\n this.deleteSelected();\n return;\n }\n\n // 快捷键切换工具\n if (!e.ctrlKey && !e.metaKey) {\n switch (e.key.toLowerCase()) {\n case 'v':\n this.setTool('SELECT');\n break;\n case 'p':\n case 'b':\n this.setTool('PENCIL');\n break;\n case 'r':\n this.setTool('RECTANGLE');\n break;\n case 'o':\n this.setTool('CIRCLE');\n break;\n case 't':\n this.setTool('TEXT');\n break;\n case 'escape':\n this.selectedId = null;\n this.hideTextInput();\n this.renderCanvas();\n this.updateUI();\n break;\n }\n }\n }\n\n // 滚轮缩放\n private handleWheel(e: WheelEvent): void {\n e.preventDefault();\n const rect = this.canvas.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n\n const delta = e.deltaY > 0 ? 0.9 : 1.1;\n const newScale = this.scale * delta;\n\n this.zoomAtPoint(newScale, mouseX, mouseY);\n }\n\n // 以指定点为中心缩放\n private zoomAtPoint(newScale: number, centerX: number, centerY: number): void {\n const clampedScale = Math.min(Math.max(newScale, 0.2), 5);\n\n const mouseXBeforeZoom = (centerX - this.panOffset.x) / this.scale;\n const mouseYBeforeZoom = (centerY - this.panOffset.y) / this.scale;\n\n const newPanOffsetX = centerX - mouseXBeforeZoom * clampedScale;\n const newPanOffsetY = centerY - mouseYBeforeZoom * clampedScale;\n\n this.scale = clampedScale;\n this.panOffset = { x: newPanOffsetX, y: newPanOffsetY };\n\n this.renderCanvas();\n this.renderMinimap();\n this.updateZoomDisplay();\n }\n\n // 放大\n private zoomIn(): void {\n const centerX = this.canvas.width / 2;\n const centerY = this.canvas.height / 2;\n this.zoomAtPoint(this.scale * 1.2, centerX, centerY);\n }\n\n // 缩小\n private zoomOut(): void {\n const centerX = this.canvas.width / 2;\n const centerY = this.canvas.height / 2;\n this.zoomAtPoint(this.scale / 1.2, centerX, centerY);\n }\n\n // 重置缩放\n private resetZoom(): void {\n this.scale = 1;\n this.panOffset = { x: 0, y: 0 };\n this.renderCanvas();\n this.renderMinimap();\n this.updateZoomDisplay();\n }\n\n // 更新缩放显示\n private updateZoomDisplay(): void {\n const zoomText = this.shadow.querySelector('.zoom-text');\n if (zoomText) {\n zoomText.textContent = `${Math.round(this.scale * 100)}%`;\n }\n }\n\n // 设置工具\n private setTool(tool: ToolType): void {\n this.tool = tool;\n this.updateToolButtons();\n }\n\n // 更新工具按钮状态\n private updateToolButtons(): void {\n const buttons = this.shadow.querySelectorAll('.tool-btn');\n buttons.forEach(btn => {\n const btnTool = btn.getAttribute('data-tool');\n if (btnTool === this.tool) {\n btn.classList.add('active');\n } else {\n btn.classList.remove('active');\n }\n });\n }\n\n // 隐藏文本输入\n private hideTextInput(): void {\n this.isTextInputVisible = false;\n if (this.textInputContainer) {\n this.textInputContainer.style.display = 'none';\n }\n this.editingTextId = null;\n }\n\n // 显示文本输入\n private showTextInput(screenX: number, screenY: number, text: string = ''): void {\n this.isTextInputVisible = true;\n this.textInputScreenPos = { x: screenX, y: screenY };\n\n if (this.textInputContainer && this.textInput) {\n this.textInputContainer.style.display = 'block';\n this.textInputContainer.style.left = `${screenX}px`;\n this.textInputContainer.style.top = `${screenY - 30}px`;\n this.textInput.value = text;\n this.textInput.style.color = this.color;\n setTimeout(() => {\n this.textInput.focus();\n if (text) this.textInput.select();\n }, 0);\n }\n }\n\n // 提交文本\n private submitText(): void {\n const value = this.textInput?.value?.trim();\n if (value) {\n if (this.editingTextId) {\n const existingObj = this.objects.find(o => o.id === this.editingTextId) as TextObject | undefined;\n if (existingObj && existingObj.text !== value) {\n this.saveHistory();\n existingObj.text = value;\n }\n this.selectedId = this.editingTextId;\n } else {\n this.saveHistory();\n const newObj: TextObject = {\n id: this.generateId(),\n type: 'TEXT',\n x: this.textInputPos.x,\n y: this.textInputPos.y,\n text: value,\n fontSize: 24,\n color: this.color,\n lineWidth: this.lineWidth\n };\n this.objects.push(newObj);\n this.selectedId = newObj.id;\n }\n this.dispatchChangeEvent();\n }\n this.hideTextInput();\n this.setTool('SELECT');\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n }\n\n // 画布鼠标按下\n private handleCanvasPointerDown(e: MouseEvent | TouchEvent): void {\n const { x, y } = this.getMousePos(e);\n const screenPos = this.getScreenPos(e);\n this.dragStart = { x, y };\n this.isDragging = true;\n\n // 如果文本输入可见且不是文本工具,先保存文本\n if (this.isTextInputVisible && this.tool !== 'TEXT') {\n this.submitText();\n }\n\n if (this.tool === 'SELECT') {\n // 检查是否点击调整大小手柄\n if (this.selectedId) {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n const handle = this.getResizeHandleAtPoint(selectedObj, x, y);\n if (handle) {\n this.saveHistory();\n this.isResizing = true;\n this.resizeHandle = handle;\n this.resizeStartBounds = this.getObjectBounds(selectedObj);\n this.resizeOriginalObject = JSON.parse(JSON.stringify(selectedObj));\n return;\n }\n }\n }\n\n // 查找点击的对象\n const clickedObject = [...this.objects].reverse().find(obj => this.isHit(obj, x, y));\n\n if (clickedObject) {\n this.selectedId = clickedObject.id;\n this.dragOffset = { x: x - clickedObject.x, y: y - clickedObject.y };\n this.saveHistory();\n this.updateUI();\n } else {\n // 开始拖拽画布\n this.selectedId = null;\n this.isPanning = true;\n this.panStart = screenPos;\n this.updateUI();\n }\n } else if (this.tool === 'TEXT') {\n // 显示文本输入\n this.textInputPos = { x, y };\n this.showTextInput(screenPos.x, screenPos.y);\n this.isDragging = false;\n } else {\n // 开始绘制图形\n this.saveHistory();\n const id = this.generateId();\n if (this.tool === 'RECTANGLE') {\n this.currentObject = { id, type: 'RECTANGLE', x, y, width: 0, height: 0, color: this.color, lineWidth: this.lineWidth };\n } else if (this.tool === 'CIRCLE') {\n this.currentObject = { id, type: 'CIRCLE', x, y, radius: 0, color: this.color, lineWidth: this.lineWidth };\n } else if (this.tool === 'PENCIL') {\n this.currentObject = { id, type: 'PATH', x, y, points: [{ x, y }], color: this.color, lineWidth: this.lineWidth };\n }\n }\n\n this.renderCanvas();\n }\n\n // 画布鼠标移动\n private handleCanvasPointerMove(e: MouseEvent | TouchEvent): void {\n // 处理画布拖拽\n if (this.isPanning) {\n const screenPos = this.getScreenPos(e);\n const dx = screenPos.x - this.panStart.x;\n const dy = screenPos.y - this.panStart.y;\n this.panOffset = { x: this.panOffset.x + dx, y: this.panOffset.y + dy };\n this.panStart = screenPos;\n this.renderCanvas();\n this.renderMinimap();\n return;\n }\n\n if (!this.isDragging || !this.dragStart) return;\n const { x, y } = this.getMousePos(e);\n\n // 处理调整大小\n if (this.isResizing && this.selectedId && this.resizeHandle && this.resizeStartBounds && this.resizeOriginalObject) {\n const obj = this.objects.find(o => o.id === this.selectedId);\n if (!obj) return;\n\n const dx = x - this.dragStart.x;\n const dy = y - this.dragStart.y;\n let newX = this.resizeStartBounds.x;\n let newY = this.resizeStartBounds.y;\n let newWidth = this.resizeStartBounds.width;\n let newHeight = this.resizeStartBounds.height;\n\n if (this.resizeHandle.includes('e')) newWidth = this.resizeStartBounds.width + dx;\n if (this.resizeHandle.includes('w')) {\n newX = this.resizeStartBounds.x + dx;\n newWidth = this.resizeStartBounds.width - dx;\n }\n if (this.resizeHandle.includes('s')) newHeight = this.resizeStartBounds.height + dy;\n if (this.resizeHandle.includes('n')) {\n newY = this.resizeStartBounds.y + dy;\n newHeight = this.resizeStartBounds.height - dy;\n }\n\n newWidth = Math.max(10, newWidth);\n newHeight = Math.max(10, newHeight);\n\n // 根据对象类型应用变化\n switch (obj.type) {\n case 'RECTANGLE':\n case 'IMAGE':\n (obj as RectObject | ImageObject).x = newX;\n (obj as RectObject | ImageObject).y = newY;\n (obj as RectObject | ImageObject).width = newWidth;\n (obj as RectObject | ImageObject).height = newHeight;\n break;\n case 'CIRCLE': {\n const radius = Math.max(newWidth, newHeight) / 2;\n (obj as CircleObject).x = newX + radius;\n (obj as CircleObject).y = newY + radius;\n (obj as CircleObject).radius = radius;\n break;\n }\n case 'TEXT': {\n const origT = this.resizeOriginalObject as TextObject;\n const scaleFactor = newWidth / this.resizeStartBounds.width;\n (obj as TextObject).x = newX;\n (obj as TextObject).y = newY + newHeight;\n (obj as TextObject).fontSize = Math.max(8, Math.round(origT.fontSize * scaleFactor));\n break;\n }\n case 'PATH': {\n const origP = this.resizeOriginalObject as PathObject;\n const scaleX = newWidth / this.resizeStartBounds.width;\n const scaleY = newHeight / this.resizeStartBounds.height;\n (obj as PathObject).points = origP.points.map(pt => ({\n x: newX + (pt.x - this.resizeStartBounds!.x) * scaleX,\n y: newY + (pt.y - this.resizeStartBounds!.y) * scaleY\n }));\n break;\n }\n }\n\n this.renderCanvas();\n this.renderMinimap();\n return;\n }\n\n // 移动选中对象\n if (this.tool === 'SELECT' && this.selectedId) {\n const obj = this.objects.find(o => o.id === this.selectedId);\n if (obj) {\n if (obj.type === 'PATH') {\n const p = obj as PathObject;\n const dx = x - this.dragStart.x;\n const dy = y - this.dragStart.y;\n p.points = p.points.map(pt => ({ x: pt.x + dx, y: pt.y + dy }));\n this.dragStart = { x, y };\n } else {\n obj.x = x - this.dragOffset.x;\n obj.y = y - this.dragOffset.y;\n }\n this.renderCanvas();\n this.renderMinimap();\n }\n } else if (this.currentObject) {\n // 更新正在绘制的图形\n if (this.currentObject.type === 'RECTANGLE') {\n (this.currentObject as RectObject).width = x - this.currentObject.x;\n (this.currentObject as RectObject).height = y - this.currentObject.y;\n } else if (this.currentObject.type === 'CIRCLE') {\n const radius = Math.sqrt(Math.pow(x - this.currentObject.x, 2) + Math.pow(y - this.currentObject.y, 2));\n (this.currentObject as CircleObject).radius = radius;\n } else if (this.currentObject.type === 'PATH') {\n (this.currentObject as PathObject).points.push({ x, y });\n }\n this.renderCanvas();\n }\n }\n\n // 画布鼠标抬起\n private handleCanvasPointerUp(): void {\n this.isDragging = false;\n this.dragStart = null;\n this.isResizing = false;\n this.resizeHandle = null;\n this.resizeStartBounds = null;\n this.resizeOriginalObject = null;\n this.isPanning = false;\n\n if (this.currentObject) {\n this.objects.push(this.currentObject);\n this.currentObject = null;\n this.dispatchChangeEvent();\n }\n\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n }\n\n // 双击编辑文本\n private handleCanvasDoubleClick(e: MouseEvent): void {\n e.preventDefault();\n const { x, y } = this.getMousePos(e);\n\n const clickedObject = [...this.objects].reverse().find(obj => this.isHit(obj, x, y));\n\n if (clickedObject && clickedObject.type === 'TEXT') {\n const textObj = clickedObject as TextObject;\n this.editingTextId = textObj.id;\n this.textInputPos = { x: textObj.x, y: textObj.y };\n const screenX = textObj.x * this.scale + this.panOffset.x;\n const screenY = textObj.y * this.scale + this.panOffset.y;\n this.showTextInput(screenX, screenY, textObj.text);\n this.setTool('SELECT');\n }\n }\n\n // 渲染画布\n private renderCanvas(): void {\n if (!this.ctx) return;\n\n // 清空画布\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n // 绘制背景\n this.ctx.fillStyle = '#ffffff';\n this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);\n\n // 应用缩放和平移\n this.ctx.save();\n this.ctx.translate(this.panOffset.x, this.panOffset.y);\n this.ctx.scale(this.scale, this.scale);\n\n // 绘制所有对象\n this.objects.forEach(obj => this.drawObject(this.ctx, obj, false));\n\n // 绘制正在创建的对象\n if (this.currentObject) {\n this.drawObject(this.ctx, this.currentObject, false);\n }\n\n // 绘制选中对象的调整手柄\n if (this.selectedId && this.tool === 'SELECT') {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n this.drawSelectionHandles(this.ctx, selectedObj);\n }\n }\n\n this.ctx.restore();\n }\n\n // 绘制单个对象\n private drawObject(ctx: CanvasRenderingContext2D, obj: CanvasObject, isMinimap: boolean): void {\n ctx.beginPath();\n ctx.strokeStyle = obj.color;\n ctx.lineWidth = obj.lineWidth;\n ctx.fillStyle = obj.color;\n\n // 选中高亮(仅主画布)\n if (!isMinimap && obj.id === this.selectedId) {\n ctx.shadowColor = 'rgba(0, 100, 255, 0.5)';\n ctx.shadowBlur = 10;\n } else {\n ctx.shadowBlur = 0;\n }\n\n switch (obj.type) {\n case 'RECTANGLE': {\n const r = obj as RectObject;\n ctx.strokeRect(r.x, r.y, r.width, r.height);\n break;\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n ctx.beginPath();\n ctx.arc(c.x, c.y, c.radius, 0, 2 * Math.PI);\n ctx.stroke();\n break;\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length < 2) break;\n ctx.beginPath();\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n ctx.moveTo(p.points[0].x, p.points[0].y);\n for (let i = 1; i < p.points.length; i++) {\n ctx.lineTo(p.points[i].x, p.points[i].y);\n }\n ctx.stroke();\n break;\n }\n case 'TEXT': {\n const t = obj as TextObject;\n ctx.font = `${t.fontSize}px sans-serif`;\n ctx.fillText(t.text, t.x, t.y);\n break;\n }\n case 'IMAGE': {\n const imgObj = obj as ImageObject;\n if (imgObj.imageElement && imgObj.imageElement.complete) {\n ctx.drawImage(imgObj.imageElement, imgObj.x, imgObj.y, imgObj.width, imgObj.height);\n } else if (imgObj.dataUrl) {\n // 加载图片\n const img = new Image();\n img.onload = () => {\n imgObj.imageElement = img;\n this.renderCanvas();\n };\n img.src = imgObj.dataUrl;\n }\n break;\n }\n }\n }\n\n // 绘制选中手柄\n private drawSelectionHandles(ctx: CanvasRenderingContext2D, obj: CanvasObject): void {\n const bounds = this.getObjectBounds(obj);\n const handleSize = 8;\n\n ctx.shadowBlur = 0;\n ctx.fillStyle = '#3b82f6';\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 2;\n\n // 绘制角落手柄\n const corners = [\n { x: bounds.x, y: bounds.y },\n { x: bounds.x + bounds.width, y: bounds.y },\n { x: bounds.x, y: bounds.y + bounds.height },\n { x: bounds.x + bounds.width, y: bounds.y + bounds.height },\n ];\n\n corners.forEach(corner => {\n ctx.beginPath();\n ctx.rect(corner.x - handleSize / 2, corner.y - handleSize / 2, handleSize, handleSize);\n ctx.fill();\n ctx.stroke();\n });\n\n // 绘制选择边框\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 1;\n ctx.setLineDash([5, 5]);\n ctx.strokeRect(bounds.x, bounds.y, bounds.width, bounds.height);\n ctx.setLineDash([]);\n }\n\n // 渲染小地图\n private renderMinimap(): void {\n if (!this.minimapCtx || !this.config.showMinimap) return;\n\n const minimap = this.minimapCanvas;\n const mainCanvas = this.canvas;\n\n this.minimapCtx.clearRect(0, 0, minimap.width, minimap.height);\n\n // 计算缩放比例\n const scaleX = minimap.width / mainCanvas.width;\n const scaleY = minimap.height / mainCanvas.height;\n const minimapScale = Math.min(scaleX, scaleY) * 0.92;\n\n const canvasW = mainCanvas.width * minimapScale;\n const canvasH = mainCanvas.height * minimapScale;\n const offsetX = (minimap.width - canvasW) / 2;\n const offsetY = (minimap.height - canvasH) / 2;\n\n // 绘制画布区域背景\n this.minimapCtx.fillStyle = '#ffffff';\n this.minimapCtx.fillRect(offsetX, offsetY, canvasW, canvasH);\n\n // 应用主画布的缩放和平移变换\n this.minimapCtx.save();\n this.minimapCtx.translate(offsetX, offsetY);\n this.minimapCtx.scale(minimapScale, minimapScale);\n this.minimapCtx.translate(this.panOffset.x, this.panOffset.y);\n this.minimapCtx.scale(this.scale, this.scale);\n\n // 绘制所有对象\n const allObjects = this.currentObject ? [...this.objects, this.currentObject] : this.objects;\n allObjects.forEach(obj => {\n this.minimapCtx.fillStyle = obj.color;\n this.minimapCtx.strokeStyle = obj.color;\n this.minimapCtx.lineWidth = Math.max(obj.lineWidth, 1);\n this.minimapCtx.setLineDash([]);\n\n switch (obj.type) {\n case 'RECTANGLE': {\n const r = obj as RectObject;\n this.minimapCtx.strokeRect(r.x, r.y, r.width, r.height);\n break;\n }\n case 'CIRCLE': {\n const c = obj as CircleObject;\n this.minimapCtx.beginPath();\n this.minimapCtx.arc(c.x, c.y, c.radius, 0, Math.PI * 2);\n this.minimapCtx.stroke();\n break;\n }\n case 'PATH': {\n const p = obj as PathObject;\n if (p.points.length > 0) {\n this.minimapCtx.beginPath();\n this.minimapCtx.lineCap = 'round';\n this.minimapCtx.lineJoin = 'round';\n this.minimapCtx.moveTo(p.points[0].x, p.points[0].y);\n p.points.forEach(pt => this.minimapCtx.lineTo(pt.x, pt.y));\n this.minimapCtx.stroke();\n }\n break;\n }\n case 'TEXT': {\n const t = obj as TextObject;\n this.minimapCtx.font = `${t.fontSize}px sans-serif`;\n this.minimapCtx.fillText(t.text, t.x, t.y);\n break;\n }\n case 'IMAGE': {\n const img = obj as ImageObject;\n if (img.imageElement) {\n this.minimapCtx.drawImage(img.imageElement, img.x, img.y, img.width, img.height);\n }\n break;\n }\n }\n });\n\n this.minimapCtx.restore();\n\n // 绘制画布边框\n this.minimapCtx.strokeStyle = '#94a3b8';\n this.minimapCtx.lineWidth = 1;\n this.minimapCtx.strokeRect(offsetX, offsetY, canvasW, canvasH);\n }\n\n // 小地图点击定位\n private handleMinimapClick(e: MouseEvent): void {\n const rect = this.minimapCanvas.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const clickY = e.clientY - rect.top;\n\n const scaleX = this.minimapCanvas.width / this.canvas.width;\n const scaleY = this.minimapCanvas.height / this.canvas.height;\n const minimapScale = Math.min(scaleX, scaleY) * 0.92;\n\n const canvasW = this.canvas.width * minimapScale;\n const canvasH = this.canvas.height * minimapScale;\n const offsetX = (this.minimapCanvas.width - canvasW) / 2;\n const offsetY = (this.minimapCanvas.height - canvasH) / 2;\n\n const relX = clickX - offsetX;\n const relY = clickY - offsetY;\n\n const canvasX = (relX / minimapScale - this.panOffset.x) / this.scale;\n const canvasY = (relY / minimapScale - this.panOffset.y) / this.scale;\n\n const viewportCenterX = this.canvas.width / 2;\n const viewportCenterY = this.canvas.height / 2;\n\n this.panOffset = {\n x: viewportCenterX / this.scale - canvasX,\n y: viewportCenterY / this.scale - canvasY\n };\n\n this.renderCanvas();\n this.renderMinimap();\n }\n\n // 图片上传处理\n private handleImageUpload(e: Event): void {\n const input = e.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) return;\n\n const file = input.files[0];\n const reader = new FileReader();\n\n reader.onload = (event) => {\n const dataUrl = event.target?.result as string;\n const img = new Image();\n img.onload = () => {\n this.saveHistory();\n const maxSize = 300;\n let width = img.width;\n let height = img.height;\n if (width > maxSize || height > maxSize) {\n const ratio = Math.min(maxSize / width, maxSize / height);\n width *= ratio;\n height *= ratio;\n }\n\n const newObj: ImageObject = {\n id: this.generateId(),\n type: 'IMAGE',\n x: 100,\n y: 100,\n width,\n height,\n color: '#000000',\n lineWidth: 1,\n dataUrl,\n imageElement: img\n };\n this.objects.push(newObj);\n this.selectedId = newObj.id;\n this.setTool('SELECT');\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n };\n img.src = dataUrl;\n };\n\n reader.readAsDataURL(file);\n input.value = '';\n }\n\n // 保存 JSON\n private saveJson(): void {\n const data = {\n version: '1.0',\n objects: this.objects.map(obj => {\n const { imageElement, ...rest } = obj as ImageObject;\n return rest;\n })\n };\n const json = JSON.stringify(data, null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'canvas-project.json';\n a.click();\n URL.revokeObjectURL(url);\n }\n\n // 加载 JSON\n private loadJson(e: Event): void {\n const input = e.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) return;\n\n const file = input.files[0];\n const reader = new FileReader();\n\n reader.onload = (event) => {\n try {\n const data = JSON.parse(event.target?.result as string);\n if (data.objects && Array.isArray(data.objects)) {\n this.saveHistory();\n this.objects = data.objects;\n this.selectedId = null;\n\n // 重新加载图片\n this.objects.forEach(obj => {\n if (obj.type === 'IMAGE' && (obj as ImageObject).dataUrl) {\n const img = new Image();\n img.onload = () => {\n (obj as ImageObject).imageElement = img;\n this.renderCanvas();\n this.renderMinimap();\n };\n img.src = (obj as ImageObject).dataUrl;\n }\n });\n\n this.renderCanvas();\n this.renderMinimap();\n this.updateUI();\n this.dispatchChangeEvent();\n }\n } catch (err) {\n console.error('Failed to load JSON:', err);\n }\n };\n\n reader.readAsText(file);\n input.value = '';\n }\n\n // 导出 PNG\n private exportPng(): void {\n // 创建临时画布\n const tempCanvas = document.createElement('canvas');\n tempCanvas.width = this.canvas.width;\n tempCanvas.height = this.canvas.height;\n const tempCtx = tempCanvas.getContext('2d')!;\n\n // 绘制白色背景\n tempCtx.fillStyle = '#ffffff';\n tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);\n\n // 应用缩放和平移\n tempCtx.translate(this.panOffset.x, this.panOffset.y);\n tempCtx.scale(this.scale, this.scale);\n\n // 绘制所有对象\n this.objects.forEach(obj => this.drawObject(tempCtx, obj, true));\n\n // 下载\n const url = tempCanvas.toDataURL('image/png');\n const a = document.createElement('a');\n a.href = url;\n a.download = 'canvas-export.png';\n a.click();\n }\n\n // 更新 UI\n private updateUI(): void {\n // 更新选中状态显示\n const selectionInfo = this.shadow.querySelector('.selection-info');\n if (selectionInfo) {\n if (this.selectedId) {\n const selectedObj = this.objects.find(o => o.id === this.selectedId);\n if (selectedObj) {\n const typeLabels: Record<string, string> = {\n 'RECTANGLE': '矩形',\n 'CIRCLE': '圆形',\n 'PATH': '画笔',\n 'TEXT': '文本',\n 'IMAGE': '图片'\n };\n const typeLabel = typeLabels[selectedObj.type] || selectedObj.type;\n selectionInfo.innerHTML = `\n <span class=\"selection-label\">已选择: ${typeLabel}</span>\n <button class=\"delete-btn\" title=\"删除\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\"/>\n </svg>\n </button>\n `;\n selectionInfo.classList.add('visible');\n const deleteBtn = selectionInfo.querySelector('.delete-btn');\n if (deleteBtn) {\n deleteBtn.addEventListener('click', () => this.deleteSelected());\n }\n }\n } else {\n selectionInfo.classList.remove('visible');\n selectionInfo.innerHTML = '';\n }\n }\n\n // 更新撤销按钮状态\n const undoBtn = this.shadow.querySelector('.undo-btn') as HTMLButtonElement;\n if (undoBtn) {\n undoBtn.disabled = this.history.length === 0;\n }\n\n // 更新空画布提示显示\n const emptyHint = this.shadow.querySelector('.empty-hint') as HTMLElement;\n if (emptyHint) {\n emptyHint.style.display = this.objects.length === 0 ? 'flex' : 'none';\n }\n }\n\n // 渲染 DOM 结构\n private render(): void {\n this.shadow.innerHTML = `\n <style>${this.getStyles()}</style>\n <div class=\"editor-container\">\n <!-- 左侧工具栏 -->\n <div class=\"toolbar\">\n ${this.createToolButton('SELECT', 'select-icon', '选择 (V)')}\n <div class=\"divider\"></div>\n ${this.config.showPencil ? this.createToolButton('PENCIL', 'pencil-icon', '画笔 (P)') : ''}\n ${this.config.showRectangle ? this.createToolButton('RECTANGLE', 'rect-icon', '矩形 (R)') : ''}\n ${this.config.showCircle ? this.createToolButton('CIRCLE', 'circle-icon', '圆形 (O)') : ''}\n ${this.config.showText ? this.createToolButton('TEXT', 'text-icon', '文本 (T)') : ''}\n ${this.config.showImage ? `\n <label class=\"tool-btn\" title=\"插入图片\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/>\n <path d=\"M21 15l-5-5L5 21\"/>\n </svg>\n <input type=\"file\" accept=\"image/*\" class=\"hidden image-input\" />\n </label>\n ` : ''}\n <div class=\"divider\"></div>\n <button class=\"tool-btn undo-btn\" title=\"撤销 (Ctrl+Z)\" disabled>\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M1 4v6h6\"/>\n <path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/>\n </svg>\n </button>\n <div class=\"spacer\"></div>\n ${this.config.showColor ? `\n <input type=\"color\" class=\"color-picker\" value=\"${this.color}\" title=\"颜色\" />\n ` : ''}\n </div>\n\n <!-- 主区域 -->\n <div class=\"main-area\">\n <!-- 顶部栏 -->\n <div class=\"top-bar\">\n <div class=\"top-bar-left\">\n <h2 class=\"title\">${this.config.title}</h2>\n <div class=\"selection-info\"></div>\n </div>\n <div class=\"top-bar-right\">\n ${this.config.showZoom ? `\n <div class=\"zoom-controls\">\n <button class=\"zoom-btn zoom-out-btn\" title=\"缩小\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"M21 21l-4.35-4.35M8 11h6\"/>\n </svg>\n </button>\n <button class=\"zoom-text\" title=\"重置缩放\">100%</button>\n <button class=\"zoom-btn zoom-in-btn\" title=\"放大\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"M21 21l-4.35-4.35M11 8v6M8 11h6\"/>\n </svg>\n </button>\n </div>\n ` : ''}\n ${(this.config.showExport || this.config.showImport || this.config.showDownload) ? `\n <div class=\"file-controls\">\n ${this.config.showExport ? `\n <button class=\"file-btn save-json-btn\" title=\"保存项目 (JSON)\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M19 21H5a2 2 0 01-2-2V5a2 2 0 012-2h11l5 5v11a2 2 0 01-2 2z\"/>\n <polyline points=\"17 21 17 13 7 13 7 21\"/><polyline points=\"7 3 7 8 15 8\"/>\n </svg>\n </button>\n ` : ''}\n ${this.config.showImport ? `\n <label class=\"file-btn\" title=\"加载项目 (JSON)\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z\"/>\n </svg>\n <input type=\"file\" accept=\".json\" class=\"hidden load-json-input\" />\n </label>\n ` : ''}\n ${this.config.showDownload ? `\n <button class=\"file-btn export-png-btn\" title=\"导出 PNG\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3\"/>\n </svg>\n </button>\n ` : ''}\n </div>\n ` : ''}\n </div>\n </div>\n\n <!-- 画布容器 -->\n <div class=\"canvas-container\">\n <canvas class=\"main-canvas\"></canvas>\n\n ${this.config.showMinimap ? `\n <div class=\"minimap-wrapper\">\n <div class=\"minimap-header\">\n <svg class=\"minimap-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <path d=\"M3 9h18M9 21V9\"/>\n </svg>\n <span>导航</span>\n </div>\n <canvas class=\"minimap-canvas\" width=\"220\" height=\"140\"></canvas>\n </div>\n ` : ''}\n\n <!-- 文本输入 -->\n <div class=\"text-input-container\" style=\"display: none;\">\n <input type=\"text\" class=\"text-input\" placeholder=\"输入文本...\" />\n </div>\n\n <!-- 空画布提示 -->\n <div class=\"empty-hint\">\n <h3>开始创作</h3>\n <p>选择左侧的工具开始绘制</p>\n </div>\n </div>\n </div>\n </div>\n `;\n\n // 获取 DOM 引用\n this.container = this.shadow.querySelector('.editor-container')!;\n this.toolbar = this.shadow.querySelector('.toolbar')!;\n this.topBar = this.shadow.querySelector('.top-bar')!;\n this.canvasContainer = this.shadow.querySelector('.canvas-container')!;\n this.canvas = this.shadow.querySelector('.main-canvas')!;\n this.ctx = this.canvas.getContext('2d')!;\n\n if (this.config.showMinimap) {\n this.minimapCanvas = this.shadow.querySelector('.minimap-canvas')!;\n this.minimapCtx = this.minimapCanvas.getContext('2d')!;\n }\n\n this.textInputContainer = this.shadow.querySelector('.text-input-container')!;\n this.textInput = this.shadow.querySelector('.text-input')!;\n\n // 绑定事件\n this.bindEvents();\n }\n\n // 绑定事件\n private bindEvents(): void {\n // 画布事件\n this.canvas.addEventListener('mousedown', (e) => this.handleCanvasPointerDown(e));\n this.canvas.addEventListener('mousemove', (e) => this.handleCanvasPointerMove(e));\n this.canvas.addEventListener('mouseup', () => this.handleCanvasPointerUp());\n this.canvas.addEventListener('mouseleave', () => this.handleCanvasPointerUp());\n this.canvas.addEventListener('dblclick', (e) => this.handleCanvasDoubleClick(e));\n this.canvas.addEventListener('touchstart', (e) => this.handleCanvasPointerDown(e));\n this.canvas.addEventListener('touchmove', (e) => this.handleCanvasPointerMove(e));\n this.canvas.addEventListener('touchend', () => this.handleCanvasPointerUp());\n this.canvas.addEventListener('wheel', this.boundHandleWheel, { passive: false });\n\n // 工具按钮\n this.shadow.querySelectorAll('.tool-btn[data-tool]').forEach(btn => {\n btn.addEventListener('mousedown', (e) => {\n // 阻止 blur 事件触发,在点击后手动处理\n e.preventDefault();\n });\n btn.addEventListener('click', () => {\n // 如果有文本输入,先提交\n if (this.isTextInputVisible) {\n this.submitText();\n }\n const tool = btn.getAttribute('data-tool') as ToolType;\n this.setTool(tool);\n });\n });\n\n // 撤销按钮\n const undoBtn = this.shadow.querySelector('.undo-btn');\n if (undoBtn) {\n undoBtn.addEventListener('click', () => this.undo());\n }\n\n // 颜色选择器\n const colorPicker = this.shadow.querySelector('.color-picker') as HTMLInputElement;\n if (colorPicker) {\n colorPicker.addEventListener('input', (e) => {\n this.color = (e.target as HTMLInputElement).value;\n });\n }\n\n // 图片上传\n const imageInput = this.shadow.querySelector('.image-input');\n if (imageInput) {\n imageInput.addEventListener('change', (e) => this.handleImageUpload(e));\n }\n\n // 缩放按钮\n const zoomInBtn = this.shadow.querySelector('.zoom-in-btn');\n const zoomOutBtn = this.shadow.querySelector('.zoom-out-btn');\n const zoomText = this.shadow.querySelector('.zoom-text');\n if (zoomInBtn) zoomInBtn.addEventListener('click', () => this.zoomIn());\n if (zoomOutBtn) zoomOutBtn.addEventListener('click', () => this.zoomOut());\n if (zoomText) zoomText.addEventListener('click', () => this.resetZoom());\n\n // 文件操作\n const saveJsonBtn = this.shadow.querySelector('.save-json-btn');\n const loadJsonInput = this.shadow.querySelector('.load-json-input');\n const exportPngBtn = this.shadow.querySelector('.export-png-btn');\n if (saveJsonBtn) saveJsonBtn.addEventListener('click', () => this.saveJson());\n if (loadJsonInput) loadJsonInput.addEventListener('change', (e) => this.loadJson(e));\n if (exportPngBtn) exportPngBtn.addEventListener('click', () => this.exportPng());\n\n // 小地图点击\n if (this.minimapCanvas) {\n this.minimapCanvas.addEventListener('click', (e) => this.handleMinimapClick(e));\n }\n\n // 文本输入\n if (this.textInput) {\n this.textInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.submitText();\n } else if (e.key === 'Escape') {\n this.hideTextInput();\n }\n });\n this.textInput.addEventListener('blur', () => {\n if (this.isTextInputVisible) {\n this.submitText();\n }\n });\n }\n }\n\n // 创建工具按钮 HTML\n private createToolButton(tool: ToolType, iconClass: string, title: string): string {\n const icons: Record<string, string> = {\n 'select-icon': '<path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/>',\n 'pencil-icon': '<path d=\"M17 3a2.85 2.85 0 114 4L7.5 20.5 2 22l1.5-5.5L17 3z\"/>',\n 'rect-icon': '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>',\n 'circle-icon': '<circle cx=\"12\" cy=\"12\" r=\"10\"/>',\n 'text-icon': '<path d=\"M4 7V4h16v3M9 20h6M12 4v16\"/>',\n };\n const isActive = this.tool === tool;\n return `\n <button class=\"tool-btn ${isActive ? 'active' : ''}\" data-tool=\"${tool}\" title=\"${title}\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n ${icons[iconClass]}\n </svg>\n </button>\n `;\n }\n\n // 获取样式\n private getStyles(): string {\n return `\n :host {\n display: block;\n width: 100%;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n .hidden {\n display: none !important;\n }\n\n .editor-container {\n display: flex;\n width: 100%;\n height: 100%;\n background: #f1f5f9;\n }\n\n /* 工具栏 */\n .toolbar {\n width: 64px;\n background: #ffffff;\n border-right: 1px solid #e2e8f0;\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 12px 8px;\n gap: 4px;\n }\n\n .tool-btn {\n width: 44px;\n height: 44px;\n border: none;\n background: transparent;\n border-radius: 12px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #64748b;\n transition: all 0.2s;\n }\n\n .tool-btn:hover {\n background: #f1f5f9;\n color: #4f46e5;\n }\n\n .tool-btn.active {\n background: #4f46e5;\n color: #ffffff;\n box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3);\n transform: scale(1.05);\n }\n\n .tool-btn:disabled {\n color: #cbd5e1;\n cursor: not-allowed;\n }\n\n .tool-btn:disabled:hover {\n background: transparent;\n color: #cbd5e1;\n }\n\n .icon {\n width: 20px;\n height: 20px;\n }\n\n .divider {\n width: 32px;\n height: 1px;\n background: #e2e8f0;\n margin: 8px 0;\n }\n\n .spacer {\n flex: 1;\n }\n\n .color-picker {\n width: 32px;\n height: 32px;\n border: 2px solid #e2e8f0;\n border-radius: 50%;\n cursor: pointer;\n padding: 0;\n overflow: hidden;\n -webkit-appearance: none;\n }\n\n .color-picker::-webkit-color-swatch-wrapper {\n padding: 0;\n }\n\n .color-picker::-webkit-color-swatch {\n border: none;\n border-radius: 50%;\n }\n\n /* 主区域 */\n .main-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* 顶部栏 */\n .top-bar {\n height: 56px;\n background: #ffffff;\n border-bottom: 1px solid #e2e8f0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 16px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n }\n\n .top-bar-left, .top-bar-right {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .title {\n font-size: 16px;\n font-weight: 600;\n color: #334155;\n }\n\n .selection-info {\n display: none;\n align-items: center;\n gap: 8px;\n background: #eef2ff;\n padding: 4px 12px;\n border-radius: 20px;\n border: 1px solid #c7d2fe;\n }\n\n .selection-info.visible {\n display: flex;\n }\n\n .selection-label {\n font-size: 12px;\n font-weight: 600;\n color: #4f46e5;\n text-transform: uppercase;\n }\n\n .delete-btn {\n background: none;\n border: none;\n color: #ef4444;\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .delete-btn:hover {\n color: #dc2626;\n }\n\n .zoom-controls, .file-controls {\n display: flex;\n align-items: center;\n background: #f1f5f9;\n border-radius: 8px;\n padding: 4px;\n }\n\n .zoom-btn, .file-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #475569;\n transition: all 0.2s;\n }\n\n .zoom-btn:hover, .file-btn:hover {\n color: #4f46e5;\n }\n\n .zoom-text {\n padding: 4px 8px;\n font-size: 12px;\n font-weight: 500;\n color: #475569;\n background: transparent;\n border: none;\n cursor: pointer;\n min-width: 50px;\n text-align: center;\n }\n\n .zoom-text:hover {\n color: #4f46e5;\n }\n\n /* 画布容器 */\n .canvas-container {\n flex: 1;\n position: relative;\n background: #f1f5f9;\n overflow: hidden;\n }\n\n .main-canvas {\n position: absolute;\n inset: 0;\n display: block;\n cursor: crosshair;\n touch-action: none;\n }\n\n /* 小地图 */\n .minimap-wrapper {\n position: absolute;\n top: 16px;\n right: 16px;\n z-index: 30;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n padding: 2px;\n }\n\n .minimap-wrapper > * {\n background: #ffffff;\n }\n\n .minimap-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: linear-gradient(to right, #f8fafc, #f1f5f9);\n border-bottom: 1px solid #e2e8f0;\n font-size: 12px;\n font-weight: 600;\n color: #475569;\n border-radius: 10px 10px 0 0;\n }\n\n .minimap-icon {\n width: 12px;\n height: 12px;\n color: #4f46e5;\n }\n\n .minimap-canvas {\n cursor: pointer;\n background: #f8fafc;\n border-radius: 0 0 10px 10px;\n display: block;\n }\n\n .minimap-canvas:hover {\n filter: brightness(1.05);\n }\n\n /* 文本输入 */\n .text-input-container {\n position: absolute;\n z-index: 20;\n }\n\n .text-input {\n padding: 8px 12px;\n border: 2px solid #4f46e5;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n outline: none;\n min-width: 200px;\n font-size: 16px;\n }\n\n /* 空画布提示 */\n .empty-hint {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n opacity: 0.4;\n }\n\n .empty-hint h3 {\n font-size: 24px;\n font-weight: 700;\n color: #94a3b8;\n margin-bottom: 8px;\n }\n\n .empty-hint p {\n color: #94a3b8;\n }\n `;\n }\n}\n\n// 注册 Web Component\nif (typeof window !== 'undefined' && !customElements.get('canvas-drawing-editor')) {\n customElements.define('canvas-drawing-editor', CanvasDrawingEditor);\n}\n"],"names":["defaultConfig","CanvasDrawingEditor","name","oldValue","newValue","e","rect","clientX","clientY","x","y","obj","r","c","t","width","p","minX","pt","maxX","minY","maxY","bounds","handleSize","handles","handle","img","previousState","o","selectedObj","newObj","mouseX","mouseY","delta","newScale","centerX","centerY","clampedScale","mouseXBeforeZoom","mouseYBeforeZoom","newPanOffsetX","newPanOffsetY","zoomText","tool","btn","screenX","screenY","text","_a","_b","value","existingObj","screenPos","clickedObject","id","dx","dy","newX","newY","newWidth","newHeight","radius","origT","scaleFactor","origP","scaleX","scaleY","textObj","ctx","isMinimap","i","imgObj","corner","minimap","mainCanvas","minimapScale","canvasW","canvasH","offsetX","offsetY","clickX","clickY","relX","relY","canvasX","canvasY","viewportCenterX","viewportCenterY","input","file","reader","event","dataUrl","maxSize","height","ratio","data","imageElement","rest","json","blob","url","a","err","tempCanvas","tempCtx","selectionInfo","typeLabel","deleteBtn","undoBtn","emptyHint","colorPicker","imageInput","zoomInBtn","zoomOutBtn","saveJsonBtn","loadJsonInput","exportPngBtn","iconClass","title","icons"],"mappings":"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"}
|