@wbiokr/arrow 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/bundle.cjs.js +1 -1
- package/dist/bundle.cjs.js.map +1 -1
- package/dist/bundle.esm.js +1 -1
- package/dist/bundle.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/bundle.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.cjs.js","sources":["../src/editor.js"],"sourcesContent":["import { Keybinding } from '@wbiokr/keybinding'\r\n\r\n// 样式注入\r\nconst STYLES = `\r\n.ae-d2-container {\r\n position: relative;\r\n width: 1000px;\r\n height: 600px;\r\n background: #fff;\r\n margin: auto;\r\n}\r\n\r\n.ae-d2-svg {\r\n width: 100%;\r\n height: 100%;\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n z-index: 10;\r\n}\r\n\r\n\r\n.ae-arrow-path {\r\n fill: none;\r\n stroke-linejoin: round;\r\n cursor: pointer;\r\n}\r\n\r\n.ae-arrow-path:hover {\r\n stroke: #00aaff;\r\n}\r\n\r\n.ae-transform-box {\r\n fill: none;\r\n stroke: #00aaff;\r\n stroke-width: 2;\r\n stroke-dasharray: 4;\r\n}\r\n\r\n.ae-transform-handle {\r\n fill: #fff;\r\n stroke: #00aaff;\r\n stroke-width: 2;\r\n cursor: pointer;\r\n}\r\n\r\n.ae-transform-handle:hover {\r\n fill: #00aaff;\r\n}\r\n\r\n.ae-rotate-handle {\r\n fill: #fff;\r\n stroke: #ff6600;\r\n stroke-width: 2;\r\n cursor: grab;\r\n}\r\n\r\n.ae-rotate-handle:hover {\r\n fill: #ff6600;\r\n}\r\n\r\n.ae-rotate-line {\r\n stroke: #ff6600;\r\n stroke-width: 1;\r\n stroke-dasharray: 4;\r\n}\r\n\r\n/* 工具条样式 */\r\n.ae-toolbar {\r\n position: fixed;\r\n display: none;\r\n flex-direction: column;\r\n gap: 10px;\r\n padding: 12px;\r\n background: #fff;\r\n border: 1px solid #ddd;\r\n border-radius: 8px;\r\n box-shadow: 0 2px 12px rgba(0,0,0,0.15);\r\n z-index: 10000;\r\n pointer-events: auto;\r\n min-width: 140px;\r\n}\r\n\r\n.ae-toolbar-drag-handle {\r\n cursor: grab;\r\n text-align: center;\r\n padding: 4px;\r\n color: #999;\r\n font-size: 14px;\r\n line-height: 1;\r\n user-select: none;\r\n border-bottom: 1px solid #eee;\r\n margin: -12px -12px 8px -12px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n border-radius: 8px 8px 0 0;\r\n}\r\n\r\n.ae-toolbar-drag-handle:active {\r\n cursor: grabbing;\r\n}\r\n\r\n.ae-toolbar-item {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n}\r\n\r\n.ae-toolbar-row {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.ae-toolbar-label {\r\n font-size: 11px;\r\n color: #666;\r\n}\r\n\r\n.ae-scale-btn {\r\n flex: 1;\r\n padding: 6px 8px;\r\n background: #f0f0f0;\r\n color: #333;\r\n border: 1px solid #ccc;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 11px;\r\n transition: background 0.2s;\r\n}\r\n\r\n.ae-scale-btn:hover {\r\n background: #e0e0e0;\r\n}\r\n\r\n.ae-scale-btn:active {\r\n background: #d0d0d0;\r\n}\r\n\r\n.ae-toolbar input[type=\"color\"] {\r\n width: 40px;\r\n height: 30px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n padding: 0;\r\n background: none;\r\n}\r\n\r\n.ae-toolbar input[type=\"range\"] {\r\n width: 120px;\r\n cursor: pointer;\r\n}\r\n\r\n.ae-toolbar-value {\r\n font-size: 10px;\r\n color: #999;\r\n text-align: right;\r\n}\r\n`\r\n\r\n// 注入样式\r\nif (typeof document !== 'undefined') {\r\n const styleEl = document.createElement('style')\r\n styleEl.textContent = STYLES\r\n document.head.appendChild(styleEl)\r\n}\r\n\r\nexport class ArrowEditor {\r\n\r\n constructor(container, options = {}) {\r\n this.container = typeof container === 'string' ? document.querySelector(container) : container\r\n this.svg = null\r\n\r\n this.arrows = []\r\n this.drawing = false\r\n this.current = null\r\n this.selected = null\r\n this.mode = null\r\n this.lastClickTime = 0\r\n this.lastClickPos = null\r\n this._shouldBlockClick = false\r\n this._defaultColor = '#2b8cff'\r\n\r\n // 配置选项\r\n this.isCtrl = options.isCtrl || false\r\n this.stopPropagation = options.stopPropagation || false\r\n this.preventDefault = options.preventDefault || false\r\n this.onDrawEnd = options.onDrawEnd || null\r\n this.onRemove = options.onRemove || null\r\n this.onChange = options.onChange || null\r\n\r\n // 默认样式\r\n this._defaultColor = options.defaultColor || this._defaultColor\r\n this._strokeWidth = options.defaultStrokeWidth || 8\r\n this._curveRate = options.defaultCurveRate ?? 0\r\n\r\n // 变换相关\r\n this._transformMode = null // 'rotate' | 'scale'\r\n this._transformHandle = null\r\n this._transformStartPos = null\r\n this._transformStartPoints = null\r\n this._transformCenter = null\r\n this._transformStartAngle = null\r\n this._rotationOffset = 0\r\n\r\n // 工具条相关\r\n this._toolbar = null\r\n\r\n // 记录鼠标位置,用于空格键打点\r\n this._lastMousePos = null\r\n\r\n this._createSVG()\r\n this._initKeybindings()\r\n this._initEvents()\r\n }\r\n\r\n _createSVG() {\r\n // 检查并设置容器的定位\r\n if (typeof getComputedStyle !== 'undefined') {\r\n const containerStyle = getComputedStyle(this.container)\r\n if (containerStyle.position === 'static') {\r\n this.container.style.position = 'relative'\r\n }\r\n }\r\n\r\n // 创建 SVG 元素\r\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\r\n this.svg.setAttribute('class', 'ae-d2-svg')\r\n this.container.appendChild(this.svg)\r\n\r\n // 创建 defs 和 marker\r\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\r\n this.svg.appendChild(defs)\r\n\r\n const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker')\r\n marker.setAttribute('id', 'ae-arrowhead')\r\n marker.setAttribute('markerWidth', '10')\r\n marker.setAttribute('markerHeight', '10')\r\n marker.setAttribute('refX', '9')\r\n marker.setAttribute('refY', '5')\r\n marker.setAttribute('orient', 'auto')\r\n\r\n const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon')\r\n polygon.setAttribute('points', '0,0 10,5 0,10 2,5')\r\n polygon.setAttribute('fill', this._defaultColor)\r\n\r\n marker.appendChild(polygon)\r\n defs.appendChild(marker)\r\n }\r\n\r\n _createToolbar() {\r\n if (this._toolbar) {\r\n this._toolbar.remove()\r\n }\r\n\r\n this._toolbar = document.createElement('div')\r\n this._toolbar.className = 'ae-toolbar'\r\n\r\n const color = this.selected.color || this._defaultColor\r\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\r\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\r\n\r\n this._toolbar.innerHTML = `\r\n <div class=\"ae-toolbar-drag-handle\">:::</div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">颜色</span>\r\n <input type=\"color\" class=\"ae-color-input\" value=\"${color}\" />\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">粗细</span>\r\n <input type=\"range\" class=\"ae-stroke-input\" min=\"1\" max=\"60\" value=\"${strokeWidth}\" />\r\n <span class=\"ae-toolbar-value\">${strokeWidth}px</span>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">曲线率</span>\r\n <input type=\"range\" class=\"ae-round-input\" min=\"0\" max=\"1\" step=\"0.1\" value=\"${curveRate}\" />\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">缩放</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-axis=\"x\">X 缩放</button>\r\n <button class=\"ae-scale-btn\" data-axis=\"y\">Y 缩放</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">3D 旋转</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-axis=\"x-rotate\">X 轴</button>\r\n <button class=\"ae-scale-btn\" data-axis=\"y-rotate\">Y 轴</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">2.5D 挤出</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-up\">上挤出</button>\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-down\">下挤出</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-left\">左挤出</button>\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-right\">右挤出</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-mode=\"reset\">重置</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">2.5D 透视</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-perspective=\"top\">上透视</button>\r\n <button class=\"ae-scale-btn\" data-perspective=\"bottom\">下透视</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-perspective=\"left\">左透视</button>\r\n <button class=\"ae-scale-btn\" data-perspective=\"right\">右透视</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">倾斜</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-skew=\"x-left\">左倾斜</button>\r\n <button class=\"ae-scale-btn\" data-skew=\"x-right\">右倾斜</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-skew=\"y-up\">上倾斜</button>\r\n <button class=\"ae-scale-btn\" data-skew=\"y-down\">下倾斜</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-mode=\"reset\">重置</button>\r\n </div>\r\n </div>\r\n `\r\n\r\n // 颜色选择\r\n const colorInput = this._toolbar.querySelector('.ae-color-input')\r\n colorInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.color = e.target.value\r\n this._defaultColor = e.target.value\r\n this._updateMarkerColor(e.target.value)\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'color', arrow: this.selected, value: e.target.value, arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 粗细调整\r\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\r\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\r\n strokeInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.strokeWidth = parseInt(e.target.value)\r\n strokeValue.textContent = e.target.value + 'px'\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'strokeWidth', arrow: this.selected, value: parseInt(e.target.value), arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 曲线率调整\r\n const roundInput = this._toolbar.querySelector('.ae-round-input')\r\n roundInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.curveRate = parseFloat(e.target.value)\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'curveRate', arrow: this.selected, value: parseFloat(e.target.value), arrows: this.getData() })\r\n }\r\n })\r\n\r\n // X/Y 缩放按钮\r\n const scaleBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-axis]')\r\n scaleBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const axis = e.target.dataset.axis\r\n\r\n // X/Y 轴旋转(3D 透视效果)\r\n if (axis === 'x-rotate') {\r\n this._startRotate3D('x')\r\n return\r\n } else if (axis === 'y-rotate') {\r\n this._startRotate3D('y')\r\n return\r\n }\r\n\r\n // 轴向缩放\r\n this._transformMode = 'scale'\r\n this._transformAxis = axis\r\n this._transformCenter = this._getArrowBBox(this.selected)\r\n this._transformStartPoints = this.selected.points.map(pt => ({ ...pt }))\r\n\r\n // 设置初始鼠标位置\r\n const rect = this._getArrowBBox(this.selected)\r\n if (axis === 'x') {\r\n this._transformStartPos = { x: rect.maxX + 10, y: rect.centerY }\r\n } else {\r\n this._transformStartPos = { x: rect.centerX, y: rect.maxY + 10 }\r\n }\r\n\r\n // 绑定鼠标移动和松开事件\r\n const onMouseMove = (ev) => {\r\n const p = this._mousePos(ev)\r\n if (axis === 'x') {\r\n this._handleScaleX(p)\r\n } else {\r\n this._handleScaleY(p)\r\n }\r\n this.render()\r\n }\r\n\r\n const onMouseUp = () => {\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onMouseUp)\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'scale', arrow: this.selected, arrows: this.getData() })\r\n }\r\n\r\n this._transformMode = null\r\n this._transformAxis = null\r\n }\r\n\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onMouseUp)\r\n })\r\n })\r\n\r\n // 2.5D 视角按钮\r\n const modeBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-mode]')\r\n modeBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const mode = e.target.dataset.mode\r\n if (mode === 'extrude-up') {\r\n this._applyExtrude(0, -15)\r\n } else if (mode === 'extrude-down') {\r\n this._applyExtrude(0, 15)\r\n } else if (mode === 'extrude-left') {\r\n this._applyExtrude(-15, 0)\r\n } else if (mode === 'extrude-right') {\r\n this._applyExtrude(15, 0)\r\n } else if (mode === 'reset') {\r\n this._resetExtrude()\r\n }\r\n })\r\n })\r\n\r\n // 2.5D 透视按钮\r\n const perspectiveBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-perspective]')\r\n perspectiveBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const direction = e.target.dataset.perspective\r\n if (direction === 'top') {\r\n this._applyPerspective('top')\r\n } else if (direction === 'bottom') {\r\n this._applyPerspective('bottom')\r\n } else if (direction === 'left') {\r\n this._applyPerspective('left')\r\n } else if (direction === 'right') {\r\n this._applyPerspective('right')\r\n }\r\n })\r\n })\r\n\r\n // 倾斜按钮\r\n const skewBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-skew]')\r\n skewBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const skewType = e.target.dataset.skew\r\n if (skewType === 'x-left') {\r\n this._applySkew('x-left')\r\n } else if (skewType === 'x-right') {\r\n this._applySkew('x-right')\r\n } else if (skewType === 'y-up') {\r\n this._applySkew('y-up')\r\n } else if (skewType === 'y-down') {\r\n this._applySkew('y-down')\r\n }\r\n })\r\n })\r\n\r\n // 拖拽功能 - 使用类实例绑定\r\n const dragHandle = this._toolbar.querySelector('.ae-toolbar-drag-handle')\r\n this._setupToolbarDrag(dragHandle)\r\n\r\n // 阻止工具条上的事件触发到容器\r\n this._toolbar.addEventListener('mousedown', (e) => {\r\n e.stopPropagation()\r\n })\r\n this._toolbar.addEventListener('mouseup', (e) => {\r\n e.stopPropagation()\r\n })\r\n\r\n // 工具条添加到 body,而不是 container\r\n document.body.appendChild(this._toolbar)\r\n }\r\n\r\n // 工具条拖拽设置\r\n _setupToolbarDrag(dragHandle) {\r\n let isDragging = false\r\n let dragOffset = { x: 0, y: 0 }\r\n\r\n dragHandle.addEventListener('mousedown', (e) => {\r\n isDragging = true\r\n this._toolbarDragging = true\r\n const rect = this._toolbar.getBoundingClientRect()\r\n dragOffset.x = e.clientX - rect.left\r\n dragOffset.y = e.clientY - rect.top\r\n e.preventDefault()\r\n e.stopPropagation()\r\n\r\n const onMove = (moveEvent) => {\r\n if (!isDragging) return\r\n // 直接使用页面坐标,不限制在容器内\r\n let newLeft = moveEvent.clientX - dragOffset.x\r\n let newTop = moveEvent.clientY - dragOffset.y\r\n this._toolbar.style.left = newLeft + 'px'\r\n this._toolbar.style.top = newTop + 'px'\r\n }\r\n\r\n const onUp = (e) => {\r\n isDragging = false\r\n this._toolbarDragging = false\r\n document.removeEventListener('mousemove', onMove)\r\n document.removeEventListener('mouseup', onUp)\r\n this._toolbar.removeEventListener('mouseup', onUp)\r\n\r\n e.preventDefault()\r\n e.stopPropagation()\r\n }\r\n\r\n document.addEventListener('mousemove', onMove)\r\n document.addEventListener('mouseup', onUp)\r\n\r\n this._toolbar.addEventListener('mouseup', onUp)\r\n })\r\n }\r\n\r\n _showToolbar() {\r\n if (this.selected) {\r\n if (!this._toolbar) {\r\n this._createToolbar()\r\n }\r\n this._toolbar.style.display = 'flex'\r\n\r\n // 更新工具条值\r\n const color = this.selected.color || this._defaultColor\r\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\r\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\r\n\r\n const colorInput = this._toolbar.querySelector('.ae-color-input')\r\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\r\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\r\n const roundInput = this._toolbar.querySelector('.ae-round-input')\r\n\r\n if (colorInput) colorInput.value = color\r\n if (strokeInput) {\r\n strokeInput.value = strokeWidth\r\n strokeValue.textContent = strokeWidth + 'px'\r\n }\r\n if (roundInput) roundInput.value = curveRate\r\n\r\n // 定位到所选箭头旁边(使用页面坐标)\r\n const containerRect = this.container.getBoundingClientRect()\r\n const bbox = this._getArrowBBox(this.selected)\r\n const toolbarWidth = this._toolbar.offsetWidth || 150\r\n const toolbarHeight = this._toolbar.offsetHeight || 120\r\n\r\n // 计算位置:放在箭头右侧,如果空间不够则放左侧\r\n let left = containerRect.left + bbox.maxX + 20\r\n if (left + toolbarWidth > window.innerWidth - 10) {\r\n left = containerRect.left + bbox.minX - toolbarWidth - 20\r\n }\r\n\r\n // 垂直居中于箭头\r\n let top = containerRect.top + bbox.centerY - toolbarHeight / 2\r\n if (top < 10) top = 10\r\n if (top + toolbarHeight > window.innerHeight - 10) {\r\n top = window.innerHeight - toolbarHeight - 10\r\n }\r\n\r\n this._toolbar.style.left = left + 'px'\r\n this._toolbar.style.top = top + 'px'\r\n }\r\n }\r\n\r\n _hideToolbar() {\r\n if (this._toolbar) {\r\n this._toolbar.style.display = 'none'\r\n }\r\n }\r\n\r\n _updateMarkerColor(color) {\r\n const marker = this.svg.querySelector('#ae-arrowhead polygon')\r\n if (marker) {\r\n marker.setAttribute('fill', color)\r\n }\r\n }\r\n\r\n _initKeybindings() {\r\n // 创建快捷键实例,绑定到 container 上\r\n this._kb = new Keybinding('arrow-editor-' + Math.random(), this.container)\r\n\r\n // Enter: 完成绘制\r\n this._kb.on('enter', () => {\r\n this._handleEnter()\r\n })\r\n\r\n // Esc: 结束绘制、取消选中\r\n this._kb.on('esc', () => {\r\n this._handleEsc()\r\n })\r\n\r\n // Delete/Backspace: 删除选中的箭头\r\n this._kb.on('delete', () => {\r\n this._handleDelete()\r\n })\r\n\r\n this._kb.on('backspace', () => {\r\n this._handleDelete()\r\n })\r\n\r\n // Space: 绘制中添加点\r\n this._kb.on('space', () => {\r\n this._handleSpace()\r\n })\r\n\r\n // 方向键:选中时微调位置\r\n this._kb.on('arrowup', () => {\r\n this._handleArrowKey(0, -1)\r\n })\r\n\r\n this._kb.on('arrowdown', () => {\r\n this._handleArrowKey(0, 1)\r\n })\r\n\r\n this._kb.on('arrowleft', () => {\r\n this._handleArrowKey(-1, 0)\r\n })\r\n\r\n this._kb.on('arrowright', () => {\r\n this._handleArrowKey(1, 0)\r\n })\r\n }\r\n\r\n // 空格键:绘制中添加点\r\n _handleSpace() {\r\n // 只有正在绘制时才处理\r\n if (!this.drawing || !this.current) return\r\n\r\n // 使用当前鼠标位置添加点\r\n if (this._lastMousePos) {\r\n this.current.points.push({ ...this._lastMousePos })\r\n this.render()\r\n }\r\n }\r\n\r\n // 方向键:选中箭头时微调位置\r\n _handleArrowKey(dx, dy) {\r\n if (!this.selected) return\r\n\r\n const step = 1 // 每次移动 1 像素\r\n this.selected.points.forEach(pt => {\r\n pt.x += dx * step\r\n pt.y += dy * step\r\n })\r\n\r\n this.render()\r\n\r\n // 触发 onChange 回调\r\n if (this.onChange) {\r\n this.onChange({ type: 'move', arrow: this.selected, arrows: this.getData() })\r\n }\r\n }\r\n\r\n _initEvents() {\r\n this.container.onclick = e => {\r\n // 点击工具条时不处理\r\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\r\n return\r\n }\r\n if (this.preventDefault) e.preventDefault()\r\n if (this.stopPropagation) e.stopPropagation()\r\n const p = this._mousePos(e)\r\n this._handleClick(p, e)\r\n }\r\n\r\n this.container.onmousemove = e => {\r\n if (this.preventDefault) e.preventDefault()\r\n if (this.stopPropagation) e.stopPropagation()\r\n const p = this._mousePos(e)\r\n // 记录鼠标位置,用于空格键打点\r\n this._lastMousePos = p\r\n this._handleMouseMove(e, p)\r\n }\r\n\r\n this.container.onmousedown = e => {\r\n // 点击工具条不触发移动\r\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\r\n return\r\n }\r\n\r\n if (this.preventDefault) e.preventDefault()\r\n if (this.stopPropagation) e.stopPropagation()\r\n\r\n if (this.selected) {\r\n const handle = e.target.getAttribute('data-handle')\r\n if (handle) {\r\n this._transformMode = handle === 'scaleX' || handle === 'scaleY' ? 'scale' : handle\r\n this._transformHandle = handle\r\n this._transformAxis = handle === 'scaleX' ? 'x' : (handle === 'scaleY' ? 'y' : null)\r\n const p = this._mousePos(e)\r\n this._transformStartPos = p\r\n this._transformStartPoints = this.selected.points.map(pt => ({ x: pt.x, y: pt.y }))\r\n this._transformCenter = this._getArrowBBox(this.selected)\r\n\r\n if (handle === 'rotate') {\r\n const center = this._transformCenter\r\n const dx = p.x - center.centerX\r\n const dy = p.y - center.centerY\r\n this._transformStartAngle = Math.atan2(dy, dx)\r\n this._rotationOffset = 0\r\n }\r\n\r\n e.stopPropagation()\r\n return\r\n }\r\n\r\n this.mode = 'move'\r\n }\r\n }\r\n\r\n this.container.onmouseup = (e) => {\r\n // 如果有变换操作,调用 onChange 回调\r\n if (this._transformMode && this.selected) {\r\n if (this.onChange) {\r\n this.onChange({ type: this._transformMode, arrow: this.selected, arrows: this.getData() })\r\n }\r\n }\r\n this.mode = null\r\n this._transformMode = null\r\n this._transformHandle = null\r\n this._transformAxis = null\r\n }\r\n }\r\n\r\n _mousePos(e) {\r\n const r = this.container.getBoundingClientRect()\r\n return {\r\n x: e.clientX - r.left,\r\n y: e.clientY - r.top\r\n }\r\n }\r\n\r\n _generatePath(pts, curveRate = 0) {\r\n if (pts.length < 2) return ''\r\n\r\n // curveRate 为 0 时画直线\r\n if (curveRate === 0) {\r\n let d = `M ${pts[0].x} ${pts[0].y}`\r\n for (let i = 1; i < pts.length; i++) {\r\n d += ` L ${pts[i].x} ${pts[i].y}`\r\n }\r\n return d\r\n }\r\n\r\n // 根据曲线率计算控制点位置\r\n // curveRate: 0 - 直线,1 - 最弯曲\r\n let d = `M ${pts[0].x} ${pts[0].y}`\r\n\r\n for (let i = 0; i < pts.length - 1; i++) {\r\n const curr = pts[i]\r\n const next = pts[i + 1]\r\n\r\n // 计算当前线段的向量\r\n const dx = next.x - curr.x\r\n const dy = next.y - curr.y\r\n const len = Math.hypot(dx, dy)\r\n\r\n if (len === 0) continue\r\n\r\n // 计算进入当前点的切线向量(前一段线段)\r\n let inDx = dx\r\n let inDy = dy\r\n\r\n if (i > 0) {\r\n const prev = pts[i - 1]\r\n inDx = curr.x - prev.x\r\n inDy = curr.y - prev.y\r\n }\r\n\r\n // 计算出当前点的切线向量(下一段线段)\r\n let outDx = dx\r\n let outDy = dy\r\n\r\n if (i < pts.length - 2) {\r\n const after = pts[i + 2]\r\n outDx = after.x - next.x\r\n outDy = after.y - next.y\r\n }\r\n\r\n // 单位向量\r\n const inLen = Math.hypot(inDx, inDy) || 1\r\n const outLen = Math.hypot(outDx, outDy) || 1\r\n const uxIn = inDx / inLen\r\n const uyIn = inDy / inLen\r\n const uxOut = outDx / outLen\r\n const uyOut = outDy / outLen\r\n\r\n // 控制点距离:曲线率 * 线段长度 * 系数\r\n const controlDist = len * curveRate * 0.3\r\n\r\n // 第一个控制点:从当前点沿进入方向的切线\r\n const cp1X = curr.x + uxIn * controlDist\r\n const cp1Y = curr.y + uyIn * controlDist\r\n\r\n // 第二个控制点:从下一个点沿出去方向的切线反方向\r\n const cp2X = next.x - uxOut * controlDist\r\n const cp2Y = next.y - uyOut * controlDist\r\n\r\n d += ` C ${cp1X} ${cp1Y} ${cp2X} ${cp2Y} ${next.x} ${next.y}`\r\n }\r\n\r\n return d\r\n }\r\n\r\n _generateArrowHead(pts, strokeWidth = 8) {\r\n if (pts.length < 2) return ''\r\n\r\n const last = pts[pts.length - 1]\r\n let prev = pts[pts.length - 2]\r\n\r\n if (pts.length >= 3) {\r\n const dist = Math.hypot(last.x - prev.x, last.y - prev.y)\r\n if (dist < 5) {\r\n prev = pts[pts.length - 3]\r\n }\r\n }\r\n\r\n const dx = last.x - prev.x\r\n const dy = last.y - prev.y\r\n const len = Math.hypot(dx, dy)\r\n\r\n if (len < 1) return ''\r\n\r\n const ux = dx / len\r\n const uy = dy / len\r\n\r\n // 根据粗细调整箭头大小\r\n const scale = strokeWidth / 8\r\n const arrowLen = 22 * scale\r\n const arrowWidth = 20 * scale\r\n\r\n const lx = last.x\r\n const ly = last.y\r\n\r\n // 箭头往外挪动一半长度,遮住箭身厚度\r\n const offsetX = ux * (arrowLen / 2)\r\n const offsetY = uy * (arrowLen / 2)\r\n\r\n // 箭头尖端(在线段末端往外挪一半)\r\n const tipX = lx + offsetX\r\n const tipY = ly + offsetY\r\n\r\n // 箭头底部中心(往回缩一个箭头长度)\r\n const baseX = lx + offsetX - ux * arrowLen\r\n const baseY = ly + offsetY - uy * arrowLen\r\n\r\n // 垂直方向的单位向量\r\n const px = -uy\r\n const py = ux\r\n\r\n // 底部左右两个角\r\n const leftX = baseX + px * arrowWidth\r\n const leftY = baseY + py * arrowWidth\r\n const rightX = baseX - px * arrowWidth\r\n const rightY = baseY - py * arrowWidth\r\n\r\n // 实心三角形\r\n return `M ${tipX} ${tipY} L ${leftX} ${leftY} L ${rightX} ${rightY} Z`\r\n }\r\n\r\n _createArrowGroup(arrow, index) {\r\n const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')\r\n g.setAttribute('data-index', index)\r\n\r\n const color = arrow.color || this._defaultColor\r\n const strokeWidth = arrow.strokeWidth || this._strokeWidth\r\n const curveRate = arrow.curveRate ?? arrow.cornerRoundness ?? 0\r\n\r\n // 挤出效果(2.5D 阴影层)\r\n const extrude = arrow.extrude || { x: 0, y: 0 }\r\n const extrudeLayers = Math.max(Math.abs(extrude.x), Math.abs(extrude.y))\r\n const hasExtrude = extrudeLayers > 0\r\n\r\n // 绘制挤出阴影层(从后往前)\r\n if (hasExtrude) {\r\n const stepX = extrude.x > 0 ? 1 : -1\r\n const stepY = extrude.y > 0 ? 1 : -1\r\n const layers = Math.max(Math.abs(extrude.x), Math.abs(extrude.y))\r\n\r\n for (let i = 1; i <= layers; i++) {\r\n const offsetX = stepX * i\r\n const offsetY = stepY * i\r\n\r\n // 阴影层路径\r\n const shadowPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n shadowPath.setAttribute('class', 'ae-arrow-path')\r\n shadowPath.style.stroke = '#ccc'\r\n shadowPath.style.strokeWidth = strokeWidth + 'px'\r\n shadowPath.style.opacity = '0.15'\r\n shadowPath.setAttribute('d', this._generatePath(arrow.points.map(pt => ({\r\n x: pt.x + offsetX,\r\n y: pt.y + offsetY\r\n })), curveRate))\r\n g.appendChild(shadowPath)\r\n\r\n // 阴影层箭头\r\n const shadowArrowHead = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n shadowArrowHead.setAttribute('fill', '#ccc')\r\n shadowArrowHead.setAttribute('fill-opacity', '0.15')\r\n shadowArrowHead.setAttribute('d', this._generateArrowHead(arrow.points.map(pt => ({\r\n x: pt.x + offsetX,\r\n y: pt.y + offsetY\r\n })), strokeWidth))\r\n g.appendChild(shadowArrowHead)\r\n }\r\n }\r\n\r\n // 绘制主箭头(箭身路径)\r\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n path.setAttribute('class', 'ae-arrow-path')\r\n path.style.stroke = color\r\n path.style.strokeWidth = strokeWidth + 'px'\r\n path.setAttribute('d', this._generatePath(arrow.points, curveRate))\r\n g.appendChild(path)\r\n\r\n // 绘制主箭头(箭头头部)\r\n const arrowHead = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n arrowHead.setAttribute('fill', color)\r\n arrowHead.setAttribute('d', this._generateArrowHead(arrow.points, strokeWidth))\r\n g.appendChild(arrowHead)\r\n\r\n if (arrow === this.selected) {\r\n const bbox = this._getArrowBBox(arrow)\r\n\r\n // 变换框\r\n const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')\r\n rect.setAttribute('class', 'ae-transform-box')\r\n rect.setAttribute('x', bbox.minX - 10)\r\n rect.setAttribute('y', bbox.minY - 10)\r\n rect.setAttribute('width', bbox.width + 20)\r\n rect.setAttribute('height', bbox.height + 20)\r\n g.appendChild(rect)\r\n\r\n // 缩放手柄(右下角)\r\n const scaleHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n scaleHandle.setAttribute('class', 'ae-transform-handle')\r\n scaleHandle.setAttribute('cx', bbox.maxX + 10)\r\n scaleHandle.setAttribute('cy', bbox.maxY + 10)\r\n scaleHandle.setAttribute('r', 6)\r\n scaleHandle.setAttribute('data-handle', 'scale')\r\n g.appendChild(scaleHandle)\r\n\r\n // X 方向缩放手柄(右边中间)\r\n const scaleXHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n scaleXHandle.setAttribute('class', 'ae-transform-handle')\r\n scaleXHandle.setAttribute('cx', bbox.maxX + 10)\r\n scaleXHandle.setAttribute('cy', bbox.centerY)\r\n scaleXHandle.setAttribute('r', 6)\r\n scaleXHandle.setAttribute('data-handle', 'scaleX')\r\n g.appendChild(scaleXHandle)\r\n\r\n // Y 方向缩放手柄(底部中间)\r\n const scaleYHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n scaleYHandle.setAttribute('class', 'ae-transform-handle')\r\n scaleYHandle.setAttribute('cx', bbox.centerX)\r\n scaleYHandle.setAttribute('cy', bbox.maxY + 10)\r\n scaleYHandle.setAttribute('r', 6)\r\n scaleYHandle.setAttribute('data-handle', 'scaleY')\r\n g.appendChild(scaleYHandle)\r\n\r\n // 旋转手柄(顶部中间)\r\n const rotateY = bbox.minY - 30\r\n const rotateX = bbox.centerX\r\n const rotateLine = document.createElementNS('http://www.w3.org/2000/svg', 'line')\r\n rotateLine.setAttribute('class', 'ae-rotate-line')\r\n rotateLine.setAttribute('x1', bbox.centerX)\r\n rotateLine.setAttribute('y1', bbox.minY - 10)\r\n rotateLine.setAttribute('x2', rotateX)\r\n rotateLine.setAttribute('y2', rotateY)\r\n g.appendChild(rotateLine)\r\n\r\n const rotateHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n rotateHandle.setAttribute('class', 'ae-rotate-handle')\r\n rotateHandle.setAttribute('cx', rotateX)\r\n rotateHandle.setAttribute('cy', rotateY)\r\n rotateHandle.setAttribute('r', 8)\r\n rotateHandle.setAttribute('data-handle', 'rotate')\r\n g.appendChild(rotateHandle)\r\n }\r\n\r\n return g\r\n }\r\n\r\n render() {\r\n this.svg.querySelectorAll('g').forEach(g => g.remove())\r\n\r\n this.arrows.forEach((arrow, index) => {\r\n const g = this._createArrowGroup(arrow, index)\r\n this.svg.appendChild(g)\r\n })\r\n\r\n if (this.current) {\r\n const g = this._createArrowGroup(this.current, this.arrows.length)\r\n this.svg.appendChild(g)\r\n }\r\n }\r\n\r\n _isDoubleClick(p) {\r\n const now = Date.now()\r\n const dt = now - this.lastClickTime\r\n this.lastClickTime = now\r\n\r\n if (dt < 300 && this.lastClickPos && Math.hypot(p.x - this.lastClickPos.x, p.y - this.lastClickPos.y) < 10) {\r\n this.lastClickPos = null\r\n return true\r\n }\r\n\r\n this.lastClickPos = p\r\n return false\r\n }\r\n\r\n _handleClick(p, e) {\r\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\r\n if (this.isCtrl && !e.ctrlKey) {\r\n return\r\n }\r\n\r\n // 如果刚才有拖拽,阻止点击事件\r\n if (this._shouldBlockClick) {\r\n this._shouldBlockClick = false\r\n return\r\n }\r\n\r\n if (this._isDoubleClick(p)) {\r\n if (this.drawing && this.current && this.current.points.length >= 2) {\r\n this.drawing = false\r\n this.arrows.push(this.current)\r\n const arrow = this.current\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n this.render()\r\n if (this.onDrawEnd) {\r\n this.onDrawEnd({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n return\r\n }\r\n\r\n // 有选中的箭头时,点击空白处取消选中\r\n if (this.selected) {\r\n for (const a of this.arrows) {\r\n if (this._hitArrow(a, p)) {\r\n this.render()\r\n return\r\n }\r\n }\r\n // 点击空白处,取消选中\r\n this.selected = null\r\n this._hideToolbar()\r\n this.render()\r\n return\r\n }\r\n\r\n // 没有选中时,检查是否点击到箭头\r\n for (const a of this.arrows) {\r\n if (this._hitArrow(a, p)) {\r\n this.selected = a\r\n this._showToolbar()\r\n this.render()\r\n return\r\n }\r\n }\r\n\r\n // 点击空白处\r\n if (this.drawing) {\r\n // 正在绘制中,添加点\r\n this.current.points.push(p)\r\n } else {\r\n // 开始绘制\r\n this.drawing = true\r\n this.current = {\r\n points: [p, p],\r\n color: this._defaultColor\r\n }\r\n // 添加 fixed 类,让 SVG 固定定位覆盖整个视口\r\n this.svg.classList.add('ae-d2-svg-fixed')\r\n }\r\n\r\n this.render()\r\n }\r\n\r\n _handleEnter() {\r\n // 正在绘制时,按 Enter 完成绘制\r\n if (this.drawing && this.current && this.current.points.length >= 2) {\r\n this.drawing = false\r\n this.arrows.push(this.current)\r\n const arrow = this.current\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n this.render()\r\n if (this.onDrawEnd) {\r\n this.onDrawEnd({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n }\r\n\r\n _handleEsc() {\r\n // 按 Esc: 结束绘制、取消选中\r\n if (this.drawing) {\r\n this.drawing = false\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n }\r\n if (this.selected) {\r\n this.selected = null\r\n }\r\n this._hideColorPicker()\r\n this._hideToolbar()\r\n this.render()\r\n }\r\n\r\n _handleDelete() {\r\n // 删除选中的箭头\r\n if (this.selected) {\r\n const arrow = this.selected\r\n const index = this.arrows.indexOf(this.selected)\r\n if (index > -1) {\r\n this.arrows.splice(index, 1)\r\n }\r\n this.selected = null\r\n this._hideToolbar()\r\n this.render()\r\n if (this.onRemove) {\r\n this.onRemove({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n }\r\n\r\n _showColorPicker(e) {\r\n if (this._showingColorPicker) {\r\n this._hideColorPicker()\r\n return\r\n }\r\n\r\n this._showingColorPicker = true\r\n\r\n // 创建颜色选择器浮窗\r\n const popup = document.createElement('div')\r\n popup.className = 'ae-color-picker-popup'\r\n\r\n const label = document.createElement('span')\r\n label.textContent = '选择颜色'\r\n label.style.cssText = 'font-size: 12px; color: #666;'\r\n\r\n const colorInput = document.createElement('input')\r\n colorInput.type = 'color'\r\n colorInput.value = this.selected.color || this._defaultColor\r\n // 自动打开颜色选择器\r\n colorInput.showPicker()\r\n\r\n popup.appendChild(label)\r\n popup.appendChild(colorInput)\r\n\r\n // 定位到颜色手柄位置\r\n const rect = this.container.getBoundingClientRect()\r\n const bbox = this._getArrowBBox(this.selected)\r\n const x = rect.left + bbox.minX - 50\r\n const y = rect.top + bbox.maxY + 15\r\n\r\n popup.style.left = x + 'px'\r\n popup.style.top = y + 'px'\r\n\r\n // 颜色改变时实时更新\r\n colorInput.addEventListener('input', (ev) => {\r\n this.selected.color = ev.target.value\r\n this._defaultColor = ev.target.value\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'color', arrow: this.selected, value: ev.target.value, arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 点击外部关闭\r\n const closeHandler = (ev) => {\r\n if (!popup.contains(ev.target)) {\r\n this._hideColorPicker()\r\n document.removeEventListener('click', closeHandler)\r\n }\r\n }\r\n\r\n document.body.appendChild(popup)\r\n this._colorPickerPopup = popup\r\n\r\n document.addEventListener('click', closeHandler)\r\n }\r\n\r\n _hideColorPicker() {\r\n if (this._colorPickerPopup) {\r\n this._colorPickerPopup.remove()\r\n this._colorPickerPopup = null\r\n }\r\n this._showingColorPicker = false\r\n }\r\n\r\n // 删除选中的箭头\r\n deleteSelected() {\r\n if (this.selected) {\r\n this.arrows = this.arrows.filter(a => a !== this.selected)\r\n this.selected = null\r\n this.render()\r\n }\r\n }\r\n\r\n _handleMouseMove(e, p) {\r\n // 如果正在拖拽工具条,不处理\r\n if (this._toolbarDragging) {\r\n return\r\n }\r\n\r\n // 如果鼠标在工具条上,不处理\r\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\r\n return\r\n }\r\n\r\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\r\n if (this.isCtrl && !e.ctrlKey) {\r\n // 如果正在绘制中,按 Ctrl 键松开则结束绘制\r\n if (this.drawing && this.current && this.current.points.length >= 2) {\r\n this.drawing = false\r\n this.arrows.push(this.current)\r\n const arrow = this.current\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n this.render()\r\n if (this.onDrawEnd) {\r\n this.onDrawEnd({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n return\r\n }\r\n\r\n if (this.drawing) {\r\n this.current.points[this.current.points.length - 1] = p\r\n this.render()\r\n }\r\n\r\n // 变换处理(旋转/缩放)\r\n if (this._transformMode && this.selected) {\r\n if (this._transformMode === 'rotate') {\r\n this._handleRotate(p)\r\n } else if (this._transformMode === 'scale') {\r\n // 根据轴向选择处理方式\r\n if (this._transformAxis === 'x') {\r\n this._handleScaleX(p)\r\n } else if (this._transformAxis === 'y') {\r\n this._handleScaleY(p)\r\n } else {\r\n this._handleScale(p)\r\n }\r\n } else if (this._transformMode === 'rotate3d') {\r\n this._handleRotate3D(p)\r\n }\r\n this.render()\r\n return\r\n }\r\n\r\n if (this.selected && this.mode === 'move') {\r\n const dx = e.movementX\r\n const dy = e.movementY\r\n\r\n // 如果有移动,标记需要阻止点击\r\n if (dx !== 0 || dy !== 0) {\r\n this._shouldBlockClick = true\r\n }\r\n\r\n this.selected.points.forEach(pt => {\r\n pt.x += dx\r\n pt.y += dy\r\n })\r\n\r\n this.render()\r\n }\r\n }\r\n\r\n _getArrowBBox(arrow) {\r\n const points = arrow.points\r\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity\r\n\r\n for (const pt of points) {\r\n minX = Math.min(minX, pt.x)\r\n minY = Math.min(minY, pt.y)\r\n maxX = Math.max(maxX, pt.x)\r\n maxY = Math.max(maxY, pt.y)\r\n }\r\n\r\n return {\r\n minX,\r\n minY,\r\n maxX,\r\n maxY,\r\n width: maxX - minX,\r\n height: maxY - minY,\r\n centerX: (minX + maxX) / 2,\r\n centerY: (minY + maxY) / 2\r\n }\r\n }\r\n\r\n _handleRotate(p) {\r\n const center = this._transformCenter\r\n const centerX = center.centerX\r\n const centerY = center.centerY\r\n\r\n // 计算当前角度和起始角度\r\n const currentAngle = Math.atan2(p.y - centerY, p.x - centerX)\r\n const startAngle = Math.atan2(this._transformStartPos.y - centerY, this._transformStartPos.x - centerX)\r\n const angleDiff = currentAngle - startAngle\r\n\r\n // 旋转点\r\n const cos = Math.cos(angleDiff)\r\n const sin = Math.sin(angleDiff)\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n const relX = this._transformStartPoints[i].x - centerX\r\n const relY = this._transformStartPoints[i].y - centerY\r\n pt.x = centerX + relX * cos - relY * sin\r\n pt.y = centerY + relX * sin + relY * cos\r\n })\r\n }\r\n\r\n _handleScale(p) {\r\n const center = this._transformCenter\r\n const centerX = center.centerX\r\n const centerY = center.centerY\r\n const startPoints = this._transformStartPoints\r\n const startPos = this._transformStartPos\r\n\r\n // 计算缩放比例\r\n const dx = p.x - centerX\r\n const dy = p.y - centerY\r\n const startDx = startPos.x - centerX\r\n const startDy = startPos.y - centerY\r\n\r\n const currentDist = Math.hypot(dx, dy)\r\n const startDist = Math.hypot(startDx, startDy)\r\n const scale = currentDist / startDist\r\n\r\n // 应用缩放\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = centerX + (startPoints[i].x - centerX) * scale\r\n pt.y = centerY + (startPoints[i].y - centerY) * scale\r\n })\r\n }\r\n\r\n // X 方向缩放\r\n _handleScaleX(p) {\r\n const center = this._transformCenter\r\n const centerX = center.centerX\r\n const startPoints = this._transformStartPoints\r\n const startPos = this._transformStartPos\r\n\r\n // 计算 X 方向缩放比例\r\n const currentDx = p.x - centerX\r\n const startDx = startPos.x - centerX\r\n const scaleX = startDx !== 0 ? currentDx / startDx : 1\r\n\r\n // 应用 X 方向缩放\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = centerX + (startPoints[i].x - centerX) * scaleX\r\n pt.y = startPoints[i].y // Y 不变\r\n })\r\n }\r\n\r\n // Y 方向缩放\r\n _handleScaleY(p) {\r\n const center = this._transformCenter\r\n const centerY = center.centerY\r\n const startPoints = this._transformStartPoints\r\n const startPos = this._transformStartPos\r\n\r\n // 计算 Y 方向缩放比例\r\n const currentDy = p.y - centerY\r\n const startDy = startPos.y - centerY\r\n const scaleY = startDy !== 0 ? currentDy / startDy : 1\r\n\r\n // 应用 Y 方向缩放\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = startPoints[i].x // X 不变\r\n pt.y = centerY + (startPoints[i].y - centerY) * scaleY\r\n })\r\n }\r\n\r\n // 开始 3D 旋转(X 轴或 Y 轴)\r\n _startRotate3D(axis) {\r\n if (!this.selected) return\r\n\r\n this._transformMode = 'rotate3d'\r\n this._transformAxis = axis // 'x' or 'y'\r\n this._transformCenter = this._getArrowBBox(this.selected)\r\n this._transformStartPoints = this.selected.points.map(pt => ({ ...pt }))\r\n this._rotation3DStartAngle = axis === 'x' ? 0 : 0\r\n\r\n // 设置初始鼠标位置\r\n const rect = this._getArrowBBox(this.selected)\r\n if (axis === 'x') {\r\n this._transformStartPos = { x: rect.maxX + 50, y: rect.centerY }\r\n } else {\r\n this._transformStartPos = { x: rect.centerX, y: rect.maxY + 50 }\r\n }\r\n\r\n // 绑定鼠标移动和松开事件\r\n const onMouseMove = (e) => {\r\n const p = this._mousePos(e)\r\n this._handleRotate3D(p)\r\n this.render()\r\n }\r\n\r\n const onMouseUp = () => {\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onMouseUp)\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'rotate3d', arrow: this.selected, value: axis, arrows: this.getData() })\r\n }\r\n\r\n this._transformMode = null\r\n this._transformAxis = null\r\n }\r\n\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onMouseUp)\r\n }\r\n\r\n // 处理 3D 旋转(使用余弦模拟透视效果)\r\n _handleRotate3D(p) {\r\n const center = this._transformCenter\r\n const startPoints = this._transformStartPoints\r\n const axis = this._transformAxis\r\n\r\n if (axis === 'x') {\r\n // X 轴旋转:上下拖动,改变 Y 坐标的缩放(cos 效果)\r\n const deltaY = p.y - this._transformStartPos.y\r\n const angle = Math.max(-90, Math.min(90, -deltaY * 0.9)) // -90 到 90 度\r\n const scale = Math.cos(angle * Math.PI / 180)\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = startPoints[i].x // X 不变\r\n // Y 坐标根据旋转角度缩放,模拟 3D 效果\r\n pt.y = center.centerY + (startPoints[i].y - center.centerY) * scale\r\n })\r\n } else {\r\n // Y 轴旋转:左右拖动,改变 X 坐标的缩放(cos 效果)\r\n const deltaX = p.x - this._transformStartPos.x\r\n const angle = Math.max(-90, Math.min(90, deltaX * 0.9)) // -90 到 90 度\r\n const scale = Math.cos(angle * Math.PI / 180)\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n // X 坐标根据旋转角度缩放,模拟 3D 效果\r\n pt.x = center.centerX + (startPoints[i].x - center.centerX) * scale\r\n pt.y = startPoints[i].y // Y 不变\r\n })\r\n }\r\n }\r\n\r\n // 应用 2.5D 挤出效果\r\n _applyExtrude(dx, dy) {\r\n if (!this.selected) return\r\n\r\n // 保存原始点(如果还没保存)\r\n if (!this._originalPoints) {\r\n this._originalPoints = this.selected.points.map(pt => ({ ...pt }))\r\n }\r\n\r\n // 设置挤出参数\r\n this.selected.extrude = { x: dx, y: dy }\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'extrude', arrow: this.selected, value: { x: dx, y: dy }, arrows: this.getData() })\r\n }\r\n }\r\n\r\n // 应用倾斜变换(Skew)\r\n _applySkew(type) {\r\n if (!this.selected) return\r\n\r\n const bbox = this._getArrowBBox(this.selected)\r\n const centerX = bbox.centerX\r\n const centerY = bbox.centerY\r\n\r\n // 保存原始点(如果还没保存)\r\n if (!this._originalPoints) {\r\n this._originalPoints = this.selected.points.map(pt => ({ ...pt }))\r\n }\r\n\r\n // 倾斜强度(像素偏移量)\r\n const skewAmount = 0.3\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n const origPt = this._originalPoints[i]\r\n\r\n if (type === 'x-left') {\r\n // 左倾斜:X 轴负方向倾斜,Y 值越小(越靠上)X 偏移越大\r\n const distFromCenterY = origPt.y - centerY\r\n const totalHeight = bbox.height || 1\r\n const factor = (distFromCenterY / totalHeight) * skewAmount * totalHeight\r\n pt.x = origPt.x - factor\r\n pt.y = origPt.y\r\n } else if (type === 'x-right') {\r\n // 右倾斜:X 轴正方向倾斜\r\n const distFromCenterY = origPt.y - centerY\r\n const totalHeight = bbox.height || 1\r\n const factor = (distFromCenterY / totalHeight) * skewAmount * totalHeight\r\n pt.x = origPt.x + factor\r\n pt.y = origPt.y\r\n } else if (type === 'y-up') {\r\n // 上倾斜:Y 轴负方向倾斜,X 值越小(越靠左)Y 偏移越大\r\n const distFromCenterX = origPt.x - centerX\r\n const totalWidth = bbox.width || 1\r\n const factor = (distFromCenterX / totalWidth) * skewAmount * totalWidth\r\n pt.x = origPt.x\r\n pt.y = origPt.y - factor\r\n } else if (type === 'y-down') {\r\n // 下倾斜:Y 轴正方向倾斜\r\n const distFromCenterX = origPt.x - centerX\r\n const totalWidth = bbox.width || 1\r\n const factor = (distFromCenterX / totalWidth) * skewAmount * totalWidth\r\n pt.x = origPt.x\r\n pt.y = origPt.y + factor\r\n }\r\n })\r\n\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'skew', arrow: this.selected, value: type, arrows: this.getData() })\r\n }\r\n }\r\n\r\n // 应用透视变换(近大远小效果)\r\n _applyPerspective(direction) {\r\n if (!this.selected) return\r\n\r\n const bbox = this._getArrowBBox(this.selected)\r\n const centerX = bbox.centerX\r\n const centerY = bbox.centerY\r\n\r\n // 保存原始点(如果还没保存)\r\n if (!this._originalPoints) {\r\n this._originalPoints = this.selected.points.map(pt => ({ ...pt }))\r\n }\r\n\r\n // 透视参数\r\n const perspectiveStrength = 0.3 // 透视强度\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n const origPt = this._originalPoints[i]\r\n\r\n if (direction === 'top') {\r\n // 上透视:上方缩小,下方放大(灭点在上方)\r\n const distFromTop = origPt.y - bbox.minY\r\n const totalHeight = bbox.height || 1\r\n const factor = 1 - (1 - distFromTop / totalHeight) * perspectiveStrength\r\n pt.x = centerX + (origPt.x - centerX) * factor\r\n pt.y = origPt.y\r\n } else if (direction === 'bottom') {\r\n // 下透视:下方缩小,上方放大(灭点在下方)\r\n const distFromBottom = bbox.maxY - origPt.y\r\n const totalHeight = bbox.height || 1\r\n const factor = 1 - (1 - distFromBottom / totalHeight) * perspectiveStrength\r\n pt.x = centerX + (origPt.x - centerX) * factor\r\n pt.y = origPt.y\r\n } else if (direction === 'left') {\r\n // 左透视:左方缩小,右方放大(灭点在左方)\r\n const distFromLeft = origPt.x - bbox.minX\r\n const totalWidth = bbox.width || 1\r\n const factor = 1 - (1 - distFromLeft / totalWidth) * perspectiveStrength\r\n pt.x = origPt.x\r\n pt.y = centerY + (origPt.y - centerY) * factor\r\n } else if (direction === 'right') {\r\n // 右透视:右方缩小,左方放大(灭点在右方)\r\n const distFromRight = bbox.maxX - origPt.x\r\n const totalWidth = bbox.width || 1\r\n const factor = 1 - (1 - distFromRight / totalWidth) * perspectiveStrength\r\n pt.x = origPt.x\r\n pt.y = centerY + (origPt.y - centerY) * factor\r\n }\r\n })\r\n\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'perspective', arrow: this.selected, value: direction, arrows: this.getData() })\r\n }\r\n }\r\n\r\n // 重置挤出效果\r\n _resetExtrude() {\r\n if (!this.selected) return\r\n\r\n // 清除挤出参数\r\n this.selected.extrude = null\r\n this._originalPoints = null\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'reset', arrow: this.selected, arrows: this.getData() })\r\n }\r\n }\r\n\r\n _hitArrow(a, p) {\r\n for (let i = 0; i < a.points.length - 1; i++) {\r\n if (this._dist(p, a.points[i], a.points[i + 1]) < 15)\r\n return true\r\n }\r\n return false\r\n }\r\n\r\n _dist(p, a, b) {\r\n const dx = b.x - a.x\r\n const dy = b.y - a.y\r\n const t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy)\r\n const tt = Math.max(0, Math.min(1, t))\r\n const px = a.x + tt * dx\r\n const py = a.y + tt * dy\r\n return Math.hypot(p.x - px, p.y - py)\r\n }\r\n\r\n // 获取所有箭头数据\r\n getData() {\r\n return this.arrows.map(arrow => ({\r\n points: arrow.points,\r\n curveRate: arrow.curveRate ?? arrow.cornerRoundness ?? 0,\r\n strokeWidth: arrow.strokeWidth,\r\n color: arrow.color\r\n }))\r\n }\r\n\r\n // 设置箭头数据\r\n setData(data) {\r\n this.arrows = data.map(item => ({\r\n points: item.points,\r\n curveRate: item.curveRate ?? 0,\r\n strokeWidth: item.strokeWidth ?? 8,\r\n color: item.color\r\n }))\r\n this.render()\r\n }\r\n\r\n // 清空所有箭头\r\n clear() {\r\n this.arrows = []\r\n this.drawing = false\r\n this.current = null\r\n this.selected = null\r\n this.render()\r\n }\r\n\r\n // 销毁编辑器,移除所有事件和元素\r\n destroy() {\r\n // 销毁键盘绑定\r\n if (this._kb && this._kb.destroy) {\r\n this._kb.destroy()\r\n }\r\n\r\n // 移除容器上的事件\r\n this.container.onclick = null\r\n this.container.onmousemove = null\r\n this.container.onmousedown = null\r\n this.container.onmouseup = null\r\n this.container.ondblclick = null\r\n\r\n // 移除 SVG 元素\r\n if (this.svg) {\r\n this.svg.remove()\r\n this.svg = null\r\n }\r\n\r\n // 移除工具条\r\n if (this._toolbar) {\r\n this._toolbar.remove()\r\n this._toolbar = null\r\n }\r\n\r\n // 移除颜色选择器\r\n if (this._colorPickerPopup) {\r\n this._colorPickerPopup.remove()\r\n this._colorPickerPopup = null\r\n }\r\n\r\n // 清空数据\r\n this.arrows = []\r\n this.drawing = false\r\n this.current = null\r\n this.selected = null\r\n this.mode = null\r\n this._transformMode = null\r\n this._transformHandle = null\r\n this._originalPoints = null\r\n }\r\n}\r\n"],"names":["document","styleEl","createElement","textContent","head","appendChild","constructor","container","options","this","querySelector","svg","arrows","drawing","current","selected","mode","lastClickTime","lastClickPos","_shouldBlockClick","_defaultColor","isCtrl","stopPropagation","preventDefault","onDrawEnd","onRemove","onChange","defaultColor","_strokeWidth","defaultStrokeWidth","_curveRate","_a","defaultCurveRate","_transformMode","_transformHandle","_transformStartPos","_transformStartPoints","_transformCenter","_transformStartAngle","_rotationOffset","_toolbar","_lastMousePos","_createSVG","_initKeybindings","_initEvents","getComputedStyle","position","style","createElementNS","setAttribute","defs","marker","polygon","_createToolbar","remove","className","color","strokeWidth","curveRate","_b","cornerRoundness","innerHTML","addEventListener","e","target","value","_updateMarkerColor","render","type","arrow","getData","strokeInput","strokeValue","parseInt","parseFloat","querySelectorAll","forEach","btn","axis","dataset","_startRotate3D","_transformAxis","_getArrowBBox","points","map","pt","__spreadValues","rect","x","maxX","y","centerY","centerX","maxY","onMouseMove","ev","p","_mousePos","_handleScaleX","_handleScaleY","onMouseUp","removeEventListener","_applyExtrude","_resetExtrude","direction","perspective","_applyPerspective","skewType","skew","_applySkew","dragHandle","_setupToolbarDrag","body","isDragging","dragOffset","_toolbarDragging","getBoundingClientRect","clientX","left","clientY","top","onMove","moveEvent","newLeft","newTop","onUp","_showToolbar","display","colorInput","roundInput","containerRect","bbox","toolbarWidth","offsetWidth","toolbarHeight","offsetHeight","window","innerWidth","minX","innerHeight","_hideToolbar","_kb","Keybinding","Math","random","on","_handleEnter","_handleEsc","_handleDelete","_handleSpace","_handleArrowKey","push","dx","dy","onclick","contains","_handleClick","onmousemove","_handleMouseMove","onmousedown","handle","getAttribute","center","atan2","onmouseup","r","_generatePath","pts","length","d","i","curr","next","len","hypot","inDx","inDy","prev","outDx","outDy","after","inLen","outLen","uxIn","uyIn","uxOut","uyOut","controlDist","_generateArrowHead","last","ux","uy","scale","arrowLen","arrowWidth","lx","ly","offsetX","offsetY","baseX","baseY","px","_createArrowGroup","index","g","extrude","max","abs","stepX","stepY","layers","shadowPath","stroke","opacity","shadowArrowHead","path","arrowHead","minY","width","height","scaleHandle","scaleXHandle","scaleYHandle","rotateY","rotateX","rotateLine","rotateHandle","_isDoubleClick","now","Date","dt","ctrlKey","classList","a","_hitArrow","add","_hideColorPicker","indexOf","splice","_showColorPicker","_showingColorPicker","popup","label","cssText","showPicker","closeHandler","_colorPickerPopup","deleteSelected","filter","_handleRotate","_handleScale","_handleRotate3D","movementX","movementY","Infinity","min","angleDiff","cos","sin","relX","relY","startPoints","startPos","startDx","startDy","currentDx","scaleX","currentDy","scaleY","_rotation3DStartAngle","deltaY","angle","PI","deltaX","_originalPoints","skewAmount","origPt","distFromCenterY","totalHeight","factor","distFromCenterX","totalWidth","perspectiveStrength","_dist","b","t","tt","py","setData","data","item","clear","destroy","ondblclick"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bundle.cjs.js","sources":["../src/editor.js"],"sourcesContent":["import { Keybinding } from '@wbiokr/keybinding'\r\n\r\n// 样式注入\r\nconst STYLES = `\r\n.ae-d2-container {\r\n position: relative;\r\n width: 1000px;\r\n height: 600px;\r\n background: #fff;\r\n margin: auto;\r\n}\r\n\r\n.ae-d2-svg {\r\n width: 100%;\r\n height: 100%;\r\n position: absolute;\r\n left: 0;\r\n top: 0;\r\n z-index: 10;\r\n}\r\n\r\n\r\n.ae-arrow-path {\r\n fill: none;\r\n stroke-linejoin: round;\r\n cursor: pointer;\r\n}\r\n\r\n.ae-arrow-path:hover {\r\n stroke: #00aaff;\r\n}\r\n\r\n.ae-transform-box {\r\n fill: none;\r\n stroke: #00aaff;\r\n stroke-width: 2;\r\n stroke-dasharray: 4;\r\n}\r\n\r\n.ae-transform-handle {\r\n fill: #fff;\r\n stroke: #00aaff;\r\n stroke-width: 2;\r\n cursor: pointer;\r\n}\r\n\r\n.ae-transform-handle:hover {\r\n fill: #00aaff;\r\n}\r\n\r\n.ae-rotate-handle {\r\n fill: #fff;\r\n stroke: #ff6600;\r\n stroke-width: 2;\r\n cursor: grab;\r\n}\r\n\r\n.ae-rotate-handle:hover {\r\n fill: #ff6600;\r\n}\r\n\r\n.ae-rotate-line {\r\n stroke: #ff6600;\r\n stroke-width: 1;\r\n stroke-dasharray: 4;\r\n}\r\n\r\n/* 工具条样式 */\r\n.ae-toolbar {\r\n position: fixed;\r\n display: none;\r\n flex-direction: column;\r\n gap: 10px;\r\n padding: 12px;\r\n background: #fff;\r\n border: 1px solid #ddd;\r\n border-radius: 8px;\r\n box-shadow: 0 2px 12px rgba(0,0,0,0.15);\r\n z-index: 10000;\r\n pointer-events: auto;\r\n min-width: 140px;\r\n}\r\n\r\n.ae-toolbar-drag-handle {\r\n cursor: grab;\r\n text-align: center;\r\n padding: 4px;\r\n color: #999;\r\n font-size: 14px;\r\n line-height: 1;\r\n user-select: none;\r\n border-bottom: 1px solid #eee;\r\n margin: -12px -12px 8px -12px;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n border-radius: 8px 8px 0 0;\r\n}\r\n\r\n.ae-toolbar-drag-handle:active {\r\n cursor: grabbing;\r\n}\r\n\r\n.ae-toolbar-item {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n}\r\n\r\n.ae-toolbar-row {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.ae-toolbar-label {\r\n font-size: 11px;\r\n color: #666;\r\n}\r\n\r\n.ae-scale-btn {\r\n flex: 1;\r\n padding: 6px 8px;\r\n background: #f0f0f0;\r\n color: #333;\r\n border: 1px solid #ccc;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 11px;\r\n transition: background 0.2s;\r\n}\r\n\r\n.ae-scale-btn:hover {\r\n background: #e0e0e0;\r\n}\r\n\r\n.ae-scale-btn:active {\r\n background: #d0d0d0;\r\n}\r\n\r\n.ae-toolbar input[type=\"color\"] {\r\n width: 40px;\r\n height: 30px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n padding: 0;\r\n background: none;\r\n}\r\n\r\n.ae-toolbar input[type=\"range\"] {\r\n width: 120px;\r\n cursor: pointer;\r\n}\r\n\r\n.ae-toolbar-value {\r\n font-size: 10px;\r\n color: #999;\r\n text-align: right;\r\n}\r\n`\r\n\r\n// 注入样式\r\nif (typeof document !== 'undefined') {\r\n const styleEl = document.createElement('style')\r\n styleEl.textContent = STYLES\r\n document.head.appendChild(styleEl)\r\n}\r\n\r\nexport class ArrowEditor {\r\n\r\n constructor(container, options = {}) {\r\n this.container = typeof container === 'string' ? document.querySelector(container) : container\r\n this.svg = null\r\n\r\n this.arrows = []\r\n this.drawing = false\r\n this.current = null\r\n this.selected = null\r\n this.mode = null\r\n this.lastClickTime = 0\r\n this.lastClickPos = null\r\n this._shouldBlockClick = false\r\n this._defaultColor = '#2b8cff'\r\n\r\n // 配置选项\r\n this.isCtrl = options.isCtrl || false\r\n this.stopPropagation = options.stopPropagation || false\r\n this.preventDefault = options.preventDefault || false\r\n this.onDrawEnd = options.onDrawEnd || null\r\n this.onRemove = options.onRemove || null\r\n this.onChange = options.onChange || null\r\n\r\n // 默认样式\r\n this._defaultColor = options.defaultColor || this._defaultColor\r\n this._strokeWidth = options.defaultStrokeWidth || 8\r\n this._curveRate = options.defaultCurveRate ?? 0\r\n this._arrowLength = options.defaultArrowLength ?? 22\r\n this._arrowWidth = options.defaultArrowWidth ?? 20\r\n\r\n // 变换相关\r\n this._transformMode = null // 'rotate' | 'scale'\r\n this._transformHandle = null\r\n this._transformStartPos = null\r\n this._transformStartPoints = null\r\n this._transformCenter = null\r\n this._transformStartAngle = null\r\n this._rotationOffset = 0\r\n\r\n // 工具条相关\r\n this._toolbar = null\r\n\r\n // 记录鼠标位置,用于空格键打点\r\n this._lastMousePos = null\r\n\r\n this._createSVG()\r\n this._initKeybindings()\r\n this._initEvents()\r\n }\r\n\r\n _createSVG() {\r\n // 检查并设置容器的定位\r\n if (typeof getComputedStyle !== 'undefined') {\r\n const containerStyle = getComputedStyle(this.container)\r\n if (containerStyle.position === 'static') {\r\n this.container.style.position = 'relative'\r\n }\r\n }\r\n\r\n // 创建 SVG 元素\r\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\r\n this.svg.setAttribute('class', 'ae-d2-svg')\r\n this.container.appendChild(this.svg)\r\n\r\n // 创建 defs 和 marker\r\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\r\n this.svg.appendChild(defs)\r\n\r\n const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker')\r\n marker.setAttribute('id', 'ae-arrowhead')\r\n marker.setAttribute('markerWidth', '10')\r\n marker.setAttribute('markerHeight', '10')\r\n marker.setAttribute('refX', '9')\r\n marker.setAttribute('refY', '5')\r\n marker.setAttribute('orient', 'auto')\r\n\r\n const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon')\r\n polygon.setAttribute('points', '0,0 10,5 0,10 2,5')\r\n polygon.setAttribute('fill', this._defaultColor)\r\n\r\n marker.appendChild(polygon)\r\n defs.appendChild(marker)\r\n }\r\n\r\n _createToolbar() {\r\n if (this._toolbar) {\r\n this._toolbar.remove()\r\n }\r\n\r\n this._toolbar = document.createElement('div')\r\n this._toolbar.className = 'ae-toolbar'\r\n\r\n const color = this.selected.color || this._defaultColor\r\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\r\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\r\n\r\n this._toolbar.innerHTML = `\r\n <div class=\"ae-toolbar-drag-handle\">:::</div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">颜色</span>\r\n <input type=\"color\" class=\"ae-color-input\" value=\"${color}\" />\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">粗细</span>\r\n <input type=\"range\" class=\"ae-stroke-input\" min=\"1\" max=\"60\" value=\"${strokeWidth}\" />\r\n <span class=\"ae-toolbar-value\">${strokeWidth}px</span>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">曲线率</span>\r\n <input type=\"range\" class=\"ae-round-input\" min=\"0\" max=\"1\" step=\"0.1\" value=\"${curveRate}\" />\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">箭头长度</span>\r\n <input type=\"range\" class=\"ae-arrow-len-input\" min=\"5\" max=\"50\" value=\"${this.selected.arrowLength ?? this._arrowLength}\" />\r\n <span class=\"ae-toolbar-value\">${this.selected.arrowLength ?? this._arrowLength}px</span>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">箭头宽度</span>\r\n <input type=\"range\" class=\"ae-arrow-width-input\" min=\"5\" max=\"50\" value=\"${this.selected.arrowWidth ?? this._arrowWidth}\" />\r\n <span class=\"ae-toolbar-value\">${this.selected.arrowWidth ?? this._arrowWidth}px</span>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">缩放</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-axis=\"x\">X 缩放</button>\r\n <button class=\"ae-scale-btn\" data-axis=\"y\">Y 缩放</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">3D 旋转</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-axis=\"x-rotate\">X 轴</button>\r\n <button class=\"ae-scale-btn\" data-axis=\"y-rotate\">Y 轴</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">2.5D 挤出</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-up\">上挤出</button>\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-down\">下挤出</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-left\">左挤出</button>\r\n <button class=\"ae-scale-btn\" data-mode=\"extrude-right\">右挤出</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-mode=\"reset\">重置</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">2.5D 透视</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-perspective=\"top\">上透视</button>\r\n <button class=\"ae-scale-btn\" data-perspective=\"bottom\">下透视</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-perspective=\"left\">左透视</button>\r\n <button class=\"ae-scale-btn\" data-perspective=\"right\">右透视</button>\r\n </div>\r\n </div>\r\n <div class=\"ae-toolbar-item\">\r\n <span class=\"ae-toolbar-label\">倾斜</span>\r\n <div class=\"ae-toolbar-row\">\r\n <button class=\"ae-scale-btn\" data-skew=\"x-left\">左倾斜</button>\r\n <button class=\"ae-scale-btn\" data-skew=\"x-right\">右倾斜</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-skew=\"y-up\">上倾斜</button>\r\n <button class=\"ae-scale-btn\" data-skew=\"y-down\">下倾斜</button>\r\n </div>\r\n <div class=\"ae-toolbar-row\" style=\"margin-top:4px;\">\r\n <button class=\"ae-scale-btn\" data-mode=\"reset\">重置</button>\r\n </div>\r\n </div>\r\n `\r\n\r\n // 颜色选择\r\n const colorInput = this._toolbar.querySelector('.ae-color-input')\r\n colorInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.color = e.target.value\r\n this._defaultColor = e.target.value\r\n this._updateMarkerColor(e.target.value)\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'color', arrow: this.selected, value: e.target.value, arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 粗细调整\r\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\r\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\r\n strokeInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.strokeWidth = parseInt(e.target.value)\r\n strokeValue.textContent = e.target.value + 'px'\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'strokeWidth', arrow: this.selected, value: parseInt(e.target.value), arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 曲线率调整\r\n const roundInput = this._toolbar.querySelector('.ae-round-input')\r\n roundInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.curveRate = parseFloat(e.target.value)\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'curveRate', arrow: this.selected, value: parseFloat(e.target.value), arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 箭头长度调整\r\n const arrowLenInput = this._toolbar.querySelector('.ae-arrow-len-input')\r\n const arrowLenValue = this._toolbar.querySelector('.ae-arrow-len-input + .ae-toolbar-value')\r\n arrowLenInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.arrowLength = parseInt(e.target.value)\r\n arrowLenValue.textContent = e.target.value + 'px'\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'arrowLength', arrow: this.selected, value: parseInt(e.target.value), arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 箭头宽度调整\r\n const arrowWidthInput = this._toolbar.querySelector('.ae-arrow-width-input')\r\n const arrowWidthValue = this._toolbar.querySelector('.ae-arrow-width-input + .ae-toolbar-value')\r\n arrowWidthInput.addEventListener('input', (e) => {\r\n if (!this.selected) return\r\n this.selected.arrowWidth = parseInt(e.target.value)\r\n arrowWidthValue.textContent = e.target.value + 'px'\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'arrowWidth', arrow: this.selected, value: parseInt(e.target.value), arrows: this.getData() })\r\n }\r\n })\r\n\r\n // X/Y 缩放按钮\r\n const scaleBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-axis]')\r\n scaleBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const axis = e.target.dataset.axis\r\n\r\n // X/Y 轴旋转(3D 透视效果)\r\n if (axis === 'x-rotate') {\r\n this._startRotate3D('x')\r\n return\r\n } else if (axis === 'y-rotate') {\r\n this._startRotate3D('y')\r\n return\r\n }\r\n\r\n // 轴向缩放\r\n this._transformMode = 'scale'\r\n this._transformAxis = axis\r\n this._transformCenter = this._getArrowBBox(this.selected)\r\n this._transformStartPoints = this.selected.points.map(pt => ({ ...pt }))\r\n\r\n // 设置初始鼠标位置\r\n const rect = this._getArrowBBox(this.selected)\r\n if (axis === 'x') {\r\n this._transformStartPos = { x: rect.maxX + 10, y: rect.centerY }\r\n } else {\r\n this._transformStartPos = { x: rect.centerX, y: rect.maxY + 10 }\r\n }\r\n\r\n // 绑定鼠标移动和松开事件\r\n const onMouseMove = (ev) => {\r\n const p = this._mousePos(ev)\r\n if (axis === 'x') {\r\n this._handleScaleX(p)\r\n } else {\r\n this._handleScaleY(p)\r\n }\r\n this.render()\r\n }\r\n\r\n const onMouseUp = () => {\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onMouseUp)\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'scale', arrow: this.selected, arrows: this.getData() })\r\n }\r\n\r\n this._transformMode = null\r\n this._transformAxis = null\r\n }\r\n\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onMouseUp)\r\n })\r\n })\r\n\r\n // 2.5D 视角按钮\r\n const modeBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-mode]')\r\n modeBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const mode = e.target.dataset.mode\r\n if (mode === 'extrude-up') {\r\n this._applyExtrude(0, -15)\r\n } else if (mode === 'extrude-down') {\r\n this._applyExtrude(0, 15)\r\n } else if (mode === 'extrude-left') {\r\n this._applyExtrude(-15, 0)\r\n } else if (mode === 'extrude-right') {\r\n this._applyExtrude(15, 0)\r\n } else if (mode === 'reset') {\r\n this._resetExtrude()\r\n }\r\n })\r\n })\r\n\r\n // 2.5D 透视按钮\r\n const perspectiveBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-perspective]')\r\n perspectiveBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const direction = e.target.dataset.perspective\r\n if (direction === 'top') {\r\n this._applyPerspective('top')\r\n } else if (direction === 'bottom') {\r\n this._applyPerspective('bottom')\r\n } else if (direction === 'left') {\r\n this._applyPerspective('left')\r\n } else if (direction === 'right') {\r\n this._applyPerspective('right')\r\n }\r\n })\r\n })\r\n\r\n // 倾斜按钮\r\n const skewBtns = this._toolbar.querySelectorAll('.ae-scale-btn[data-skew]')\r\n skewBtns.forEach(btn => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation()\r\n const skewType = e.target.dataset.skew\r\n if (skewType === 'x-left') {\r\n this._applySkew('x-left')\r\n } else if (skewType === 'x-right') {\r\n this._applySkew('x-right')\r\n } else if (skewType === 'y-up') {\r\n this._applySkew('y-up')\r\n } else if (skewType === 'y-down') {\r\n this._applySkew('y-down')\r\n }\r\n })\r\n })\r\n\r\n // 拖拽功能 - 使用类实例绑定\r\n const dragHandle = this._toolbar.querySelector('.ae-toolbar-drag-handle')\r\n this._setupToolbarDrag(dragHandle)\r\n\r\n // 阻止工具条上的事件触发到容器\r\n this._toolbar.addEventListener('mousedown', (e) => {\r\n e.stopPropagation()\r\n })\r\n this._toolbar.addEventListener('mouseup', (e) => {\r\n e.stopPropagation()\r\n })\r\n\r\n // 工具条添加到 body,而不是 container\r\n document.body.appendChild(this._toolbar)\r\n }\r\n\r\n // 工具条拖拽设置\r\n _setupToolbarDrag(dragHandle) {\r\n let isDragging = false\r\n let dragOffset = { x: 0, y: 0 }\r\n\r\n dragHandle.addEventListener('mousedown', (e) => {\r\n isDragging = true\r\n this._toolbarDragging = true\r\n const rect = this._toolbar.getBoundingClientRect()\r\n dragOffset.x = e.clientX - rect.left\r\n dragOffset.y = e.clientY - rect.top\r\n e.preventDefault()\r\n e.stopPropagation()\r\n\r\n const onMove = (moveEvent) => {\r\n if (!isDragging) return\r\n // 直接使用页面坐标,不限制在容器内\r\n let newLeft = moveEvent.clientX - dragOffset.x\r\n let newTop = moveEvent.clientY - dragOffset.y\r\n this._toolbar.style.left = newLeft + 'px'\r\n this._toolbar.style.top = newTop + 'px'\r\n }\r\n\r\n const onUp = (e) => {\r\n isDragging = false\r\n this._toolbarDragging = false\r\n document.removeEventListener('mousemove', onMove)\r\n document.removeEventListener('mouseup', onUp)\r\n this._toolbar.removeEventListener('mouseup', onUp)\r\n\r\n e.preventDefault()\r\n e.stopPropagation()\r\n }\r\n\r\n document.addEventListener('mousemove', onMove)\r\n document.addEventListener('mouseup', onUp)\r\n\r\n this._toolbar.addEventListener('mouseup', onUp)\r\n })\r\n }\r\n\r\n _showToolbar() {\r\n if (this.selected) {\r\n if (!this._toolbar) {\r\n this._createToolbar()\r\n }\r\n this._toolbar.style.display = 'flex'\r\n\r\n // 更新工具条值\r\n const color = this.selected.color || this._defaultColor\r\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\r\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\r\n const arrowLength = this.selected.arrowLength ?? this._arrowLength\r\n const arrowWidth = this.selected.arrowWidth ?? this._arrowWidth\r\n\r\n const colorInput = this._toolbar.querySelector('.ae-color-input')\r\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\r\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\r\n const roundInput = this._toolbar.querySelector('.ae-round-input')\r\n const arrowLenInput = this._toolbar.querySelector('.ae-arrow-len-input')\r\n const arrowLenValue = this._toolbar.querySelector('.ae-arrow-len-input + .ae-toolbar-value')\r\n const arrowWidthInput = this._toolbar.querySelector('.ae-arrow-width-input')\r\n const arrowWidthValue = this._toolbar.querySelector('.ae-arrow-width-input + .ae-toolbar-value')\r\n\r\n if (colorInput) colorInput.value = color\r\n if (strokeInput) {\r\n strokeInput.value = strokeWidth\r\n strokeValue.textContent = strokeWidth + 'px'\r\n }\r\n if (roundInput) roundInput.value = curveRate\r\n if (arrowLenInput) {\r\n arrowLenInput.value = arrowLength\r\n arrowLenValue.textContent = arrowLength + 'px'\r\n }\r\n if (arrowWidthInput) {\r\n arrowWidthInput.value = arrowWidth\r\n arrowWidthValue.textContent = arrowWidth + 'px'\r\n }\r\n\r\n // 定位到所选箭头旁边(使用页面坐标)\r\n const containerRect = this.container.getBoundingClientRect()\r\n const bbox = this._getArrowBBox(this.selected)\r\n const toolbarWidth = this._toolbar.offsetWidth || 150\r\n const toolbarHeight = this._toolbar.offsetHeight || 120\r\n\r\n // 计算位置:放在箭头右侧,如果空间不够则放左侧\r\n let left = containerRect.left + bbox.maxX + 20\r\n if (left + toolbarWidth > window.innerWidth - 10) {\r\n left = containerRect.left + bbox.minX - toolbarWidth - 20\r\n }\r\n\r\n // 垂直居中于箭头\r\n let top = containerRect.top + bbox.centerY - toolbarHeight / 2\r\n if (top < 10) top = 10\r\n if (top + toolbarHeight > window.innerHeight - 10) {\r\n top = window.innerHeight - toolbarHeight - 10\r\n }\r\n\r\n this._toolbar.style.left = left + 'px'\r\n this._toolbar.style.top = top + 'px'\r\n }\r\n }\r\n\r\n _hideToolbar() {\r\n if (this._toolbar) {\r\n this._toolbar.style.display = 'none'\r\n }\r\n }\r\n\r\n _updateMarkerColor(color) {\r\n const marker = this.svg.querySelector('#ae-arrowhead polygon')\r\n if (marker) {\r\n marker.setAttribute('fill', color)\r\n }\r\n }\r\n\r\n _initKeybindings() {\r\n // 创建快捷键实例,绑定到 container 上\r\n this._kb = new Keybinding('arrow-editor-' + Math.random(), this.container)\r\n\r\n // Enter: 完成绘制\r\n this._kb.on('enter', () => {\r\n this._handleEnter()\r\n })\r\n\r\n // Esc: 结束绘制、取消选中\r\n this._kb.on('esc', () => {\r\n this._handleEsc()\r\n })\r\n\r\n // Delete/Backspace: 删除选中的箭头\r\n this._kb.on('delete', () => {\r\n this._handleDelete()\r\n })\r\n\r\n this._kb.on('backspace', () => {\r\n this._handleDelete()\r\n })\r\n\r\n // Space: 绘制中添加点\r\n this._kb.on('space', () => {\r\n this._handleSpace()\r\n })\r\n\r\n // 方向键:选中时微调位置\r\n this._kb.on('arrowup', () => {\r\n this._handleArrowKey(0, -1)\r\n })\r\n\r\n this._kb.on('arrowdown', () => {\r\n this._handleArrowKey(0, 1)\r\n })\r\n\r\n this._kb.on('arrowleft', () => {\r\n this._handleArrowKey(-1, 0)\r\n })\r\n\r\n this._kb.on('arrowright', () => {\r\n this._handleArrowKey(1, 0)\r\n })\r\n }\r\n\r\n // 空格键:绘制中添加点\r\n _handleSpace() {\r\n // 只有正在绘制时才处理\r\n if (!this.drawing || !this.current) return\r\n\r\n // 使用当前鼠标位置添加点\r\n if (this._lastMousePos) {\r\n this.current.points.push({ ...this._lastMousePos })\r\n this.render()\r\n }\r\n }\r\n\r\n // 方向键:选中箭头时微调位置\r\n _handleArrowKey(dx, dy) {\r\n if (!this.selected) return\r\n\r\n const step = 1 // 每次移动 1 像素\r\n this.selected.points.forEach(pt => {\r\n pt.x += dx * step\r\n pt.y += dy * step\r\n })\r\n\r\n this.render()\r\n\r\n // 触发 onChange 回调\r\n if (this.onChange) {\r\n this.onChange({ type: 'move', arrow: this.selected, arrows: this.getData() })\r\n }\r\n }\r\n\r\n _initEvents() {\r\n this.container.onclick = e => {\r\n // 点击工具条时不处理\r\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\r\n return\r\n }\r\n if (this.preventDefault) e.preventDefault()\r\n if (this.stopPropagation) e.stopPropagation()\r\n const p = this._mousePos(e)\r\n this._handleClick(p, e)\r\n }\r\n\r\n this.container.onmousemove = e => {\r\n if (this.preventDefault) e.preventDefault()\r\n if (this.stopPropagation) e.stopPropagation()\r\n const p = this._mousePos(e)\r\n // 记录鼠标位置,用于空格键打点\r\n this._lastMousePos = p\r\n this._handleMouseMove(e, p)\r\n }\r\n\r\n this.container.onmousedown = e => {\r\n // 点击工具条不触发移动\r\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\r\n return\r\n }\r\n\r\n if (this.preventDefault) e.preventDefault()\r\n if (this.stopPropagation) e.stopPropagation()\r\n\r\n if (this.selected) {\r\n const handle = e.target.getAttribute('data-handle')\r\n if (handle) {\r\n this._transformMode = handle === 'scaleX' || handle === 'scaleY' ? 'scale' : handle\r\n this._transformHandle = handle\r\n this._transformAxis = handle === 'scaleX' ? 'x' : (handle === 'scaleY' ? 'y' : null)\r\n const p = this._mousePos(e)\r\n this._transformStartPos = p\r\n this._transformStartPoints = this.selected.points.map(pt => ({ x: pt.x, y: pt.y }))\r\n this._transformCenter = this._getArrowBBox(this.selected)\r\n\r\n if (handle === 'rotate') {\r\n const center = this._transformCenter\r\n const dx = p.x - center.centerX\r\n const dy = p.y - center.centerY\r\n this._transformStartAngle = Math.atan2(dy, dx)\r\n this._rotationOffset = 0\r\n }\r\n\r\n e.stopPropagation()\r\n return\r\n }\r\n\r\n this.mode = 'move'\r\n }\r\n }\r\n\r\n this.container.onmouseup = (e) => {\r\n // 如果有变换操作,调用 onChange 回调\r\n if (this._transformMode && this.selected) {\r\n if (this.onChange) {\r\n this.onChange({ type: this._transformMode, arrow: this.selected, arrows: this.getData() })\r\n }\r\n }\r\n this.mode = null\r\n this._transformMode = null\r\n this._transformHandle = null\r\n this._transformAxis = null\r\n }\r\n }\r\n\r\n _mousePos(e) {\r\n const r = this.container.getBoundingClientRect()\r\n return {\r\n x: e.clientX - r.left,\r\n y: e.clientY - r.top\r\n }\r\n }\r\n\r\n _generatePath(pts, curveRate = 0) {\r\n if (pts.length < 2) return ''\r\n\r\n // curveRate 为 0 时画直线\r\n if (curveRate === 0) {\r\n let d = `M ${pts[0].x} ${pts[0].y}`\r\n for (let i = 1; i < pts.length; i++) {\r\n d += ` L ${pts[i].x} ${pts[i].y}`\r\n }\r\n return d\r\n }\r\n\r\n // 根据曲线率计算控制点位置\r\n // curveRate: 0 - 直线,1 - 最弯曲\r\n let d = `M ${pts[0].x} ${pts[0].y}`\r\n\r\n for (let i = 0; i < pts.length - 1; i++) {\r\n const curr = pts[i]\r\n const next = pts[i + 1]\r\n\r\n // 计算当前线段的向量\r\n const dx = next.x - curr.x\r\n const dy = next.y - curr.y\r\n const len = Math.hypot(dx, dy)\r\n\r\n if (len === 0) continue\r\n\r\n // 计算进入当前点的切线向量(前一段线段)\r\n let inDx = dx\r\n let inDy = dy\r\n\r\n if (i > 0) {\r\n const prev = pts[i - 1]\r\n inDx = curr.x - prev.x\r\n inDy = curr.y - prev.y\r\n }\r\n\r\n // 计算出当前点的切线向量(下一段线段)\r\n let outDx = dx\r\n let outDy = dy\r\n\r\n if (i < pts.length - 2) {\r\n const after = pts[i + 2]\r\n outDx = after.x - next.x\r\n outDy = after.y - next.y\r\n }\r\n\r\n // 单位向量\r\n const inLen = Math.hypot(inDx, inDy) || 1\r\n const outLen = Math.hypot(outDx, outDy) || 1\r\n const uxIn = inDx / inLen\r\n const uyIn = inDy / inLen\r\n const uxOut = outDx / outLen\r\n const uyOut = outDy / outLen\r\n\r\n // 控制点距离:曲线率 * 线段长度 * 系数\r\n const controlDist = len * curveRate * 0.3\r\n\r\n // 第一个控制点:从当前点沿进入方向的切线\r\n const cp1X = curr.x + uxIn * controlDist\r\n const cp1Y = curr.y + uyIn * controlDist\r\n\r\n // 第二个控制点:从下一个点沿出去方向的切线反方向\r\n const cp2X = next.x - uxOut * controlDist\r\n const cp2Y = next.y - uyOut * controlDist\r\n\r\n d += ` C ${cp1X} ${cp1Y} ${cp2X} ${cp2Y} ${next.x} ${next.y}`\r\n }\r\n\r\n return d\r\n }\r\n\r\n _generateArrowHead(pts, strokeWidth = 8, arrowLength = 22, arrowWidth = 20) {\r\n if (pts.length < 2) return ''\r\n\r\n const last = pts[pts.length - 1]\r\n let prev = pts[pts.length - 2]\r\n\r\n if (pts.length >= 3) {\r\n const dist = Math.hypot(last.x - prev.x, last.y - prev.y)\r\n if (dist < 5) {\r\n prev = pts[pts.length - 3]\r\n }\r\n }\r\n\r\n const dx = last.x - prev.x\r\n const dy = last.y - prev.y\r\n const len = Math.hypot(dx, dy)\r\n\r\n if (len < 1) return ''\r\n\r\n const ux = dx / len\r\n const uy = dy / len\r\n\r\n // 根据粗细调整箭头大小\r\n const scale = strokeWidth / 8\r\n const arrowLen = arrowLength * scale\r\n const scaledArrowWidth = arrowWidth * scale\r\n\r\n const lx = last.x\r\n const ly = last.y\r\n\r\n // 箭头往外挪动一半长度,遮住箭身厚度\r\n const offsetX = ux * (arrowLen / 2)\r\n const offsetY = uy * (arrowLen / 2)\r\n\r\n // 箭头尖端(在线段末端往外挪一半)\r\n const tipX = lx + offsetX\r\n const tipY = ly + offsetY\r\n\r\n // 箭头底部中心(往回缩一个箭头长度)\r\n const baseX = lx + offsetX - ux * arrowLen\r\n const baseY = ly + offsetY - uy * arrowLen\r\n\r\n // 垂直方向的单位向量\r\n const px = -uy\r\n const py = ux\r\n\r\n // 底部左右两个角\r\n const leftX = baseX + px * scaledArrowWidth\r\n const leftY = baseY + py * scaledArrowWidth\r\n const rightX = baseX - px * scaledArrowWidth\r\n const rightY = baseY - py * scaledArrowWidth\r\n\r\n // 实心三角形\r\n return `M ${tipX} ${tipY} L ${leftX} ${leftY} L ${rightX} ${rightY} Z`\r\n }\r\n\r\n _createArrowGroup(arrow, index) {\r\n const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')\r\n g.setAttribute('data-index', index)\r\n\r\n const color = arrow.color || this._defaultColor\r\n const strokeWidth = arrow.strokeWidth || this._strokeWidth\r\n const curveRate = arrow.curveRate ?? arrow.cornerRoundness ?? 0\r\n const arrowLength = arrow.arrowLength ?? this._arrowLength\r\n const arrowWidth = arrow.arrowWidth ?? this._arrowWidth\r\n\r\n // 挤出效果(2.5D 阴影层)\r\n const extrude = arrow.extrude || { x: 0, y: 0 }\r\n const extrudeLayers = Math.max(Math.abs(extrude.x), Math.abs(extrude.y))\r\n const hasExtrude = extrudeLayers > 0\r\n\r\n // 绘制挤出阴影层(从后往前)\r\n if (hasExtrude) {\r\n const stepX = extrude.x > 0 ? 1 : -1\r\n const stepY = extrude.y > 0 ? 1 : -1\r\n const layers = Math.max(Math.abs(extrude.x), Math.abs(extrude.y))\r\n\r\n for (let i = 1; i <= layers; i++) {\r\n const offsetX = stepX * i\r\n const offsetY = stepY * i\r\n\r\n // 阴影层路径\r\n const shadowPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n shadowPath.setAttribute('class', 'ae-arrow-path')\r\n shadowPath.style.stroke = '#ccc'\r\n shadowPath.style.strokeWidth = strokeWidth + 'px'\r\n shadowPath.style.opacity = '0.15'\r\n shadowPath.setAttribute('d', this._generatePath(arrow.points.map(pt => ({\r\n x: pt.x + offsetX,\r\n y: pt.y + offsetY\r\n })), curveRate))\r\n g.appendChild(shadowPath)\r\n\r\n // 阴影层箭头\r\n const shadowArrowHead = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n shadowArrowHead.setAttribute('fill', '#ccc')\r\n shadowArrowHead.setAttribute('fill-opacity', '0.15')\r\n shadowArrowHead.setAttribute('d', this._generateArrowHead(arrow.points.map(pt => ({\r\n x: pt.x + offsetX,\r\n y: pt.y + offsetY\r\n })), strokeWidth, arrowLength, arrowWidth))\r\n g.appendChild(shadowArrowHead)\r\n }\r\n }\r\n\r\n // 绘制主箭头(箭身路径)\r\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n path.setAttribute('class', 'ae-arrow-path')\r\n path.style.stroke = color\r\n path.style.strokeWidth = strokeWidth + 'px'\r\n path.setAttribute('d', this._generatePath(arrow.points, curveRate))\r\n g.appendChild(path)\r\n\r\n // 绘制主箭头(箭头头部)\r\n const arrowHead = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n arrowHead.setAttribute('fill', color)\r\n arrowHead.setAttribute('d', this._generateArrowHead(arrow.points, strokeWidth, arrowLength, arrowWidth))\r\n g.appendChild(arrowHead)\r\n\r\n if (arrow === this.selected) {\r\n const bbox = this._getArrowBBox(arrow)\r\n\r\n // 变换框\r\n const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')\r\n rect.setAttribute('class', 'ae-transform-box')\r\n rect.setAttribute('x', bbox.minX - 10)\r\n rect.setAttribute('y', bbox.minY - 10)\r\n rect.setAttribute('width', bbox.width + 20)\r\n rect.setAttribute('height', bbox.height + 20)\r\n g.appendChild(rect)\r\n\r\n // 缩放手柄(右下角)\r\n const scaleHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n scaleHandle.setAttribute('class', 'ae-transform-handle')\r\n scaleHandle.setAttribute('cx', bbox.maxX + 10)\r\n scaleHandle.setAttribute('cy', bbox.maxY + 10)\r\n scaleHandle.setAttribute('r', 6)\r\n scaleHandle.setAttribute('data-handle', 'scale')\r\n g.appendChild(scaleHandle)\r\n\r\n // X 方向缩放手柄(右边中间)\r\n const scaleXHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n scaleXHandle.setAttribute('class', 'ae-transform-handle')\r\n scaleXHandle.setAttribute('cx', bbox.maxX + 10)\r\n scaleXHandle.setAttribute('cy', bbox.centerY)\r\n scaleXHandle.setAttribute('r', 6)\r\n scaleXHandle.setAttribute('data-handle', 'scaleX')\r\n g.appendChild(scaleXHandle)\r\n\r\n // Y 方向缩放手柄(底部中间)\r\n const scaleYHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n scaleYHandle.setAttribute('class', 'ae-transform-handle')\r\n scaleYHandle.setAttribute('cx', bbox.centerX)\r\n scaleYHandle.setAttribute('cy', bbox.maxY + 10)\r\n scaleYHandle.setAttribute('r', 6)\r\n scaleYHandle.setAttribute('data-handle', 'scaleY')\r\n g.appendChild(scaleYHandle)\r\n\r\n // 旋转手柄(顶部中间)\r\n const rotateY = bbox.minY - 30\r\n const rotateX = bbox.centerX\r\n const rotateLine = document.createElementNS('http://www.w3.org/2000/svg', 'line')\r\n rotateLine.setAttribute('class', 'ae-rotate-line')\r\n rotateLine.setAttribute('x1', bbox.centerX)\r\n rotateLine.setAttribute('y1', bbox.minY - 10)\r\n rotateLine.setAttribute('x2', rotateX)\r\n rotateLine.setAttribute('y2', rotateY)\r\n g.appendChild(rotateLine)\r\n\r\n const rotateHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\r\n rotateHandle.setAttribute('class', 'ae-rotate-handle')\r\n rotateHandle.setAttribute('cx', rotateX)\r\n rotateHandle.setAttribute('cy', rotateY)\r\n rotateHandle.setAttribute('r', 8)\r\n rotateHandle.setAttribute('data-handle', 'rotate')\r\n g.appendChild(rotateHandle)\r\n }\r\n\r\n return g\r\n }\r\n\r\n render() {\r\n this.svg.querySelectorAll('g').forEach(g => g.remove())\r\n\r\n this.arrows.forEach((arrow, index) => {\r\n const g = this._createArrowGroup(arrow, index)\r\n this.svg.appendChild(g)\r\n })\r\n\r\n if (this.current) {\r\n const g = this._createArrowGroup(this.current, this.arrows.length)\r\n this.svg.appendChild(g)\r\n }\r\n }\r\n\r\n _isDoubleClick(p) {\r\n const now = Date.now()\r\n const dt = now - this.lastClickTime\r\n this.lastClickTime = now\r\n\r\n if (dt < 300 && this.lastClickPos && Math.hypot(p.x - this.lastClickPos.x, p.y - this.lastClickPos.y) < 10) {\r\n this.lastClickPos = null\r\n return true\r\n }\r\n\r\n this.lastClickPos = p\r\n return false\r\n }\r\n\r\n _handleClick(p, e) {\r\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\r\n if (this.isCtrl && !e.ctrlKey) {\r\n return\r\n }\r\n\r\n // 如果刚才有拖拽,阻止点击事件\r\n if (this._shouldBlockClick) {\r\n this._shouldBlockClick = false\r\n return\r\n }\r\n\r\n if (this._isDoubleClick(p)) {\r\n if (this.drawing && this.current && this.current.points.length >= 2) {\r\n this.drawing = false\r\n this.arrows.push(this.current)\r\n const arrow = this.current\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n this.render()\r\n if (this.onDrawEnd) {\r\n this.onDrawEnd({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n return\r\n }\r\n\r\n // 有选中的箭头时,点击空白处取消选中\r\n if (this.selected) {\r\n for (const a of this.arrows) {\r\n if (this._hitArrow(a, p)) {\r\n this.render()\r\n return\r\n }\r\n }\r\n // 点击空白处,取消选中\r\n this.selected = null\r\n this._hideToolbar()\r\n this.render()\r\n return\r\n }\r\n\r\n // 没有选中时,检查是否点击到箭头\r\n for (const a of this.arrows) {\r\n if (this._hitArrow(a, p)) {\r\n this.selected = a\r\n this._showToolbar()\r\n this.render()\r\n return\r\n }\r\n }\r\n\r\n // 点击空白处\r\n if (this.drawing) {\r\n // 正在绘制中,添加点\r\n this.current.points.push(p)\r\n } else {\r\n // 开始绘制\r\n this.drawing = true\r\n this.current = {\r\n points: [p, p],\r\n color: this._defaultColor\r\n }\r\n // 添加 fixed 类,让 SVG 固定定位覆盖整个视口\r\n this.svg.classList.add('ae-d2-svg-fixed')\r\n }\r\n\r\n this.render()\r\n }\r\n\r\n _handleEnter() {\r\n // 正在绘制时,按 Enter 完成绘制\r\n if (this.drawing && this.current && this.current.points.length >= 2) {\r\n this.drawing = false\r\n this.arrows.push(this.current)\r\n const arrow = this.current\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n this.render()\r\n if (this.onDrawEnd) {\r\n this.onDrawEnd({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n }\r\n\r\n _handleEsc() {\r\n // 按 Esc: 结束绘制、取消选中\r\n if (this.drawing) {\r\n this.drawing = false\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n }\r\n if (this.selected) {\r\n this.selected = null\r\n }\r\n this._hideColorPicker()\r\n this._hideToolbar()\r\n this.render()\r\n }\r\n\r\n _handleDelete() {\r\n // 删除选中的箭头\r\n if (this.selected) {\r\n const arrow = this.selected\r\n const index = this.arrows.indexOf(this.selected)\r\n if (index > -1) {\r\n this.arrows.splice(index, 1)\r\n }\r\n this.selected = null\r\n this._hideToolbar()\r\n this.render()\r\n if (this.onRemove) {\r\n this.onRemove({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n }\r\n\r\n _showColorPicker(e) {\r\n if (this._showingColorPicker) {\r\n this._hideColorPicker()\r\n return\r\n }\r\n\r\n this._showingColorPicker = true\r\n\r\n // 创建颜色选择器浮窗\r\n const popup = document.createElement('div')\r\n popup.className = 'ae-color-picker-popup'\r\n\r\n const label = document.createElement('span')\r\n label.textContent = '选择颜色'\r\n label.style.cssText = 'font-size: 12px; color: #666;'\r\n\r\n const colorInput = document.createElement('input')\r\n colorInput.type = 'color'\r\n colorInput.value = this.selected.color || this._defaultColor\r\n // 自动打开颜色选择器\r\n colorInput.showPicker()\r\n\r\n popup.appendChild(label)\r\n popup.appendChild(colorInput)\r\n\r\n // 定位到颜色手柄位置\r\n const rect = this.container.getBoundingClientRect()\r\n const bbox = this._getArrowBBox(this.selected)\r\n const x = rect.left + bbox.minX - 50\r\n const y = rect.top + bbox.maxY + 15\r\n\r\n popup.style.left = x + 'px'\r\n popup.style.top = y + 'px'\r\n\r\n // 颜色改变时实时更新\r\n colorInput.addEventListener('input', (ev) => {\r\n this.selected.color = ev.target.value\r\n this._defaultColor = ev.target.value\r\n this.render()\r\n if (this.onChange) {\r\n this.onChange({ type: 'color', arrow: this.selected, value: ev.target.value, arrows: this.getData() })\r\n }\r\n })\r\n\r\n // 点击外部关闭\r\n const closeHandler = (ev) => {\r\n if (!popup.contains(ev.target)) {\r\n this._hideColorPicker()\r\n document.removeEventListener('click', closeHandler)\r\n }\r\n }\r\n\r\n document.body.appendChild(popup)\r\n this._colorPickerPopup = popup\r\n\r\n document.addEventListener('click', closeHandler)\r\n }\r\n\r\n _hideColorPicker() {\r\n if (this._colorPickerPopup) {\r\n this._colorPickerPopup.remove()\r\n this._colorPickerPopup = null\r\n }\r\n this._showingColorPicker = false\r\n }\r\n\r\n // 删除选中的箭头\r\n deleteSelected() {\r\n if (this.selected) {\r\n this.arrows = this.arrows.filter(a => a !== this.selected)\r\n this.selected = null\r\n this.render()\r\n }\r\n }\r\n\r\n _handleMouseMove(e, p) {\r\n // 如果正在拖拽工具条,不处理\r\n if (this._toolbarDragging) {\r\n return\r\n }\r\n\r\n // 如果鼠标在工具条上,不处理\r\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\r\n return\r\n }\r\n\r\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\r\n if (this.isCtrl && !e.ctrlKey) {\r\n // 如果正在绘制中,按 Ctrl 键松开则结束绘制\r\n if (this.drawing && this.current && this.current.points.length >= 2) {\r\n this.drawing = false\r\n this.arrows.push(this.current)\r\n const arrow = this.current\r\n this.current = null\r\n this.svg.classList.remove('ae-d2-svg-fixed')\r\n this.render()\r\n if (this.onDrawEnd) {\r\n this.onDrawEnd({ arrow, arrows: this.getData() })\r\n }\r\n }\r\n return\r\n }\r\n\r\n if (this.drawing) {\r\n this.current.points[this.current.points.length - 1] = p\r\n this.render()\r\n }\r\n\r\n // 变换处理(旋转/缩放)\r\n if (this._transformMode && this.selected) {\r\n if (this._transformMode === 'rotate') {\r\n this._handleRotate(p)\r\n } else if (this._transformMode === 'scale') {\r\n // 根据轴向选择处理方式\r\n if (this._transformAxis === 'x') {\r\n this._handleScaleX(p)\r\n } else if (this._transformAxis === 'y') {\r\n this._handleScaleY(p)\r\n } else {\r\n this._handleScale(p)\r\n }\r\n } else if (this._transformMode === 'rotate3d') {\r\n this._handleRotate3D(p)\r\n }\r\n this.render()\r\n return\r\n }\r\n\r\n if (this.selected && this.mode === 'move') {\r\n const dx = e.movementX\r\n const dy = e.movementY\r\n\r\n // 如果有移动,标记需要阻止点击\r\n if (dx !== 0 || dy !== 0) {\r\n this._shouldBlockClick = true\r\n }\r\n\r\n this.selected.points.forEach(pt => {\r\n pt.x += dx\r\n pt.y += dy\r\n })\r\n\r\n this.render()\r\n }\r\n }\r\n\r\n _getArrowBBox(arrow) {\r\n const points = arrow.points\r\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity\r\n\r\n for (const pt of points) {\r\n minX = Math.min(minX, pt.x)\r\n minY = Math.min(minY, pt.y)\r\n maxX = Math.max(maxX, pt.x)\r\n maxY = Math.max(maxY, pt.y)\r\n }\r\n\r\n return {\r\n minX,\r\n minY,\r\n maxX,\r\n maxY,\r\n width: maxX - minX,\r\n height: maxY - minY,\r\n centerX: (minX + maxX) / 2,\r\n centerY: (minY + maxY) / 2\r\n }\r\n }\r\n\r\n _handleRotate(p) {\r\n const center = this._transformCenter\r\n const centerX = center.centerX\r\n const centerY = center.centerY\r\n\r\n // 计算当前角度和起始角度\r\n const currentAngle = Math.atan2(p.y - centerY, p.x - centerX)\r\n const startAngle = Math.atan2(this._transformStartPos.y - centerY, this._transformStartPos.x - centerX)\r\n const angleDiff = currentAngle - startAngle\r\n\r\n // 旋转点\r\n const cos = Math.cos(angleDiff)\r\n const sin = Math.sin(angleDiff)\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n const relX = this._transformStartPoints[i].x - centerX\r\n const relY = this._transformStartPoints[i].y - centerY\r\n pt.x = centerX + relX * cos - relY * sin\r\n pt.y = centerY + relX * sin + relY * cos\r\n })\r\n }\r\n\r\n _handleScale(p) {\r\n const center = this._transformCenter\r\n const centerX = center.centerX\r\n const centerY = center.centerY\r\n const startPoints = this._transformStartPoints\r\n const startPos = this._transformStartPos\r\n\r\n // 计算缩放比例\r\n const dx = p.x - centerX\r\n const dy = p.y - centerY\r\n const startDx = startPos.x - centerX\r\n const startDy = startPos.y - centerY\r\n\r\n const currentDist = Math.hypot(dx, dy)\r\n const startDist = Math.hypot(startDx, startDy)\r\n const scale = currentDist / startDist\r\n\r\n // 应用缩放\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = centerX + (startPoints[i].x - centerX) * scale\r\n pt.y = centerY + (startPoints[i].y - centerY) * scale\r\n })\r\n }\r\n\r\n // X 方向缩放\r\n _handleScaleX(p) {\r\n const center = this._transformCenter\r\n const centerX = center.centerX\r\n const startPoints = this._transformStartPoints\r\n const startPos = this._transformStartPos\r\n\r\n // 计算 X 方向缩放比例\r\n const currentDx = p.x - centerX\r\n const startDx = startPos.x - centerX\r\n const scaleX = startDx !== 0 ? currentDx / startDx : 1\r\n\r\n // 应用 X 方向缩放\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = centerX + (startPoints[i].x - centerX) * scaleX\r\n pt.y = startPoints[i].y // Y 不变\r\n })\r\n }\r\n\r\n // Y 方向缩放\r\n _handleScaleY(p) {\r\n const center = this._transformCenter\r\n const centerY = center.centerY\r\n const startPoints = this._transformStartPoints\r\n const startPos = this._transformStartPos\r\n\r\n // 计算 Y 方向缩放比例\r\n const currentDy = p.y - centerY\r\n const startDy = startPos.y - centerY\r\n const scaleY = startDy !== 0 ? currentDy / startDy : 1\r\n\r\n // 应用 Y 方向缩放\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = startPoints[i].x // X 不变\r\n pt.y = centerY + (startPoints[i].y - centerY) * scaleY\r\n })\r\n }\r\n\r\n // 开始 3D 旋转(X 轴或 Y 轴)\r\n _startRotate3D(axis) {\r\n if (!this.selected) return\r\n\r\n this._transformMode = 'rotate3d'\r\n this._transformAxis = axis // 'x' or 'y'\r\n this._transformCenter = this._getArrowBBox(this.selected)\r\n this._transformStartPoints = this.selected.points.map(pt => ({ ...pt }))\r\n this._rotation3DStartAngle = axis === 'x' ? 0 : 0\r\n\r\n // 设置初始鼠标位置\r\n const rect = this._getArrowBBox(this.selected)\r\n if (axis === 'x') {\r\n this._transformStartPos = { x: rect.maxX + 50, y: rect.centerY }\r\n } else {\r\n this._transformStartPos = { x: rect.centerX, y: rect.maxY + 50 }\r\n }\r\n\r\n // 绑定鼠标移动和松开事件\r\n const onMouseMove = (e) => {\r\n const p = this._mousePos(e)\r\n this._handleRotate3D(p)\r\n this.render()\r\n }\r\n\r\n const onMouseUp = () => {\r\n document.removeEventListener('mousemove', onMouseMove)\r\n document.removeEventListener('mouseup', onMouseUp)\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'rotate3d', arrow: this.selected, value: axis, arrows: this.getData() })\r\n }\r\n\r\n this._transformMode = null\r\n this._transformAxis = null\r\n }\r\n\r\n document.addEventListener('mousemove', onMouseMove)\r\n document.addEventListener('mouseup', onMouseUp)\r\n }\r\n\r\n // 处理 3D 旋转(使用余弦模拟透视效果)\r\n _handleRotate3D(p) {\r\n const center = this._transformCenter\r\n const startPoints = this._transformStartPoints\r\n const axis = this._transformAxis\r\n\r\n if (axis === 'x') {\r\n // X 轴旋转:上下拖动,改变 Y 坐标的缩放(cos 效果)\r\n const deltaY = p.y - this._transformStartPos.y\r\n const angle = Math.max(-90, Math.min(90, -deltaY * 0.9)) // -90 到 90 度\r\n const scale = Math.cos(angle * Math.PI / 180)\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n pt.x = startPoints[i].x // X 不变\r\n // Y 坐标根据旋转角度缩放,模拟 3D 效果\r\n pt.y = center.centerY + (startPoints[i].y - center.centerY) * scale\r\n })\r\n } else {\r\n // Y 轴旋转:左右拖动,改变 X 坐标的缩放(cos 效果)\r\n const deltaX = p.x - this._transformStartPos.x\r\n const angle = Math.max(-90, Math.min(90, deltaX * 0.9)) // -90 到 90 度\r\n const scale = Math.cos(angle * Math.PI / 180)\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n // X 坐标根据旋转角度缩放,模拟 3D 效果\r\n pt.x = center.centerX + (startPoints[i].x - center.centerX) * scale\r\n pt.y = startPoints[i].y // Y 不变\r\n })\r\n }\r\n }\r\n\r\n // 应用 2.5D 挤出效果\r\n _applyExtrude(dx, dy) {\r\n if (!this.selected) return\r\n\r\n // 保存原始点(如果还没保存)\r\n if (!this._originalPoints) {\r\n this._originalPoints = this.selected.points.map(pt => ({ ...pt }))\r\n }\r\n\r\n // 设置挤出参数\r\n this.selected.extrude = { x: dx, y: dy }\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'extrude', arrow: this.selected, value: { x: dx, y: dy }, arrows: this.getData() })\r\n }\r\n }\r\n\r\n // 应用倾斜变换(Skew)\r\n _applySkew(type) {\r\n if (!this.selected) return\r\n\r\n const bbox = this._getArrowBBox(this.selected)\r\n const centerX = bbox.centerX\r\n const centerY = bbox.centerY\r\n\r\n // 保存原始点(如果还没保存)\r\n if (!this._originalPoints) {\r\n this._originalPoints = this.selected.points.map(pt => ({ ...pt }))\r\n }\r\n\r\n // 倾斜强度(像素偏移量)\r\n const skewAmount = 0.3\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n const origPt = this._originalPoints[i]\r\n\r\n if (type === 'x-left') {\r\n // 左倾斜:X 轴负方向倾斜,Y 值越小(越靠上)X 偏移越大\r\n const distFromCenterY = origPt.y - centerY\r\n const totalHeight = bbox.height || 1\r\n const factor = (distFromCenterY / totalHeight) * skewAmount * totalHeight\r\n pt.x = origPt.x - factor\r\n pt.y = origPt.y\r\n } else if (type === 'x-right') {\r\n // 右倾斜:X 轴正方向倾斜\r\n const distFromCenterY = origPt.y - centerY\r\n const totalHeight = bbox.height || 1\r\n const factor = (distFromCenterY / totalHeight) * skewAmount * totalHeight\r\n pt.x = origPt.x + factor\r\n pt.y = origPt.y\r\n } else if (type === 'y-up') {\r\n // 上倾斜:Y 轴负方向倾斜,X 值越小(越靠左)Y 偏移越大\r\n const distFromCenterX = origPt.x - centerX\r\n const totalWidth = bbox.width || 1\r\n const factor = (distFromCenterX / totalWidth) * skewAmount * totalWidth\r\n pt.x = origPt.x\r\n pt.y = origPt.y - factor\r\n } else if (type === 'y-down') {\r\n // 下倾斜:Y 轴正方向倾斜\r\n const distFromCenterX = origPt.x - centerX\r\n const totalWidth = bbox.width || 1\r\n const factor = (distFromCenterX / totalWidth) * skewAmount * totalWidth\r\n pt.x = origPt.x\r\n pt.y = origPt.y + factor\r\n }\r\n })\r\n\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'skew', arrow: this.selected, value: type, arrows: this.getData() })\r\n }\r\n }\r\n\r\n // 应用透视变换(近大远小效果)\r\n _applyPerspective(direction) {\r\n if (!this.selected) return\r\n\r\n const bbox = this._getArrowBBox(this.selected)\r\n const centerX = bbox.centerX\r\n const centerY = bbox.centerY\r\n\r\n // 保存原始点(如果还没保存)\r\n if (!this._originalPoints) {\r\n this._originalPoints = this.selected.points.map(pt => ({ ...pt }))\r\n }\r\n\r\n // 透视参数\r\n const perspectiveStrength = 0.3 // 透视强度\r\n\r\n this.selected.points.forEach((pt, i) => {\r\n const origPt = this._originalPoints[i]\r\n\r\n if (direction === 'top') {\r\n // 上透视:上方缩小,下方放大(灭点在上方)\r\n const distFromTop = origPt.y - bbox.minY\r\n const totalHeight = bbox.height || 1\r\n const factor = 1 - (1 - distFromTop / totalHeight) * perspectiveStrength\r\n pt.x = centerX + (origPt.x - centerX) * factor\r\n pt.y = origPt.y\r\n } else if (direction === 'bottom') {\r\n // 下透视:下方缩小,上方放大(灭点在下方)\r\n const distFromBottom = bbox.maxY - origPt.y\r\n const totalHeight = bbox.height || 1\r\n const factor = 1 - (1 - distFromBottom / totalHeight) * perspectiveStrength\r\n pt.x = centerX + (origPt.x - centerX) * factor\r\n pt.y = origPt.y\r\n } else if (direction === 'left') {\r\n // 左透视:左方缩小,右方放大(灭点在左方)\r\n const distFromLeft = origPt.x - bbox.minX\r\n const totalWidth = bbox.width || 1\r\n const factor = 1 - (1 - distFromLeft / totalWidth) * perspectiveStrength\r\n pt.x = origPt.x\r\n pt.y = centerY + (origPt.y - centerY) * factor\r\n } else if (direction === 'right') {\r\n // 右透视:右方缩小,左方放大(灭点在右方)\r\n const distFromRight = bbox.maxX - origPt.x\r\n const totalWidth = bbox.width || 1\r\n const factor = 1 - (1 - distFromRight / totalWidth) * perspectiveStrength\r\n pt.x = origPt.x\r\n pt.y = centerY + (origPt.y - centerY) * factor\r\n }\r\n })\r\n\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'perspective', arrow: this.selected, value: direction, arrows: this.getData() })\r\n }\r\n }\r\n\r\n // 重置挤出效果\r\n _resetExtrude() {\r\n if (!this.selected) return\r\n\r\n // 清除挤出参数\r\n this.selected.extrude = null\r\n this._originalPoints = null\r\n this.render()\r\n\r\n if (this.onChange) {\r\n this.onChange({ type: 'reset', arrow: this.selected, arrows: this.getData() })\r\n }\r\n }\r\n\r\n _hitArrow(a, p) {\r\n for (let i = 0; i < a.points.length - 1; i++) {\r\n if (this._dist(p, a.points[i], a.points[i + 1]) < 15)\r\n return true\r\n }\r\n return false\r\n }\r\n\r\n _dist(p, a, b) {\r\n const dx = b.x - a.x\r\n const dy = b.y - a.y\r\n const t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy)\r\n const tt = Math.max(0, Math.min(1, t))\r\n const px = a.x + tt * dx\r\n const py = a.y + tt * dy\r\n return Math.hypot(p.x - px, p.y - py)\r\n }\r\n\r\n // 获取所有箭头数据\r\n getData() {\r\n return this.arrows.map(arrow => ({\r\n points: arrow.points,\r\n curveRate: arrow.curveRate ?? arrow.cornerRoundness ?? 0,\r\n strokeWidth: arrow.strokeWidth ?? this._strokeWidth,\r\n arrowLength: arrow.arrowLength ?? this._arrowLength,\r\n arrowWidth: arrow.arrowWidth ?? this._arrowWidth,\r\n color: arrow.color\r\n }))\r\n }\r\n\r\n // 设置箭头数据\r\n setData(data) {\r\n this.arrows = data.map(item => ({\r\n points: item.points,\r\n curveRate: item.curveRate ?? this._curveRate ?? 0,\r\n strokeWidth: item.strokeWidth ?? this._strokeWidth,\r\n arrowLength: item.arrowLength ?? this._arrowLength,\r\n arrowWidth: item.arrowWidth ?? this._arrowWidth,\r\n color: item.color\r\n }))\r\n this.render()\r\n }\r\n\r\n // 清空所有箭头\r\n clear() {\r\n this.arrows = []\r\n this.drawing = false\r\n this.current = null\r\n this.selected = null\r\n this.render()\r\n }\r\n\r\n // 销毁编辑器,移除所有事件和元素\r\n destroy() {\r\n // 销毁键盘绑定\r\n if (this._kb && this._kb.destroy) {\r\n this._kb.destroy()\r\n }\r\n\r\n // 移除容器上的事件\r\n this.container.onclick = null\r\n this.container.onmousemove = null\r\n this.container.onmousedown = null\r\n this.container.onmouseup = null\r\n this.container.ondblclick = null\r\n\r\n // 移除 SVG 元素\r\n if (this.svg) {\r\n this.svg.remove()\r\n this.svg = null\r\n }\r\n\r\n // 移除工具条\r\n if (this._toolbar) {\r\n this._toolbar.remove()\r\n this._toolbar = null\r\n }\r\n\r\n // 移除颜色选择器\r\n if (this._colorPickerPopup) {\r\n this._colorPickerPopup.remove()\r\n this._colorPickerPopup = null\r\n }\r\n\r\n // 清空数据\r\n this.arrows = []\r\n this.drawing = false\r\n this.current = null\r\n this.selected = null\r\n this.mode = null\r\n this._transformMode = null\r\n this._transformHandle = null\r\n this._originalPoints = null\r\n }\r\n}\r\n"],"names":["document","styleEl","createElement","textContent","head","appendChild","constructor","container","options","this","querySelector","svg","arrows","drawing","current","selected","mode","lastClickTime","lastClickPos","_shouldBlockClick","_defaultColor","isCtrl","stopPropagation","preventDefault","onDrawEnd","onRemove","onChange","defaultColor","_strokeWidth","defaultStrokeWidth","_curveRate","_a","defaultCurveRate","_arrowLength","_b","defaultArrowLength","_arrowWidth","_c","defaultArrowWidth","_transformMode","_transformHandle","_transformStartPos","_transformStartPoints","_transformCenter","_transformStartAngle","_rotationOffset","_toolbar","_lastMousePos","_createSVG","_initKeybindings","_initEvents","getComputedStyle","position","style","createElementNS","setAttribute","defs","marker","polygon","_createToolbar","remove","className","color","strokeWidth","curveRate","cornerRoundness","innerHTML","arrowLength","_d","_e","arrowWidth","_f","addEventListener","e","target","value","_updateMarkerColor","render","type","arrow","getData","strokeInput","strokeValue","parseInt","parseFloat","arrowLenInput","arrowLenValue","arrowWidthInput","arrowWidthValue","querySelectorAll","forEach","btn","axis","dataset","_startRotate3D","_transformAxis","_getArrowBBox","points","map","pt","__spreadValues","rect","x","maxX","y","centerY","centerX","maxY","onMouseMove","ev","p","_mousePos","_handleScaleX","_handleScaleY","onMouseUp","removeEventListener","_applyExtrude","_resetExtrude","direction","perspective","_applyPerspective","skewType","skew","_applySkew","dragHandle","_setupToolbarDrag","body","isDragging","dragOffset","_toolbarDragging","getBoundingClientRect","clientX","left","clientY","top","onMove","moveEvent","newLeft","newTop","onUp","_showToolbar","display","colorInput","roundInput","containerRect","bbox","toolbarWidth","offsetWidth","toolbarHeight","offsetHeight","window","innerWidth","minX","innerHeight","_hideToolbar","_kb","Keybinding","Math","random","on","_handleEnter","_handleEsc","_handleDelete","_handleSpace","_handleArrowKey","push","dx","dy","onclick","contains","_handleClick","onmousemove","_handleMouseMove","onmousedown","handle","getAttribute","center","atan2","onmouseup","r","_generatePath","pts","length","d","i","curr","next","len","hypot","inDx","inDy","prev","outDx","outDy","after","inLen","outLen","uxIn","uyIn","uxOut","uyOut","controlDist","_generateArrowHead","last","ux","uy","scale","arrowLen","scaledArrowWidth","lx","ly","offsetX","offsetY","baseX","baseY","px","_createArrowGroup","index","g","extrude","max","abs","stepX","stepY","layers","shadowPath","stroke","opacity","shadowArrowHead","path","arrowHead","minY","width","height","scaleHandle","scaleXHandle","scaleYHandle","rotateY","rotateX","rotateLine","rotateHandle","_isDoubleClick","now","Date","dt","ctrlKey","classList","a","_hitArrow","add","_hideColorPicker","indexOf","splice","_showColorPicker","_showingColorPicker","popup","label","cssText","showPicker","closeHandler","_colorPickerPopup","deleteSelected","filter","_handleRotate","_handleScale","_handleRotate3D","movementX","movementY","Infinity","min","angleDiff","cos","sin","relX","relY","startPoints","startPos","startDx","startDy","currentDx","scaleX","currentDy","scaleY","_rotation3DStartAngle","deltaY","angle","PI","deltaX","_originalPoints","skewAmount","origPt","distFromCenterY","totalHeight","factor","distFromCenterX","totalWidth","perspectiveStrength","_dist","b","t","tt","py","setData","data","item","clear","destroy","ondblclick"],"mappings":"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"}
|