canvas-drawing-editor 2.0.7 → 2.0.9

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.
@@ -9,10 +9,9 @@ const f = {
9
9
  showDownload: !0,
10
10
  showExport: !0,
11
11
  showImport: !0,
12
- showColor: !0,
13
- showMinimap: !0
12
+ showColor: !0
14
13
  };
15
- class b extends HTMLElement {
14
+ class g extends HTMLElement {
16
15
  constructor() {
17
16
  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
17
  }
@@ -30,7 +29,6 @@ class b extends HTMLElement {
30
29
  "show-export",
31
30
  "show-import",
32
31
  "show-color",
33
- "show-minimap",
34
32
  "initial-data"
35
33
  ];
36
34
  }
@@ -43,10 +41,10 @@ class b extends HTMLElement {
43
41
  this.removeEventListeners();
44
42
  }
45
43
  // 生命周期:属性变化
46
- attributeChangedCallback(t, i, s) {
47
- if (i !== s) {
48
- if (t === "initial-data" && s && this.canvas) {
49
- this.loadInitialData(), this.renderCanvas(), this.renderMinimap();
44
+ attributeChangedCallback(t, s, i) {
45
+ if (s !== i) {
46
+ if (t === "initial-data" && i && this.canvas) {
47
+ this.loadInitialData(), this.renderCanvas();
50
48
  return;
51
49
  }
52
50
  this.parseAttributes(), this.container && this.updateUI();
@@ -65,8 +63,7 @@ class b extends HTMLElement {
65
63
  showDownload: this.getAttribute("show-download") !== "false",
66
64
  showExport: this.getAttribute("show-export") !== "false",
67
65
  showImport: this.getAttribute("show-import") !== "false",
68
- showColor: this.getAttribute("show-color") !== "false",
69
- showMinimap: this.getAttribute("show-minimap") !== "false"
66
+ showColor: this.getAttribute("show-color") !== "false"
70
67
  };
71
68
  }
72
69
  // 生成唯一 ID
@@ -78,17 +75,17 @@ class b extends HTMLElement {
78
75
  const t = this.getAttribute("initial-data");
79
76
  if (t)
80
77
  try {
81
- const i = JSON.parse(t);
82
- i.objects && Array.isArray(i.objects) && (this.objects = i.objects, this.selectedId = null, this.objects.forEach((s) => {
83
- if (s.type === "IMAGE" && s.dataUrl) {
78
+ const s = JSON.parse(t);
79
+ s.objects && Array.isArray(s.objects) && (this.objects = s.objects, this.selectedId = null, this.scale = 1, this.panOffset = { x: 0, y: 0 }, this.updateZoomDisplay(), this.objects.forEach((i) => {
80
+ if (i.type === "IMAGE" && i.dataUrl) {
84
81
  const e = new Image();
85
82
  e.onload = () => {
86
- s.imageElement = e, this.renderCanvas(), this.renderMinimap();
87
- }, e.src = s.dataUrl;
83
+ i.imageElement = e, this.renderCanvas();
84
+ }, e.src = i.dataUrl;
88
85
  }
89
86
  }), this.updateUI());
90
- } catch (i) {
91
- console.error("Failed to parse initial-data:", i);
87
+ } catch (s) {
88
+ console.error("Failed to parse initial-data:", s);
92
89
  }
93
90
  }
94
91
  // 设置事件监听
@@ -106,96 +103,96 @@ class b extends HTMLElement {
106
103
  // 初始化画布
107
104
  initCanvas(t = !1) {
108
105
  !this.canvasContainer || !this.canvas || requestAnimationFrame(() => {
109
- this.canvas.width = this.canvasContainer.clientWidth, this.canvas.height = this.canvasContainer.clientHeight, t && this.loadInitialData(), this.renderCanvas(), this.renderMinimap();
106
+ this.canvas.width = this.canvasContainer.clientWidth, this.canvas.height = this.canvasContainer.clientHeight, t && this.loadInitialData(), this.renderCanvas();
110
107
  });
111
108
  }
112
109
  // 获取鼠标在画布上的位置(考虑缩放和平移)
113
110
  getMousePos(t) {
114
- const i = this.canvas.getBoundingClientRect();
115
- let s, e;
111
+ const s = this.canvas.getBoundingClientRect();
112
+ let i, e;
116
113
  if ("touches" in t && t.touches.length > 0)
117
- s = t.touches[0].clientX, e = t.touches[0].clientY;
114
+ i = t.touches[0].clientX, e = t.touches[0].clientY;
118
115
  else if ("clientX" in t)
119
- s = t.clientX, e = t.clientY;
116
+ i = t.clientX, e = t.clientY;
120
117
  else
121
118
  return { x: 0, y: 0 };
122
- const n = (s - i.left - this.panOffset.x) / this.scale, o = (e - i.top - this.panOffset.y) / this.scale;
123
- return { x: n, y: o };
119
+ const n = (i - s.left - this.panOffset.x) / this.scale, a = (e - s.top - this.panOffset.y) / this.scale;
120
+ return { x: n, y: a };
124
121
  }
125
122
  // 获取屏幕坐标(不考虑缩放和平移)
126
123
  getScreenPos(t) {
127
- const i = this.canvas.getBoundingClientRect();
128
- let s, e;
124
+ const s = this.canvas.getBoundingClientRect();
125
+ let i, e;
129
126
  if ("touches" in t && t.touches.length > 0)
130
- s = t.touches[0].clientX, e = t.touches[0].clientY;
127
+ i = t.touches[0].clientX, e = t.touches[0].clientY;
131
128
  else if ("clientX" in t)
132
- s = t.clientX, e = t.clientY;
129
+ i = t.clientX, e = t.clientY;
133
130
  else
134
131
  return { x: 0, y: 0 };
135
- return { x: s - i.left, y: e - i.top };
132
+ return { x: i - s.left, y: e - s.top };
136
133
  }
137
134
  // 获取对象边界
138
135
  getObjectBounds(t) {
139
136
  switch (t.type) {
140
137
  case "RECTANGLE":
141
138
  case "IMAGE": {
142
- const i = t;
143
- return { x: i.x, y: i.y, width: i.width, height: i.height };
139
+ const s = t;
140
+ return { x: s.x, y: s.y, width: s.width, height: s.height };
144
141
  }
145
142
  case "CIRCLE": {
146
- const i = t;
147
- return { x: i.x - i.radius, y: i.y - i.radius, width: i.radius * 2, height: i.radius * 2 };
143
+ const s = t;
144
+ return { x: s.x - s.radius, y: s.y - s.radius, width: s.radius * 2, height: s.radius * 2 };
148
145
  }
149
146
  case "TEXT": {
150
- const i = t, s = i.text.length * i.fontSize * 0.6;
151
- return { x: i.x, y: i.y - i.fontSize, width: s, height: i.fontSize };
147
+ const s = t, i = s.text.length * s.fontSize * 0.6;
148
+ return { x: s.x, y: s.y - s.fontSize, width: i, height: s.fontSize };
152
149
  }
153
150
  case "PATH": {
154
- const i = t;
155
- if (i.points.length === 0) return { x: 0, y: 0, width: 0, height: 0 };
156
- const s = Math.min(...i.points.map((a) => a.x)), e = Math.max(...i.points.map((a) => a.x)), n = Math.min(...i.points.map((a) => a.y)), o = Math.max(...i.points.map((a) => a.y));
157
- return { x: s, y: n, width: e - s, height: o - n };
151
+ const s = t;
152
+ if (s.points.length === 0) return { x: 0, y: 0, width: 0, height: 0 };
153
+ const i = Math.min(...s.points.map((o) => o.x)), e = Math.max(...s.points.map((o) => o.x)), n = Math.min(...s.points.map((o) => o.y)), a = Math.max(...s.points.map((o) => o.y));
154
+ return { x: i, y: n, width: e - i, height: a - n };
158
155
  }
159
156
  }
160
157
  return { x: 0, y: 0, width: 0, height: 0 };
161
158
  }
162
159
  // 检查调整大小手柄
163
- getResizeHandleAtPoint(t, i, s) {
164
- const e = this.getObjectBounds(t), n = 8, o = [
160
+ getResizeHandleAtPoint(t, s, i) {
161
+ const e = this.getObjectBounds(t), n = 8, a = [
165
162
  { name: "nw", x: e.x, y: e.y },
166
163
  { name: "ne", x: e.x + e.width, y: e.y },
167
164
  { name: "sw", x: e.x, y: e.y + e.height },
168
165
  { name: "se", x: e.x + e.width, y: e.y + e.height }
169
166
  ];
170
- for (const a of o)
171
- if (Math.abs(i - a.x) <= n && Math.abs(s - a.y) <= n)
172
- return a.name;
167
+ for (const o of a)
168
+ if (Math.abs(s - o.x) <= n && Math.abs(i - o.y) <= n)
169
+ return o.name;
173
170
  return null;
174
171
  }
175
172
  // 碰撞检测
176
- isHit(t, i, s) {
173
+ isHit(t, s, i) {
177
174
  switch (t.type) {
178
175
  case "RECTANGLE": {
179
176
  const e = t;
180
- return i >= e.x && i <= e.x + e.width && s >= e.y && s <= e.y + e.height;
177
+ return s >= e.x && s <= e.x + e.width && i >= e.y && i <= e.y + e.height;
181
178
  }
182
179
  case "CIRCLE": {
183
180
  const e = t;
184
- return Math.sqrt(Math.pow(i - e.x, 2) + Math.pow(s - e.y, 2)) <= e.radius;
181
+ return Math.sqrt(Math.pow(s - e.x, 2) + Math.pow(i - e.y, 2)) <= e.radius;
185
182
  }
186
183
  case "IMAGE": {
187
184
  const e = t;
188
- return i >= e.x && i <= e.x + e.width && s >= e.y && s <= e.y + e.height;
185
+ return s >= e.x && s <= e.x + e.width && i >= e.y && i <= e.y + e.height;
189
186
  }
190
187
  case "TEXT": {
191
188
  const e = t;
192
- return i >= e.x && i <= e.x + e.text.length * e.fontSize * 0.6 && s >= e.y - e.fontSize && s <= e.y;
189
+ return s >= e.x && s <= e.x + e.text.length * e.fontSize * 0.6 && i >= e.y - e.fontSize && i <= e.y;
193
190
  }
194
191
  case "PATH": {
195
192
  const e = t;
196
193
  if (e.points.length === 0) return !1;
197
- const n = Math.min(...e.points.map((r) => r.x)), o = Math.max(...e.points.map((r) => r.x)), a = Math.min(...e.points.map((r) => r.y)), l = Math.max(...e.points.map((r) => r.y));
198
- return i >= n && i <= o && s >= a && s <= l;
194
+ const n = Math.min(...e.points.map((h) => h.x)), a = Math.max(...e.points.map((h) => h.x)), o = Math.min(...e.points.map((h) => h.y)), l = Math.max(...e.points.map((h) => h.y));
195
+ return s >= n && s <= a && i >= o && i <= l;
199
196
  }
200
197
  }
201
198
  return !1;
@@ -208,16 +205,16 @@ class b extends HTMLElement {
208
205
  undo() {
209
206
  if (this.history.length === 0) return;
210
207
  const t = this.history.pop();
211
- t && (this.objects = t, this.selectedId = null, this.renderCanvas(), this.renderMinimap(), this.dispatchChangeEvent());
208
+ t && (this.objects = t, this.selectedId = null, this.renderCanvas(), this.dispatchChangeEvent());
212
209
  }
213
210
  // 删除选中对象
214
211
  deleteSelected() {
215
- this.selectedId && (this.saveHistory(), this.objects = this.objects.filter((t) => t.id !== this.selectedId), this.selectedId = null, this.renderCanvas(), this.renderMinimap(), this.updateUI(), this.dispatchChangeEvent());
212
+ this.selectedId && (this.saveHistory(), this.objects = this.objects.filter((t) => t.id !== this.selectedId), this.selectedId = null, this.renderCanvas(), this.updateUI(), this.dispatchChangeEvent());
216
213
  }
217
214
  // 复制选中对象
218
215
  copySelected() {
219
216
  if (this.selectedId) {
220
- const t = this.objects.find((i) => i.id === this.selectedId);
217
+ const t = this.objects.find((s) => s.id === this.selectedId);
221
218
  t && (this.clipboard = JSON.parse(JSON.stringify(t)));
222
219
  }
223
220
  }
@@ -231,10 +228,10 @@ class b extends HTMLElement {
231
228
  x: this.clipboard.x + 20,
232
229
  y: this.clipboard.y + 20
233
230
  };
234
- t.type === "PATH" && t.points && (t.points = t.points.map((i) => ({
235
- x: i.x + 20,
236
- y: i.y + 20
237
- }))), this.objects.push(t), this.selectedId = t.id, this.clipboard = t, this.renderCanvas(), this.renderMinimap(), this.updateUI(), this.dispatchChangeEvent();
231
+ t.type === "PATH" && t.points && (t.points = t.points.map((s) => ({
232
+ x: s.x + 20,
233
+ y: s.y + 20
234
+ }))), this.objects.push(t), this.selectedId = t.id, this.clipboard = t, this.renderCanvas(), this.updateUI(), this.dispatchChangeEvent();
238
235
  }
239
236
  }
240
237
  // 派发变化事件
@@ -291,27 +288,27 @@ class b extends HTMLElement {
291
288
  // 滚轮缩放
292
289
  handleWheel(t) {
293
290
  t.preventDefault();
294
- const i = this.canvas.getBoundingClientRect(), s = t.clientX - i.left, e = t.clientY - i.top, n = t.deltaY > 0 ? 0.9 : 1.1, o = this.scale * n;
295
- this.zoomAtPoint(o, s, e);
291
+ const s = this.canvas.getBoundingClientRect(), i = t.clientX - s.left, e = t.clientY - s.top, n = t.deltaY > 0 ? 0.9 : 1.1, a = this.scale * n;
292
+ this.zoomAtPoint(a, i, e);
296
293
  }
297
294
  // 以指定点为中心缩放
298
- zoomAtPoint(t, i, s) {
299
- const e = Math.min(Math.max(t, 0.2), 5), n = (i - this.panOffset.x) / this.scale, o = (s - this.panOffset.y) / this.scale, a = i - n * e, l = s - o * e;
300
- this.scale = e, this.panOffset = { x: a, y: l }, this.renderCanvas(), this.renderMinimap(), this.updateZoomDisplay();
295
+ zoomAtPoint(t, s, i) {
296
+ const e = Math.min(Math.max(t, 0.2), 5), n = (s - this.panOffset.x) / this.scale, a = (i - this.panOffset.y) / this.scale, o = s - n * e, l = i - a * e;
297
+ this.scale = e, this.panOffset = { x: o, y: l }, this.renderCanvas(), this.updateZoomDisplay();
301
298
  }
302
299
  // 放大
303
300
  zoomIn() {
304
- const t = this.canvas.width / 2, i = this.canvas.height / 2;
305
- this.zoomAtPoint(this.scale * 1.2, t, i);
301
+ const t = this.canvas.width / 2, s = this.canvas.height / 2;
302
+ this.zoomAtPoint(this.scale * 1.2, t, s);
306
303
  }
307
304
  // 缩小
308
305
  zoomOut() {
309
- const t = this.canvas.width / 2, i = this.canvas.height / 2;
310
- this.zoomAtPoint(this.scale / 1.2, t, i);
306
+ const t = this.canvas.width / 2, s = this.canvas.height / 2;
307
+ this.zoomAtPoint(this.scale / 1.2, t, s);
311
308
  }
312
309
  // 重置缩放
313
310
  resetZoom() {
314
- this.scale = 1, this.panOffset = { x: 0, y: 0 }, this.renderCanvas(), this.renderMinimap(), this.updateZoomDisplay();
311
+ this.scale = 1, this.panOffset = { x: 0, y: 0 }, this.renderCanvas(), this.updateZoomDisplay();
315
312
  }
316
313
  // 更新缩放显示
317
314
  updateZoomDisplay() {
@@ -324,8 +321,8 @@ class b extends HTMLElement {
324
321
  }
325
322
  // 更新工具按钮状态
326
323
  updateToolButtons() {
327
- this.shadow.querySelectorAll(".tool-btn").forEach((i) => {
328
- i.getAttribute("data-tool") === this.tool ? i.classList.add("active") : i.classList.remove("active");
324
+ this.shadow.querySelectorAll(".tool-btn").forEach((s) => {
325
+ s.getAttribute("data-tool") === this.tool ? s.classList.add("active") : s.classList.remove("active");
329
326
  });
330
327
  }
331
328
  // 隐藏文本输入
@@ -333,15 +330,15 @@ class b extends HTMLElement {
333
330
  this.isTextInputVisible = !1, this.textInputContainer && (this.textInputContainer.style.display = "none"), this.editingTextId = null;
334
331
  }
335
332
  // 显示文本输入
336
- showTextInput(t, i, s = "") {
337
- this.isTextInputVisible = !0, this.textInputScreenPos = { x: t, y: i }, this.textInputContainer && this.textInput && (this.textInputContainer.style.display = "block", this.textInputContainer.style.left = `${t}px`, this.textInputContainer.style.top = `${i - 30}px`, this.textInput.value = s, this.textInput.style.color = this.color, setTimeout(() => {
338
- this.textInput.focus(), s && this.textInput.select();
333
+ showTextInput(t, s, i = "") {
334
+ this.isTextInputVisible = !0, this.textInputScreenPos = { x: t, y: s }, this.textInputContainer && this.textInput && (this.textInputContainer.style.display = "block", this.textInputContainer.style.left = `${t}px`, this.textInputContainer.style.top = `${s - 30}px`, this.textInput.value = i, this.textInput.style.color = this.color, setTimeout(() => {
335
+ this.textInput.focus(), i && this.textInput.select();
339
336
  }, 0));
340
337
  }
341
338
  // 提交文本
342
339
  submitText() {
343
- var i, s;
344
- const t = (s = (i = this.textInput) == null ? void 0 : i.value) == null ? void 0 : s.trim();
340
+ var s, i;
341
+ const t = (i = (s = this.textInput) == null ? void 0 : s.value) == null ? void 0 : i.trim();
345
342
  if (t) {
346
343
  if (this.editingTextId) {
347
344
  const e = this.objects.find((n) => n.id === this.editingTextId);
@@ -362,289 +359,245 @@ class b extends HTMLElement {
362
359
  }
363
360
  this.dispatchChangeEvent();
364
361
  }
365
- this.hideTextInput(), this.setTool("SELECT"), this.renderCanvas(), this.renderMinimap(), this.updateUI();
362
+ this.hideTextInput(), this.setTool("SELECT"), this.renderCanvas(), this.updateUI();
366
363
  }
367
364
  // 画布鼠标按下
368
365
  handleCanvasPointerDown(t) {
369
- const { x: i, y: s } = this.getMousePos(t), e = this.getScreenPos(t);
370
- if (this.dragStart = { x: i, y: s }, this.isDragging = !0, this.isTextInputVisible && this.tool !== "TEXT" && this.submitText(), this.tool === "SELECT") {
366
+ const { x: s, y: i } = this.getMousePos(t), e = this.getScreenPos(t);
367
+ if (this.dragStart = { x: s, y: i }, this.isDragging = !0, this.isTextInputVisible && this.tool !== "TEXT" && this.submitText(), this.tool === "SELECT") {
371
368
  if (this.selectedId) {
372
- const o = this.objects.find((a) => a.id === this.selectedId);
373
- if (o) {
374
- const a = this.getResizeHandleAtPoint(o, i, s);
375
- if (a) {
376
- this.saveHistory(), this.isResizing = !0, this.resizeHandle = a, this.resizeStartBounds = this.getObjectBounds(o), this.resizeOriginalObject = JSON.parse(JSON.stringify(o));
369
+ const a = this.objects.find((o) => o.id === this.selectedId);
370
+ if (a) {
371
+ const o = this.getResizeHandleAtPoint(a, s, i);
372
+ if (o) {
373
+ this.saveHistory(), this.isResizing = !0, this.resizeHandle = o, this.resizeStartBounds = this.getObjectBounds(a), this.resizeOriginalObject = JSON.parse(JSON.stringify(a));
377
374
  return;
378
375
  }
379
376
  }
380
377
  }
381
- const n = [...this.objects].reverse().find((o) => this.isHit(o, i, s));
382
- n ? (this.selectedId = n.id, this.dragOffset = { x: i - n.x, y: s - n.y }, this.saveHistory(), this.updateUI()) : (this.selectedId = null, this.isPanning = !0, this.panStart = e, this.updateUI());
378
+ const n = [...this.objects].reverse().find((a) => this.isHit(a, s, i));
379
+ n ? (this.selectedId = n.id, this.dragOffset = { x: s - n.x, y: i - n.y }, this.saveHistory(), this.updateUI()) : (this.selectedId = null, this.isPanning = !0, this.panStart = e, this.updateUI());
383
380
  } else if (this.tool === "TEXT")
384
- this.textInputPos = { x: i, y: s }, this.showTextInput(e.x, e.y), this.isDragging = !1;
381
+ this.textInputPos = { x: s, y: i }, this.showTextInput(e.x, e.y), this.isDragging = !1;
385
382
  else {
386
383
  this.saveHistory();
387
384
  const n = this.generateId();
388
- this.tool === "RECTANGLE" ? this.currentObject = { id: n, type: "RECTANGLE", x: i, y: s, width: 0, height: 0, color: this.color, lineWidth: this.lineWidth } : this.tool === "CIRCLE" ? this.currentObject = { id: n, type: "CIRCLE", x: i, y: s, radius: 0, color: this.color, lineWidth: this.lineWidth } : this.tool === "PENCIL" && (this.currentObject = { id: n, type: "PATH", x: i, y: s, points: [{ x: i, y: s }], color: this.color, lineWidth: this.lineWidth });
385
+ this.tool === "RECTANGLE" ? this.currentObject = { id: n, type: "RECTANGLE", x: s, y: i, width: 0, height: 0, color: this.color, lineWidth: this.lineWidth } : this.tool === "CIRCLE" ? this.currentObject = { id: n, type: "CIRCLE", x: s, y: i, radius: 0, color: this.color, lineWidth: this.lineWidth } : this.tool === "PENCIL" && (this.currentObject = { id: n, type: "PATH", x: s, y: i, points: [{ x: s, y: i }], color: this.color, lineWidth: this.lineWidth });
389
386
  }
390
387
  this.renderCanvas();
391
388
  }
392
389
  // 画布鼠标移动
393
390
  handleCanvasPointerMove(t) {
394
391
  if (this.isPanning) {
395
- const e = this.getScreenPos(t), n = e.x - this.panStart.x, o = e.y - this.panStart.y;
396
- this.panOffset = { x: this.panOffset.x + n, y: this.panOffset.y + o }, this.panStart = e, this.renderCanvas(), this.renderMinimap();
392
+ const e = this.getScreenPos(t), n = e.x - this.panStart.x, a = e.y - this.panStart.y;
393
+ this.panOffset = { x: this.panOffset.x + n, y: this.panOffset.y + a }, this.panStart = e, this.renderCanvas();
397
394
  return;
398
395
  }
399
396
  if (!this.isDragging || !this.dragStart) return;
400
- const { x: i, y: s } = this.getMousePos(t);
397
+ const { x: s, y: i } = this.getMousePos(t);
401
398
  if (this.isResizing && this.selectedId && this.resizeHandle && this.resizeStartBounds && this.resizeOriginalObject) {
402
- const e = this.objects.find((d) => d.id === this.selectedId);
399
+ const e = this.objects.find((c) => c.id === this.selectedId);
403
400
  if (!e) return;
404
- const n = i - this.dragStart.x, o = s - this.dragStart.y;
405
- let a = this.resizeStartBounds.x, l = this.resizeStartBounds.y, r = this.resizeStartBounds.width, h = this.resizeStartBounds.height;
406
- switch (this.resizeHandle.includes("e") && (r = this.resizeStartBounds.width + n), this.resizeHandle.includes("w") && (a = this.resizeStartBounds.x + n, r = this.resizeStartBounds.width - n), this.resizeHandle.includes("s") && (h = this.resizeStartBounds.height + o), this.resizeHandle.includes("n") && (l = this.resizeStartBounds.y + o, h = this.resizeStartBounds.height - o), r = Math.max(10, r), h = Math.max(10, h), e.type) {
401
+ const n = s - this.dragStart.x, a = i - this.dragStart.y;
402
+ let o = this.resizeStartBounds.x, l = this.resizeStartBounds.y, h = this.resizeStartBounds.width, r = this.resizeStartBounds.height;
403
+ switch (this.resizeHandle.includes("e") && (h = this.resizeStartBounds.width + n), this.resizeHandle.includes("w") && (o = this.resizeStartBounds.x + n, h = this.resizeStartBounds.width - n), this.resizeHandle.includes("s") && (r = this.resizeStartBounds.height + a), this.resizeHandle.includes("n") && (l = this.resizeStartBounds.y + a, r = this.resizeStartBounds.height - a), h = Math.max(10, h), r = Math.max(10, r), e.type) {
407
404
  case "RECTANGLE":
408
405
  case "IMAGE":
409
- e.x = a, e.y = l, e.width = r, e.height = h;
406
+ e.x = o, e.y = l, e.width = h, e.height = r;
410
407
  break;
411
408
  case "CIRCLE": {
412
- const d = Math.max(r, h) / 2;
413
- e.x = a + d, e.y = l + d, e.radius = d;
409
+ const c = Math.max(h, r) / 2;
410
+ e.x = o + c, e.y = l + c, e.radius = c;
414
411
  break;
415
412
  }
416
413
  case "TEXT": {
417
- const d = this.resizeOriginalObject, c = r / this.resizeStartBounds.width;
418
- e.x = a, e.y = l + h, e.fontSize = Math.max(8, Math.round(d.fontSize * c));
414
+ const c = this.resizeOriginalObject, d = h / this.resizeStartBounds.width;
415
+ e.x = o, e.y = l + r, e.fontSize = Math.max(8, Math.round(c.fontSize * d));
419
416
  break;
420
417
  }
421
418
  case "PATH": {
422
- const d = this.resizeOriginalObject, c = r / this.resizeStartBounds.width, p = h / this.resizeStartBounds.height;
423
- e.points = d.points.map((u) => ({
424
- x: a + (u.x - this.resizeStartBounds.x) * c,
425
- y: l + (u.y - this.resizeStartBounds.y) * p
419
+ const c = this.resizeOriginalObject, d = h / this.resizeStartBounds.width, u = r / this.resizeStartBounds.height;
420
+ e.points = c.points.map((p) => ({
421
+ x: o + (p.x - this.resizeStartBounds.x) * d,
422
+ y: l + (p.y - this.resizeStartBounds.y) * u
426
423
  }));
427
424
  break;
428
425
  }
429
426
  }
430
- this.renderCanvas(), this.renderMinimap();
427
+ this.renderCanvas();
431
428
  return;
432
429
  }
433
430
  if (this.tool === "SELECT" && this.selectedId) {
434
431
  const e = this.objects.find((n) => n.id === this.selectedId);
435
432
  if (e) {
436
433
  if (e.type === "PATH") {
437
- const n = e, o = i - this.dragStart.x, a = s - this.dragStart.y;
438
- n.points = n.points.map((l) => ({ x: l.x + o, y: l.y + a })), this.dragStart = { x: i, y: s };
434
+ const n = e, a = s - this.dragStart.x, o = i - this.dragStart.y;
435
+ n.points = n.points.map((l) => ({ x: l.x + a, y: l.y + o })), this.dragStart = { x: s, y: i };
439
436
  } else
440
- e.x = i - this.dragOffset.x, e.y = s - this.dragOffset.y;
441
- this.renderCanvas(), this.renderMinimap();
437
+ e.x = s - this.dragOffset.x, e.y = i - this.dragOffset.y;
438
+ this.renderCanvas();
442
439
  }
443
440
  } else if (this.currentObject) {
444
441
  if (this.currentObject.type === "RECTANGLE")
445
- this.currentObject.width = i - this.currentObject.x, this.currentObject.height = s - this.currentObject.y;
442
+ this.currentObject.width = s - this.currentObject.x, this.currentObject.height = i - this.currentObject.y;
446
443
  else if (this.currentObject.type === "CIRCLE") {
447
- const e = Math.sqrt(Math.pow(i - this.currentObject.x, 2) + Math.pow(s - this.currentObject.y, 2));
444
+ const e = Math.sqrt(Math.pow(s - this.currentObject.x, 2) + Math.pow(i - this.currentObject.y, 2));
448
445
  this.currentObject.radius = e;
449
- } else this.currentObject.type === "PATH" && this.currentObject.points.push({ x: i, y: s });
446
+ } else this.currentObject.type === "PATH" && this.currentObject.points.push({ x: s, y: i });
450
447
  this.renderCanvas();
451
448
  }
452
449
  }
453
450
  // 画布鼠标抬起
454
451
  handleCanvasPointerUp() {
455
- 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();
452
+ 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.updateUI();
456
453
  }
457
454
  // 双击编辑文本
458
455
  handleCanvasDoubleClick(t) {
459
456
  t.preventDefault();
460
- const { x: i, y: s } = this.getMousePos(t), e = [...this.objects].reverse().find((n) => this.isHit(n, i, s));
457
+ const { x: s, y: i } = this.getMousePos(t), e = [...this.objects].reverse().find((n) => this.isHit(n, s, i));
461
458
  if (e && e.type === "TEXT") {
462
459
  const n = e;
463
460
  this.editingTextId = n.id, this.textInputPos = { x: n.x, y: n.y };
464
- const o = n.x * this.scale + this.panOffset.x, a = n.y * this.scale + this.panOffset.y;
465
- this.showTextInput(o, a, n.text), this.setTool("SELECT");
461
+ const a = n.x * this.scale + this.panOffset.x, o = n.y * this.scale + this.panOffset.y;
462
+ this.showTextInput(a, o, n.text), this.setTool("SELECT");
466
463
  }
467
464
  }
468
465
  // 渲染画布
469
466
  renderCanvas() {
470
467
  if (this.ctx) {
471
- if (this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height), this.ctx.fillStyle = "#ffffff", this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height), this.ctx.save(), this.ctx.translate(this.panOffset.x, this.panOffset.y), this.ctx.scale(this.scale, this.scale), this.objects.forEach((t) => this.drawObject(this.ctx, t, !1)), this.currentObject && this.drawObject(this.ctx, this.currentObject, !1), this.selectedId && this.tool === "SELECT") {
472
- const t = this.objects.find((i) => i.id === this.selectedId);
468
+ if (this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height), this.ctx.fillStyle = "#ffffff", this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height), this.ctx.save(), this.ctx.translate(this.panOffset.x, this.panOffset.y), this.ctx.scale(this.scale, this.scale), this.objects.forEach((t) => this.drawObject(this.ctx, t)), this.currentObject && this.drawObject(this.ctx, this.currentObject), this.selectedId && this.tool === "SELECT") {
469
+ const t = this.objects.find((s) => s.id === this.selectedId);
473
470
  t && this.drawSelectionHandles(this.ctx, t);
474
471
  }
475
472
  this.ctx.restore();
476
473
  }
477
474
  }
478
475
  // 绘制单个对象
479
- drawObject(t, i, s) {
480
- switch (t.beginPath(), t.strokeStyle = i.color, t.lineWidth = i.lineWidth, t.fillStyle = i.color, !s && i.id === this.selectedId ? (t.shadowColor = "rgba(0, 100, 255, 0.5)", t.shadowBlur = 10) : t.shadowBlur = 0, i.type) {
476
+ drawObject(t, s) {
477
+ switch (t.beginPath(), t.strokeStyle = s.color, t.lineWidth = s.lineWidth, t.fillStyle = s.color, s.id === this.selectedId ? (t.shadowColor = "rgba(0, 100, 255, 0.5)", t.shadowBlur = 10) : t.shadowBlur = 0, s.type) {
481
478
  case "RECTANGLE": {
482
- const e = i;
483
- t.strokeRect(e.x, e.y, e.width, e.height);
479
+ const i = s;
480
+ t.strokeRect(i.x, i.y, i.width, i.height);
484
481
  break;
485
482
  }
486
483
  case "CIRCLE": {
487
- const e = i;
488
- t.beginPath(), t.arc(e.x, e.y, e.radius, 0, 2 * Math.PI), t.stroke();
484
+ const i = s;
485
+ t.beginPath(), t.arc(i.x, i.y, i.radius, 0, 2 * Math.PI), t.stroke();
489
486
  break;
490
487
  }
491
488
  case "PATH": {
492
- const e = i;
493
- if (e.points.length < 2) break;
494
- t.beginPath(), t.lineCap = "round", t.lineJoin = "round", t.moveTo(e.points[0].x, e.points[0].y);
495
- for (let n = 1; n < e.points.length; n++)
496
- t.lineTo(e.points[n].x, e.points[n].y);
489
+ const i = s;
490
+ if (i.points.length < 2) break;
491
+ t.beginPath(), t.lineCap = "round", t.lineJoin = "round", t.moveTo(i.points[0].x, i.points[0].y);
492
+ for (let e = 1; e < i.points.length; e++)
493
+ t.lineTo(i.points[e].x, i.points[e].y);
497
494
  t.stroke();
498
495
  break;
499
496
  }
500
497
  case "TEXT": {
501
- const e = i;
502
- t.font = `${e.fontSize}px sans-serif`, t.fillText(e.text, e.x, e.y);
498
+ const i = s;
499
+ t.font = `${i.fontSize}px sans-serif`, t.fillText(i.text, i.x, i.y);
503
500
  break;
504
501
  }
505
502
  case "IMAGE": {
506
- const e = i;
507
- if (e.imageElement && e.imageElement.complete)
508
- t.drawImage(e.imageElement, e.x, e.y, e.width, e.height);
509
- else if (e.dataUrl) {
510
- const n = new Image();
511
- n.onload = () => {
512
- e.imageElement = n, this.renderCanvas();
513
- }, n.src = e.dataUrl;
503
+ const i = s;
504
+ if (i.imageElement && i.imageElement.complete)
505
+ t.drawImage(i.imageElement, i.x, i.y, i.width, i.height);
506
+ else if (i.dataUrl) {
507
+ const e = new Image();
508
+ e.onload = () => {
509
+ i.imageElement = e, this.renderCanvas();
510
+ }, e.src = i.dataUrl;
514
511
  }
515
512
  break;
516
513
  }
517
514
  }
518
515
  }
519
516
  // 绘制选中手柄
520
- drawSelectionHandles(t, i) {
521
- const s = this.getObjectBounds(i), e = 8;
517
+ drawSelectionHandles(t, s) {
518
+ const i = this.getObjectBounds(s), e = 8;
522
519
  t.shadowBlur = 0, t.fillStyle = "#3b82f6", t.strokeStyle = "#ffffff", t.lineWidth = 2, [
523
- { x: s.x, y: s.y },
524
- { x: s.x + s.width, y: s.y },
525
- { x: s.x, y: s.y + s.height },
526
- { x: s.x + s.width, y: s.y + s.height }
527
- ].forEach((o) => {
528
- t.beginPath(), t.rect(o.x - e / 2, o.y - e / 2, e, e), t.fill(), t.stroke();
529
- }), t.strokeStyle = "#3b82f6", t.lineWidth = 1, t.setLineDash([5, 5]), t.strokeRect(s.x, s.y, s.width, s.height), t.setLineDash([]);
530
- }
531
- // 渲染小地图
532
- renderMinimap() {
533
- if (!this.minimapCtx || !this.config.showMinimap) return;
534
- const t = this.minimapCanvas, i = this.canvas;
535
- this.minimapCtx.clearRect(0, 0, t.width, t.height);
536
- const s = t.width / i.width, e = t.height / i.height, n = Math.min(s, e) * 0.92, o = i.width * n, a = i.height * n, l = (t.width - o) / 2, r = (t.height - a) / 2;
537
- this.minimapCtx.fillStyle = "#ffffff", this.minimapCtx.fillRect(l, r, o, a), this.minimapCtx.save(), this.minimapCtx.translate(l, r), this.minimapCtx.scale(n, n), (this.currentObject ? [...this.objects, this.currentObject] : this.objects).forEach((d) => {
538
- switch (this.minimapCtx.fillStyle = d.color, this.minimapCtx.strokeStyle = d.color, this.minimapCtx.lineWidth = Math.max(d.lineWidth, 1), this.minimapCtx.setLineDash([]), d.type) {
539
- case "RECTANGLE": {
540
- const c = d;
541
- this.minimapCtx.strokeRect(c.x, c.y, c.width, c.height);
542
- break;
543
- }
544
- case "CIRCLE": {
545
- const c = d;
546
- this.minimapCtx.beginPath(), this.minimapCtx.arc(c.x, c.y, c.radius, 0, Math.PI * 2), this.minimapCtx.stroke();
547
- break;
548
- }
549
- case "PATH": {
550
- const c = d;
551
- c.points.length > 0 && (this.minimapCtx.beginPath(), this.minimapCtx.lineCap = "round", this.minimapCtx.lineJoin = "round", this.minimapCtx.moveTo(c.points[0].x, c.points[0].y), c.points.forEach((p) => this.minimapCtx.lineTo(p.x, p.y)), this.minimapCtx.stroke());
552
- break;
553
- }
554
- case "TEXT": {
555
- const c = d;
556
- this.minimapCtx.font = `${c.fontSize}px sans-serif`, this.minimapCtx.fillText(c.text, c.x, c.y);
557
- break;
558
- }
559
- case "IMAGE": {
560
- const c = d;
561
- c.imageElement && this.minimapCtx.drawImage(c.imageElement, c.x, c.y, c.width, c.height);
562
- break;
563
- }
564
- }
565
- }), this.minimapCtx.restore(), this.minimapCtx.strokeStyle = "#94a3b8", this.minimapCtx.lineWidth = 1, this.minimapCtx.strokeRect(l, r, o, a);
566
- }
567
- // 小地图点击定位
568
- handleMinimapClick(t) {
569
- const i = this.minimapCanvas.getBoundingClientRect(), s = t.clientX - i.left, e = t.clientY - i.top, n = this.minimapCanvas.width / this.canvas.width, o = this.minimapCanvas.height / this.canvas.height, a = Math.min(n, o) * 0.92, l = this.canvas.width * a, r = this.canvas.height * a, h = (this.minimapCanvas.width - l) / 2, d = (this.minimapCanvas.height - r) / 2, c = s - h, p = e - d, u = (c / a - this.panOffset.x) / this.scale, g = (p / a - this.panOffset.y) / this.scale, m = this.canvas.width / 2, x = this.canvas.height / 2;
570
- this.panOffset = {
571
- x: m / this.scale - u,
572
- y: x / this.scale - g
573
- }, this.renderCanvas(), this.renderMinimap();
520
+ { x: i.x, y: i.y },
521
+ { x: i.x + i.width, y: i.y },
522
+ { x: i.x, y: i.y + i.height },
523
+ { x: i.x + i.width, y: i.y + i.height }
524
+ ].forEach((a) => {
525
+ t.beginPath(), t.rect(a.x - e / 2, a.y - e / 2, e, e), t.fill(), t.stroke();
526
+ }), t.strokeStyle = "#3b82f6", t.lineWidth = 1, t.setLineDash([5, 5]), t.strokeRect(i.x, i.y, i.width, i.height), t.setLineDash([]);
574
527
  }
575
528
  // 图片上传处理
576
529
  handleImageUpload(t) {
577
- const i = t.target;
578
- if (!i.files || i.files.length === 0) return;
579
- const s = i.files[0], e = new FileReader();
530
+ const s = t.target;
531
+ if (!s.files || s.files.length === 0) return;
532
+ const i = s.files[0], e = new FileReader();
580
533
  e.onload = (n) => {
581
534
  var l;
582
- const o = (l = n.target) == null ? void 0 : l.result, a = new Image();
583
- a.onload = () => {
535
+ const a = (l = n.target) == null ? void 0 : l.result, o = new Image();
536
+ o.onload = () => {
584
537
  this.saveHistory();
585
- const r = 300;
586
- let h = a.width, d = a.height;
587
- if (h > r || d > r) {
588
- const p = Math.min(r / h, r / d);
589
- h *= p, d *= p;
538
+ const h = 300;
539
+ let r = o.width, c = o.height;
540
+ if (r > h || c > h) {
541
+ const u = Math.min(h / r, h / c);
542
+ r *= u, c *= u;
590
543
  }
591
- const c = {
544
+ const d = {
592
545
  id: this.generateId(),
593
546
  type: "IMAGE",
594
547
  x: 100,
595
548
  y: 100,
596
- width: h,
597
- height: d,
549
+ width: r,
550
+ height: c,
598
551
  color: "#000000",
599
552
  lineWidth: 1,
600
- dataUrl: o,
601
- imageElement: a
553
+ dataUrl: a,
554
+ imageElement: o
602
555
  };
603
- this.objects.push(c), this.selectedId = c.id, this.setTool("SELECT"), this.renderCanvas(), this.renderMinimap(), this.updateUI(), this.dispatchChangeEvent();
604
- }, a.src = o;
605
- }, e.readAsDataURL(s), i.value = "";
556
+ this.objects.push(d), this.selectedId = d.id, this.setTool("SELECT"), this.renderCanvas(), this.updateUI(), this.dispatchChangeEvent();
557
+ }, o.src = a;
558
+ }, e.readAsDataURL(i), s.value = "";
606
559
  }
607
560
  // 保存 JSON
608
561
  saveJson() {
609
562
  const t = {
610
563
  version: "1.0",
611
- objects: this.objects.map((o) => {
612
- const { imageElement: a, ...l } = o;
564
+ objects: this.objects.map((a) => {
565
+ const { imageElement: o, ...l } = a;
613
566
  return l;
614
567
  })
615
- }, i = JSON.stringify(t, null, 2), s = new Blob([i], { type: "application/json" }), e = URL.createObjectURL(s), n = document.createElement("a");
568
+ }, s = JSON.stringify(t, null, 2), i = new Blob([s], { type: "application/json" }), e = URL.createObjectURL(i), n = document.createElement("a");
616
569
  n.href = e, n.download = "canvas-project.json", n.click(), URL.revokeObjectURL(e);
617
570
  }
618
571
  // 加载 JSON
619
572
  loadJson(t) {
620
- const i = t.target;
621
- if (!i.files || i.files.length === 0) return;
622
- const s = i.files[0], e = new FileReader();
573
+ const s = t.target;
574
+ if (!s.files || s.files.length === 0) return;
575
+ const i = s.files[0], e = new FileReader();
623
576
  e.onload = (n) => {
624
- var o;
577
+ var a;
625
578
  try {
626
- const a = JSON.parse((o = n.target) == null ? void 0 : o.result);
627
- a.objects && Array.isArray(a.objects) && (this.saveHistory(), this.objects = a.objects, this.selectedId = null, this.objects.forEach((l) => {
579
+ const o = JSON.parse((a = n.target) == null ? void 0 : a.result);
580
+ o.objects && Array.isArray(o.objects) && (this.saveHistory(), this.objects = o.objects, this.selectedId = null, this.objects.forEach((l) => {
628
581
  if (l.type === "IMAGE" && l.dataUrl) {
629
- const r = new Image();
630
- r.onload = () => {
631
- l.imageElement = r, this.renderCanvas(), this.renderMinimap();
632
- }, r.src = l.dataUrl;
582
+ const h = new Image();
583
+ h.onload = () => {
584
+ l.imageElement = h, this.renderCanvas();
585
+ }, h.src = l.dataUrl;
633
586
  }
634
- }), this.renderCanvas(), this.renderMinimap(), this.updateUI(), this.dispatchChangeEvent());
635
- } catch (a) {
636
- console.error("Failed to load JSON:", a);
587
+ }), this.renderCanvas(), this.updateUI(), this.dispatchChangeEvent());
588
+ } catch (o) {
589
+ console.error("Failed to load JSON:", o);
637
590
  }
638
- }, e.readAsText(s), i.value = "";
591
+ }, e.readAsText(i), s.value = "";
639
592
  }
640
593
  // 导出 PNG
641
594
  exportPng() {
642
595
  const t = document.createElement("canvas");
643
596
  t.width = this.canvas.width, t.height = this.canvas.height;
644
- const i = t.getContext("2d");
645
- i.fillStyle = "#ffffff", i.fillRect(0, 0, t.width, t.height), i.translate(this.panOffset.x, this.panOffset.y), i.scale(this.scale, this.scale), this.objects.forEach((n) => this.drawObject(i, n, !0));
646
- const s = t.toDataURL("image/png"), e = document.createElement("a");
647
- e.href = s, e.download = "canvas-export.png", e.click();
597
+ const s = t.getContext("2d");
598
+ s.fillStyle = "#ffffff", s.fillRect(0, 0, t.width, t.height), s.translate(this.panOffset.x, this.panOffset.y), s.scale(this.scale, this.scale), this.objects.forEach((n) => this.drawObject(s, n, !0));
599
+ const i = t.toDataURL("image/png"), e = document.createElement("a");
600
+ e.href = i, e.download = "canvas-export.png", e.click();
648
601
  }
649
602
  // 更新 UI
650
603
  updateUI() {
@@ -653,7 +606,7 @@ class b extends HTMLElement {
653
606
  if (this.selectedId) {
654
607
  const e = this.objects.find((n) => n.id === this.selectedId);
655
608
  if (e) {
656
- const o = {
609
+ const a = {
657
610
  RECTANGLE: "矩形",
658
611
  CIRCLE: "圆形",
659
612
  PATH: "画笔",
@@ -661,22 +614,22 @@ class b extends HTMLElement {
661
614
  IMAGE: "图片"
662
615
  }[e.type] || e.type;
663
616
  t.innerHTML = `
664
- <span class="selection-label">已选择: ${o}</span>
617
+ <span class="selection-label">已选择: ${a}</span>
665
618
  <button class="delete-btn" title="删除">
666
619
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
667
620
  <path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/>
668
621
  </svg>
669
622
  </button>
670
623
  `, t.classList.add("visible");
671
- const a = t.querySelector(".delete-btn");
672
- a && a.addEventListener("click", () => this.deleteSelected());
624
+ const o = t.querySelector(".delete-btn");
625
+ o && o.addEventListener("click", () => this.deleteSelected());
673
626
  }
674
627
  } else
675
628
  t.classList.remove("visible"), t.innerHTML = "";
676
- const i = this.shadow.querySelector(".undo-btn");
677
- i && (i.disabled = this.history.length === 0);
678
- const s = this.shadow.querySelector(".empty-hint");
679
- s && (s.style.display = this.objects.length === 0 ? "flex" : "none");
629
+ const s = this.shadow.querySelector(".undo-btn");
630
+ s && (s.disabled = this.history.length === 0);
631
+ const i = this.shadow.querySelector(".empty-hint");
632
+ i && (i.style.display = this.objects.length === 0 ? "flex" : "none");
680
633
  }
681
634
  // 渲染 DOM 结构
682
635
  render() {
@@ -772,19 +725,6 @@ class b extends HTMLElement {
772
725
  <div class="canvas-container">
773
726
  <canvas class="main-canvas"></canvas>
774
727
 
775
- ${this.config.showMinimap ? `
776
- <div class="minimap-wrapper">
777
- <div class="minimap-header">
778
- <svg class="minimap-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
779
- <rect x="3" y="3" width="18" height="18" rx="2"/>
780
- <path d="M3 9h18M9 21V9"/>
781
- </svg>
782
- <span>导航</span>
783
- </div>
784
- <canvas class="minimap-canvas" width="220" height="140"></canvas>
785
- </div>
786
- ` : ""}
787
-
788
728
  <!-- 文本输入 -->
789
729
  <div class="text-input-container" style="display: none;">
790
730
  <div class="text-input-hint">按 Enter 确认,Esc 取消</div>
@@ -799,38 +739,38 @@ class b extends HTMLElement {
799
739
  </div>
800
740
  </div>
801
741
  </div>
802
- `, this.container = this.shadow.querySelector(".editor-container"), this.toolbar = this.shadow.querySelector(".toolbar"), this.topBar = this.shadow.querySelector(".top-bar"), this.canvasContainer = this.shadow.querySelector(".canvas-container"), this.canvas = this.shadow.querySelector(".main-canvas"), this.ctx = this.canvas.getContext("2d"), this.config.showMinimap && (this.minimapCanvas = this.shadow.querySelector(".minimap-canvas"), this.minimapCtx = this.minimapCanvas.getContext("2d")), this.textInputContainer = this.shadow.querySelector(".text-input-container"), this.textInput = this.shadow.querySelector(".text-input"), this.bindEvents();
742
+ `, this.container = this.shadow.querySelector(".editor-container"), this.toolbar = this.shadow.querySelector(".toolbar"), this.topBar = this.shadow.querySelector(".top-bar"), this.canvasContainer = this.shadow.querySelector(".canvas-container"), this.canvas = this.shadow.querySelector(".main-canvas"), this.ctx = this.canvas.getContext("2d"), this.textInputContainer = this.shadow.querySelector(".text-input-container"), this.textInput = this.shadow.querySelector(".text-input"), this.bindEvents();
803
743
  }
804
744
  // 绑定事件
805
745
  bindEvents() {
806
- 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) => {
807
- h.addEventListener("mousedown", (d) => {
808
- d.preventDefault();
809
- }), h.addEventListener("click", () => {
746
+ this.canvas.addEventListener("mousedown", (r) => this.handleCanvasPointerDown(r)), this.canvas.addEventListener("mousemove", (r) => this.handleCanvasPointerMove(r)), this.canvas.addEventListener("mouseup", () => this.handleCanvasPointerUp()), this.canvas.addEventListener("mouseleave", () => this.handleCanvasPointerUp()), this.canvas.addEventListener("dblclick", (r) => this.handleCanvasDoubleClick(r)), this.canvas.addEventListener("touchstart", (r) => this.handleCanvasPointerDown(r)), this.canvas.addEventListener("touchmove", (r) => this.handleCanvasPointerMove(r)), this.canvas.addEventListener("touchend", () => this.handleCanvasPointerUp()), this.canvas.addEventListener("wheel", this.boundHandleWheel, { passive: !1 }), this.shadow.querySelectorAll(".tool-btn[data-tool]").forEach((r) => {
747
+ r.addEventListener("mousedown", (c) => {
748
+ c.preventDefault();
749
+ }), r.addEventListener("click", () => {
810
750
  this.isTextInputVisible && this.submitText();
811
- const d = h.getAttribute("data-tool");
812
- this.setTool(d);
751
+ const c = r.getAttribute("data-tool");
752
+ this.setTool(c);
813
753
  });
814
754
  });
815
755
  const t = this.shadow.querySelector(".undo-btn");
816
756
  t && t.addEventListener("click", () => this.undo());
817
- const i = this.shadow.querySelector(".color-picker");
818
- i && i.addEventListener("input", (h) => {
819
- this.color = h.target.value;
757
+ const s = this.shadow.querySelector(".color-picker");
758
+ s && s.addEventListener("input", (r) => {
759
+ this.color = r.target.value;
820
760
  });
821
- const s = this.shadow.querySelector(".image-input");
822
- s && s.addEventListener("change", (h) => this.handleImageUpload(h));
823
- const e = this.shadow.querySelector(".zoom-in-btn"), n = this.shadow.querySelector(".zoom-out-btn"), o = this.shadow.querySelector(".zoom-text");
824
- e && e.addEventListener("click", () => this.zoomIn()), n && n.addEventListener("click", () => this.zoomOut()), o && o.addEventListener("click", () => this.resetZoom());
825
- const a = this.shadow.querySelector(".save-json-btn"), l = this.shadow.querySelector(".load-json-input"), r = this.shadow.querySelector(".export-png-btn");
826
- a && a.addEventListener("click", () => this.saveJson()), l && l.addEventListener("change", (h) => this.loadJson(h)), r && r.addEventListener("click", () => this.exportPng()), this.minimapCanvas && this.minimapCanvas.addEventListener("click", (h) => this.handleMinimapClick(h)), this.textInput && (this.textInput.addEventListener("keydown", (h) => {
827
- h.key === "Enter" ? (h.preventDefault(), this.submitText()) : h.key === "Escape" && this.hideTextInput();
761
+ const i = this.shadow.querySelector(".image-input");
762
+ i && i.addEventListener("change", (r) => this.handleImageUpload(r));
763
+ const e = this.shadow.querySelector(".zoom-in-btn"), n = this.shadow.querySelector(".zoom-out-btn"), a = this.shadow.querySelector(".zoom-text");
764
+ e && e.addEventListener("click", () => this.zoomIn()), n && n.addEventListener("click", () => this.zoomOut()), a && a.addEventListener("click", () => this.resetZoom());
765
+ const o = this.shadow.querySelector(".save-json-btn"), l = this.shadow.querySelector(".load-json-input"), h = this.shadow.querySelector(".export-png-btn");
766
+ o && o.addEventListener("click", () => this.saveJson()), l && l.addEventListener("change", (r) => this.loadJson(r)), h && h.addEventListener("click", () => this.exportPng()), this.textInput && (this.textInput.addEventListener("keydown", (r) => {
767
+ r.key === "Enter" ? (r.preventDefault(), this.submitText()) : r.key === "Escape" && this.hideTextInput();
828
768
  }), this.textInput.addEventListener("blur", () => {
829
769
  this.isTextInputVisible && this.submitText();
830
770
  }));
831
771
  }
832
772
  // 创建工具按钮 HTML
833
- createToolButton(t, i, s) {
773
+ createToolButton(t, s, i) {
834
774
  const e = {
835
775
  "select-icon": '<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>',
836
776
  "pencil-icon": '<path d="M17 3a2.85 2.85 0 114 4L7.5 20.5 2 22l1.5-5.5L17 3z"/>',
@@ -839,9 +779,9 @@ class b extends HTMLElement {
839
779
  "text-icon": '<path d="M4 7V4h16v3M9 20h6M12 4v16"/>'
840
780
  };
841
781
  return `
842
- <button class="tool-btn ${this.tool === t ? "active" : ""}" data-tool="${t}" title="${s}">
782
+ <button class="tool-btn ${this.tool === t ? "active" : ""}" data-tool="${t}" title="${i}">
843
783
  <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
844
- ${e[i]}
784
+ ${e[s]}
845
785
  </svg>
846
786
  </button>
847
787
  `;
@@ -1083,53 +1023,6 @@ class b extends HTMLElement {
1083
1023
  touch-action: none;
1084
1024
  }
1085
1025
 
1086
- /* 小地图 */
1087
- .minimap-wrapper {
1088
- position: absolute;
1089
- top: 16px;
1090
- right: 16px;
1091
- z-index: 30;
1092
- border-radius: 12px;
1093
- overflow: hidden;
1094
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
1095
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1096
- padding: 2px;
1097
- }
1098
-
1099
- .minimap-wrapper > * {
1100
- background: #ffffff;
1101
- }
1102
-
1103
- .minimap-header {
1104
- display: flex;
1105
- align-items: center;
1106
- gap: 8px;
1107
- padding: 6px 12px;
1108
- background: linear-gradient(to right, #f8fafc, #f1f5f9);
1109
- border-bottom: 1px solid #e2e8f0;
1110
- font-size: 12px;
1111
- font-weight: 600;
1112
- color: #475569;
1113
- border-radius: 10px 10px 0 0;
1114
- }
1115
-
1116
- .minimap-icon {
1117
- width: 12px;
1118
- height: 12px;
1119
- color: #4f46e5;
1120
- }
1121
-
1122
- .minimap-canvas {
1123
- cursor: pointer;
1124
- background: #f8fafc;
1125
- border-radius: 0 0 10px 10px;
1126
- display: block;
1127
- }
1128
-
1129
- .minimap-canvas:hover {
1130
- filter: brightness(1.05);
1131
- }
1132
-
1133
1026
  /* 文本输入 */
1134
1027
  .text-input-container {
1135
1028
  position: absolute;
@@ -1184,8 +1077,8 @@ class b extends HTMLElement {
1184
1077
  `;
1185
1078
  }
1186
1079
  }
1187
- typeof window < "u" && !customElements.get("canvas-drawing-editor") && customElements.define("canvas-drawing-editor", b);
1080
+ typeof window < "u" && !customElements.get("canvas-drawing-editor") && customElements.define("canvas-drawing-editor", g);
1188
1081
  export {
1189
- b as CanvasDrawingEditor
1082
+ g as CanvasDrawingEditor
1190
1083
  };
1191
1084
  //# sourceMappingURL=canvas-drawing-editor.es.js.map