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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-drawing-editor.umd.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","value","_b","_a","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.umd.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","value","_b","_a","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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "canvas-drawing-editor",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "A powerful canvas-based drawing editor Web Component - Zero dependencies, works with Vue 2/3, React, Angular, and vanilla HTML",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/canvas-drawing-editor.umd.js",
|