canvas-drawing-editor 2.0.10 → 2.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 typsusan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -39,7 +39,7 @@ npm install canvas-drawing-editor
39
39
  </style>
40
40
  </head>
41
41
  <body>
42
- <canvas-drawing-editor title="My Canvas" show-minimap="true"></canvas-drawing-editor>
42
+ <canvas-drawing-editor title="My Canvas"></canvas-drawing-editor>
43
43
 
44
44
  <script src="https://unpkg.com/canvas-drawing-editor/dist/canvas-drawing-editor.umd.js"></script>
45
45
  </body>
@@ -52,7 +52,6 @@ npm install canvas-drawing-editor
52
52
  <template>
53
53
  <canvas-drawing-editor
54
54
  title="Vue Canvas"
55
- show-minimap="true"
56
55
  style="width: 100%; height: 600px;"
57
56
  ></canvas-drawing-editor>
58
57
  </template>
@@ -90,7 +89,6 @@ import 'canvas-drawing-editor'
90
89
  <template>
91
90
  <canvas-drawing-editor
92
91
  title="Vue2 Canvas"
93
- show-minimap="true"
94
92
  style="width: 100%; height: 600px;"
95
93
  ></canvas-drawing-editor>
96
94
  </template>
@@ -105,7 +103,6 @@ function App() {
105
103
  return (
106
104
  <canvas-drawing-editor
107
105
  title="React Canvas"
108
- show-minimap="true"
109
106
  style={{ width: '100%', height: '600px' }}
110
107
  />
111
108
  );
@@ -127,7 +124,7 @@ function App() {
127
124
  | `show-export` | boolean | true | Show JSON save |
128
125
  | `show-import` | boolean | true | Show JSON load |
129
126
  | `show-color` | boolean | true | Show color picker |
130
- | `show-minimap` | boolean | true | Show navigation minimap |
127
+ | `show-clear` | boolean | true | Show clear canvas button |
131
128
  | `initial-data` | string | - | Initial JSON data to render (see format below) |
132
129
 
133
130
  ### 📊 Initial Data
@@ -270,7 +267,7 @@ npm install canvas-drawing-editor
270
267
  </style>
271
268
  </head>
272
269
  <body>
273
- <canvas-drawing-editor title="我的画板" show-minimap="true"></canvas-drawing-editor>
270
+ <canvas-drawing-editor title="我的画板"></canvas-drawing-editor>
274
271
 
275
272
  <script src="https://unpkg.com/canvas-drawing-editor/dist/canvas-drawing-editor.umd.js"></script>
276
273
  </body>
@@ -283,7 +280,6 @@ npm install canvas-drawing-editor
283
280
  <template>
284
281
  <canvas-drawing-editor
285
282
  title="Vue 画板"
286
- show-minimap="true"
287
283
  style="width: 100%; height: 600px;"
288
284
  ></canvas-drawing-editor>
289
285
  </template>
@@ -321,7 +317,6 @@ import 'canvas-drawing-editor'
321
317
  <template>
322
318
  <canvas-drawing-editor
323
319
  title="Vue2 画板"
324
- show-minimap="true"
325
320
  style="width: 100%; height: 600px;"
326
321
  ></canvas-drawing-editor>
327
322
  </template>
@@ -336,7 +331,6 @@ function App() {
336
331
  return (
337
332
  <canvas-drawing-editor
338
333
  title="React 画板"
339
- show-minimap="true"
340
334
  style={{ width: '100%', height: '600px' }}
341
335
  />
342
336
  );
@@ -358,7 +352,7 @@ function App() {
358
352
  | `show-export` | boolean | true | 显示 JSON 保存 |
359
353
  | `show-import` | boolean | true | 显示 JSON 加载 |
360
354
  | `show-color` | boolean | true | 显示颜色选择器 |
361
- | `show-minimap` | boolean | true | 显示导航小地图 |
355
+ | `show-clear` | boolean | true | 显示清空画布按钮 |
362
356
  | `initial-data` | string | - | 初始化 JSON 数据(格式见下方) |
363
357
 
364
358
  ### 📊 初始化数据
@@ -9,7 +9,8 @@ const f = {
9
9
  showDownload: !0,
10
10
  showExport: !0,
11
11
  showImport: !0,
12
- showColor: !0
12
+ showColor: !0,
13
+ showClear: !0
13
14
  };
14
15
  class g extends HTMLElement {
15
16
  constructor() {
@@ -63,7 +64,8 @@ class g extends HTMLElement {
63
64
  showDownload: this.getAttribute("show-download") !== "false",
64
65
  showExport: this.getAttribute("show-export") !== "false",
65
66
  showImport: this.getAttribute("show-import") !== "false",
66
- showColor: this.getAttribute("show-color") !== "false"
67
+ showColor: this.getAttribute("show-color") !== "false",
68
+ showClear: this.getAttribute("show-clear") !== "false"
67
69
  };
68
70
  }
69
71
  // 生成唯一 ID
@@ -396,28 +398,28 @@ class g extends HTMLElement {
396
398
  if (!this.isDragging || !this.dragStart) return;
397
399
  const { x: s, y: i } = this.getMousePos(t);
398
400
  if (this.isResizing && this.selectedId && this.resizeHandle && this.resizeStartBounds && this.resizeOriginalObject) {
399
- const e = this.objects.find((c) => c.id === this.selectedId);
401
+ const e = this.objects.find((r) => r.id === this.selectedId);
400
402
  if (!e) return;
401
403
  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) {
404
+ let o = this.resizeStartBounds.x, l = this.resizeStartBounds.y, h = this.resizeStartBounds.width, c = this.resizeStartBounds.height;
405
+ 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") && (c = this.resizeStartBounds.height + a), this.resizeHandle.includes("n") && (l = this.resizeStartBounds.y + a, c = this.resizeStartBounds.height - a), h = Math.max(10, h), c = Math.max(10, c), e.type) {
404
406
  case "RECTANGLE":
405
407
  case "IMAGE":
406
- e.x = o, e.y = l, e.width = h, e.height = r;
408
+ e.x = o, e.y = l, e.width = h, e.height = c;
407
409
  break;
408
410
  case "CIRCLE": {
409
- const c = Math.max(h, r) / 2;
410
- e.x = o + c, e.y = l + c, e.radius = c;
411
+ const r = Math.max(h, c) / 2;
412
+ e.x = o + r, e.y = l + r, e.radius = r;
411
413
  break;
412
414
  }
413
415
  case "TEXT": {
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));
416
+ const r = this.resizeOriginalObject, d = h / this.resizeStartBounds.width;
417
+ e.x = o, e.y = l + c, e.fontSize = Math.max(8, Math.round(r.fontSize * d));
416
418
  break;
417
419
  }
418
420
  case "PATH": {
419
- const c = this.resizeOriginalObject, d = h / this.resizeStartBounds.width, u = r / this.resizeStartBounds.height;
420
- e.points = c.points.map((p) => ({
421
+ const r = this.resizeOriginalObject, d = h / this.resizeStartBounds.width, u = c / this.resizeStartBounds.height;
422
+ e.points = r.points.map((p) => ({
421
423
  x: o + (p.x - this.resizeStartBounds.x) * d,
422
424
  y: l + (p.y - this.resizeStartBounds.y) * u
423
425
  }));
@@ -536,18 +538,18 @@ class g extends HTMLElement {
536
538
  o.onload = () => {
537
539
  this.saveHistory();
538
540
  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;
541
+ let c = o.width, r = o.height;
542
+ if (c > h || r > h) {
543
+ const u = Math.min(h / c, h / r);
544
+ c *= u, r *= u;
543
545
  }
544
546
  const d = {
545
547
  id: this.generateId(),
546
548
  type: "IMAGE",
547
549
  x: 100,
548
550
  y: 100,
549
- width: r,
550
- height: c,
551
+ width: c,
552
+ height: r,
551
553
  color: "#000000",
552
554
  lineWidth: 1,
553
555
  dataUrl: a,
@@ -599,6 +601,10 @@ class g extends HTMLElement {
599
601
  const i = t.toDataURL("image/png"), e = document.createElement("a");
600
602
  e.href = i, e.download = "canvas-export.png", e.click();
601
603
  }
604
+ // 清空画布
605
+ clearCanvas() {
606
+ this.objects.length !== 0 && (this.saveHistory(), this.objects = [], this.selectedId = null, this.render(), this.dispatchChangeEvent(), this.updateUI());
607
+ }
602
608
  // 更新 UI
603
609
  updateUI() {
604
610
  const t = this.shadow.querySelector(".selection-info");
@@ -691,7 +697,7 @@ class g extends HTMLElement {
691
697
  </button>
692
698
  </div>
693
699
  ` : ""}
694
- ${this.config.showExport || this.config.showImport || this.config.showDownload ? `
700
+ ${this.config.showExport || this.config.showImport || this.config.showDownload || this.config.showClear ? `
695
701
  <div class="file-controls">
696
702
  ${this.config.showExport ? `
697
703
  <button class="file-btn save-json-btn" title="保存项目 (JSON)">
@@ -716,6 +722,14 @@ class g extends HTMLElement {
716
722
  </svg>
717
723
  </button>
718
724
  ` : ""}
725
+ ${this.config.showClear ? `
726
+ <button class="file-btn clear-canvas-btn" title="清空画布">
727
+ <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
728
+ <path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/>
729
+ <line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/>
730
+ </svg>
731
+ </button>
732
+ ` : ""}
719
733
  </div>
720
734
  ` : ""}
721
735
  </div>
@@ -744,12 +758,12 @@ class g extends HTMLElement {
744
758
  // 绑定事件
745
759
  bindEvents() {
746
760
  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();
761
+ r.addEventListener("mousedown", (d) => {
762
+ d.preventDefault();
749
763
  }), r.addEventListener("click", () => {
750
764
  this.isTextInputVisible && this.submitText();
751
- const c = r.getAttribute("data-tool");
752
- this.setTool(c);
765
+ const d = r.getAttribute("data-tool");
766
+ this.setTool(d);
753
767
  });
754
768
  });
755
769
  const t = this.shadow.querySelector(".undo-btn");
@@ -762,8 +776,8 @@ class g extends HTMLElement {
762
776
  i && i.addEventListener("change", (r) => this.handleImageUpload(r));
763
777
  const e = this.shadow.querySelector(".zoom-in-btn"), n = this.shadow.querySelector(".zoom-out-btn"), a = this.shadow.querySelector(".zoom-text");
764
778
  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) => {
779
+ const o = this.shadow.querySelector(".save-json-btn"), l = this.shadow.querySelector(".load-json-input"), h = this.shadow.querySelector(".export-png-btn"), c = this.shadow.querySelector(".clear-canvas-btn");
780
+ o && o.addEventListener("click", () => this.saveJson()), l && l.addEventListener("change", (r) => this.loadJson(r)), h && h.addEventListener("click", () => this.exportPng()), c && c.addEventListener("click", () => this.clearCanvas()), this.textInput && (this.textInput.addEventListener("keydown", (r) => {
767
781
  r.key === "Enter" ? (r.preventDefault(), this.submitText()) : r.key === "Escape" && this.hideTextInput();
768
782
  }), this.textInput.addEventListener("blur", () => {
769
783
  this.isTextInputVisible && this.submitText();