@wbiokr/arrow 1.1.3 → 1.2.1
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 +64 -0
- 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/README.md
CHANGED
|
@@ -195,9 +195,73 @@ editor.destroy()
|
|
|
195
195
|
- **颜色**:点击颜色选择器
|
|
196
196
|
- **粗细**:拖动滑块(1-60px)
|
|
197
197
|
- **曲线率**:拖动滑块(0-1,0=直线,1=最弯曲)
|
|
198
|
+
- **缩放**:
|
|
199
|
+
- **X 缩放**:仅水平方向缩放
|
|
200
|
+
- **Y 缩放**:仅垂直方向缩放
|
|
201
|
+
- **3D 旋转**:
|
|
202
|
+
- **X 轴旋转**:上下拖动,模拟绕 X 轴旋转的透视效果
|
|
203
|
+
- **Y 轴旋转**:左右拖动,模拟绕 Y 轴旋转的透视效果
|
|
204
|
+
- **2.5D 挤出**:
|
|
205
|
+
- **上挤出**:向上方挤出立体阴影
|
|
206
|
+
- **下挤出**:向下方挤出立体阴影
|
|
207
|
+
- **左挤出**:向左方挤出立体阴影
|
|
208
|
+
- **右挤出**:向右方挤出立体阴影
|
|
209
|
+
- **重置**:恢复原始形状
|
|
210
|
+
- **2.5D 透视**:
|
|
211
|
+
- **上透视**:上方缩小,下方放大(灭点在上方)
|
|
212
|
+
- **下透视**:下方缩小,上方放大(灭点在下方)
|
|
213
|
+
- **左透视**:左方缩小,右方放大(灭点在左方)
|
|
214
|
+
- **右透视**:右方缩小,左方放大(灭点在右方)
|
|
215
|
+
- **倾斜**:
|
|
216
|
+
- **左倾斜**:向左倾斜
|
|
217
|
+
- **右倾斜**:向右倾斜
|
|
218
|
+
- **上倾斜**:向上倾斜
|
|
219
|
+
- **下倾斜**:向下倾斜
|
|
220
|
+
- **重置**:恢复原始形状
|
|
198
221
|
|
|
199
222
|
工具条可以拖拽到任意位置。
|
|
200
223
|
|
|
224
|
+
## 缩放手柄
|
|
225
|
+
|
|
226
|
+
选中箭头后,箭头周围会显示三个缩放手柄:
|
|
227
|
+
|
|
228
|
+
- **右下角手柄**:同时 X 和 Y 方向缩放(等比缩放)
|
|
229
|
+
- **右边中间手柄**:仅 X 方向缩放
|
|
230
|
+
- **底部中间手柄**:仅 Y 方向缩放
|
|
231
|
+
|
|
232
|
+
## 3D 旋转说明
|
|
233
|
+
|
|
234
|
+
- **X 轴旋转**:绕 X 轴旋转,上下拖动鼠标控制角度,Y 坐标会根据旋转角度缩放(模拟透视效果)
|
|
235
|
+
- **Y 轴旋转**:绕 Y 轴旋转,左右拖动鼠标控制角度,X 坐标会根据旋转角度缩放(模拟透视效果)
|
|
236
|
+
- **Z 轴旋转**:现有的顶部橙色手柄,绕 Z 轴(垂直于屏幕)旋转
|
|
237
|
+
|
|
238
|
+
> 注:由于 SVG 是 2D 平面,X/Y 轴旋转使用余弦缩放模拟 3D 透视效果,旋转角度范围为 -90°到 90°。
|
|
239
|
+
|
|
240
|
+
## 2.5D 挤出效果
|
|
241
|
+
|
|
242
|
+
- **上/下/左/右挤出**:通过绘制多层灰色阴影,模拟箭头立体挤出的 2.5D 效果
|
|
243
|
+
- **重置**:清除挤出效果,恢复原始 2D 形状
|
|
244
|
+
|
|
245
|
+
> 2.5D 挤出效果是一种伪 3D 效果,通过沿指定方向绘制多层半透明阴影层来模拟立体深度感。
|
|
246
|
+
|
|
247
|
+
## 2.5D 透视效果
|
|
248
|
+
|
|
249
|
+
- **上透视**:灭点在上方,上方缩小下方放大,产生仰视效果
|
|
250
|
+
- **下透视**:灭点在下方,下方缩小上方放大,产生俯视效果
|
|
251
|
+
- **左透视**:灭点在左方,左方缩小右方放大
|
|
252
|
+
- **右透视**:灭点在右方,右方缩小左方放大
|
|
253
|
+
|
|
254
|
+
> 透视效果通过近大远小的原理,根据各点距离灭点的距离动态调整缩放比例,模拟真实的 3D 透视感。
|
|
255
|
+
|
|
256
|
+
## 倾斜效果
|
|
257
|
+
|
|
258
|
+
- **左倾斜**:向左方向倾斜(平行四边形效果)
|
|
259
|
+
- **右倾斜**:向右方向倾斜
|
|
260
|
+
- **上倾斜**:向上方向倾斜
|
|
261
|
+
- **下倾斜**:向下方向倾斜
|
|
262
|
+
|
|
263
|
+
> 倾斜效果通过错切变换(Skew Transform),根据点的位置偏移坐标,产生倾斜的视觉效果。
|
|
264
|
+
|
|
201
265
|
## 键盘快捷键
|
|
202
266
|
|
|
203
267
|
| 快捷键 | 功能 |
|
package/dist/bundle.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var t=Object.defineProperty,e=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable,o=(e,s,r)=>s in e?t(e,s,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[s]=r;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("@wbiokr/keybinding");if("undefined"!=typeof document){const t=document.createElement("style");t.textContent='\n.ae-d2-container {\n position: relative;\n width: 1000px;\n height: 600px;\n background: #fff;\n margin: auto;\n}\n\n.ae-d2-svg {\n width: 100%;\n height: 100%;\n position: absolute;\n left: 0;\n top: 0;\n z-index: 10;\n}\n\n\n.ae-arrow-path {\n fill: none;\n stroke-linejoin: round;\n cursor: pointer;\n}\n\n.ae-arrow-path:hover {\n stroke: #00aaff;\n}\n\n.ae-transform-box {\n fill: none;\n stroke: #00aaff;\n stroke-width: 2;\n stroke-dasharray: 4;\n}\n\n.ae-transform-handle {\n fill: #fff;\n stroke: #00aaff;\n stroke-width: 2;\n cursor: pointer;\n}\n\n.ae-transform-handle:hover {\n fill: #00aaff;\n}\n\n.ae-rotate-handle {\n fill: #fff;\n stroke: #ff6600;\n stroke-width: 2;\n cursor: grab;\n}\n\n.ae-rotate-handle:hover {\n fill: #ff6600;\n}\n\n.ae-rotate-line {\n stroke: #ff6600;\n stroke-width: 1;\n stroke-dasharray: 4;\n}\n\n/* 工具条样式 */\n.ae-toolbar {\n position: absolute;\n display: none;\n flex-direction: column;\n gap: 10px;\n padding: 12px;\n background: #fff;\n border: 1px solid #ddd;\n border-radius: 8px;\n box-shadow: 0 2px 12px rgba(0,0,0,0.15);\n z-index: 100;\n pointer-events: auto;\n min-width: 140px;\n}\n\n.ae-toolbar-drag-handle {\n cursor: grab;\n text-align: center;\n padding: 4px;\n color: #999;\n font-size: 14px;\n line-height: 1;\n user-select: none;\n border-bottom: 1px solid #eee;\n margin: -12px -12px 8px -12px;\n padding-top: 8px;\n padding-bottom: 8px;\n border-radius: 8px 8px 0 0;\n}\n\n.ae-toolbar-drag-handle:active {\n cursor: grabbing;\n}\n\n.ae-toolbar-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-toolbar-label {\n font-size: 11px;\n color: #666;\n}\n\n.ae-toolbar input[type="color"] {\n width: 40px;\n height: 30px;\n border: 1px solid #ddd;\n border-radius: 4px;\n cursor: pointer;\n padding: 0;\n background: none;\n}\n\n.ae-toolbar input[type="range"] {\n width: 120px;\n cursor: pointer;\n}\n\n.ae-toolbar-value {\n font-size: 10px;\n color: #999;\n text-align: right;\n}\n',document.head.appendChild(t)}exports.ArrowEditor=class{constructor(t,e={}){var s;this.container="string"==typeof t?document.querySelector(t):t,this.svg=null,this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this.lastClickTime=0,this.lastClickPos=null,this._shouldBlockClick=!1,this._defaultColor="#2b8cff",this.isCtrl=e.isCtrl||!1,this.stopPropagation=e.stopPropagation||!1,this.preventDefault=e.preventDefault||!1,this.onDrawEnd=e.onDrawEnd||null,this.onRemove=e.onRemove||null,this.onChange=e.onChange||null,this._defaultColor=e.defaultColor||this._defaultColor,this._strokeWidth=e.defaultStrokeWidth||8,this._curveRate=null!=(s=e.defaultCurveRate)?s:0,this._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._lastMousePos=null,this._createSVG(),this._initKeybindings(),this._initEvents()}_createSVG(){if("undefined"!=typeof getComputedStyle){"static"===getComputedStyle(this.container).position&&(this.container.style.position="relative")}this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.setAttribute("class","ae-d2-svg"),this.container.appendChild(this.svg);const t=document.createElementNS("http://www.w3.org/2000/svg","defs");this.svg.appendChild(t);const e=document.createElementNS("http://www.w3.org/2000/svg","marker");e.setAttribute("id","ae-arrowhead"),e.setAttribute("markerWidth","10"),e.setAttribute("markerHeight","10"),e.setAttribute("refX","9"),e.setAttribute("refY","5"),e.setAttribute("orient","auto");const s=document.createElementNS("http://www.w3.org/2000/svg","polygon");s.setAttribute("points","0,0 10,5 0,10 2,5"),s.setAttribute("fill",this._defaultColor),e.appendChild(s),t.appendChild(e)}_createToolbar(){var t,e;this._toolbar&&this._toolbar.remove(),this._toolbar=document.createElement("div"),this._toolbar.className="ae-toolbar";const s=this.selected.color||this._defaultColor,r=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0;this._toolbar.innerHTML=`\n <div class="ae-toolbar-drag-handle">:::</div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">颜色</span>\n <input type="color" class="ae-color-input" value="${s}" />\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">粗细</span>\n <input type="range" class="ae-stroke-input" min="1" max="60" value="${r}" />\n <span class="ae-toolbar-value">${r}px</span>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">曲线率</span>\n <input type="range" class="ae-round-input" min="0" max="1" step="0.1" value="${o}" />\n </div>\n `;this._toolbar.querySelector(".ae-color-input").addEventListener("input",t=>{this.selected&&(this.selected.color=t.target.value,this._defaultColor=t.target.value,this._updateMarkerColor(t.target.value),this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()}))});const n=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value");n.addEventListener("input",t=>{this.selected&&(this.selected.strokeWidth=parseInt(t.target.value),i.textContent=t.target.value+"px",this.render(),this.onChange&&this.onChange({type:"strokeWidth",arrow:this.selected,value:parseInt(t.target.value),arrows:this.getData()}))});this._toolbar.querySelector(".ae-round-input").addEventListener("input",t=>{this.selected&&(this.selected.curveRate=parseFloat(t.target.value),this.render(),this.onChange&&this.onChange({type:"curveRate",arrow:this.selected,value:parseFloat(t.target.value),arrows:this.getData()}))});const a=this._toolbar.querySelector(".ae-toolbar-drag-handle");this._setupToolbarDrag(a),this._toolbar.addEventListener("mousedown",t=>{t.stopPropagation()}),this._toolbar.addEventListener("mouseup",t=>{t.stopPropagation()}),this.container.appendChild(this._toolbar)}_setupToolbarDrag(t){let e=!1,s={x:0,y:0};t.addEventListener("mousedown",t=>{e=!0,this._toolbarDragging=!0;const r=this._toolbar.getBoundingClientRect();s.x=t.clientX-r.left,s.y=t.clientY-r.top,t.preventDefault(),t.stopPropagation();const o=t=>{if(!e)return;const r=this.container.getBoundingClientRect();let o=t.clientX-r.left-s.x,n=t.clientY-r.top-s.y;const i=this._toolbar.offsetWidth,a=this._toolbar.offsetHeight;o=Math.max(0,Math.min(o,r.width-i)),n=Math.max(0,Math.min(n,r.height-a)),this._toolbar.style.left=o+"px",this._toolbar.style.top=n+"px"},n=t=>{e=!1,this._toolbarDragging=!1,document.removeEventListener("mousemove",o),document.removeEventListener("mouseup",n),this._toolbar.removeEventListener("mouseup",n),t.preventDefault(),t.stopPropagation()};document.addEventListener("mousemove",o),document.addEventListener("mouseup",n),this._toolbar.addEventListener("mouseup",n)})}_showToolbar(){var t,e;if(this.selected){this._toolbar||this._createToolbar(),this._toolbar.style.display="flex";const s=this.selected.color||this._defaultColor,r=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0,n=this._toolbar.querySelector(".ae-color-input"),i=this._toolbar.querySelector(".ae-stroke-input"),a=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value"),l=this._toolbar.querySelector(".ae-round-input");n&&(n.value=s),i&&(i.value=r,a.textContent=r+"px"),l&&(l.value=o);const h=this._getArrowBBox(this.selected),d=this._toolbar.offsetWidth||150,c=this._toolbar.offsetHeight||120;let u=h.maxX+20;u+d>this.container.offsetWidth&&(u=h.minX-d-20);let p=h.centerY-c/2;p<0&&(p=0),p+c>this.container.offsetHeight&&(p=this.container.offsetHeight-c),this._toolbar.style.left=u+"px",this._toolbar.style.top=p+"px"}}_hideToolbar(){this._toolbar&&(this._toolbar.style.display="none")}_updateMarkerColor(t){const e=this.svg.querySelector("#ae-arrowhead polygon");e&&e.setAttribute("fill",t)}_initKeybindings(){this._kb=new n.Keybinding("arrow-editor-"+Math.random(),this.container),this._kb.on("enter",()=>{this._handleEnter()}),this._kb.on("esc",()=>{this._handleEsc()}),this._kb.on("delete",()=>{this._handleDelete()}),this._kb.on("backspace",()=>{this._handleDelete()}),this._kb.on("space",()=>{this._handleSpace()}),this._kb.on("arrowup",()=>{this._handleArrowKey(0,-1)}),this._kb.on("arrowdown",()=>{this._handleArrowKey(0,1)}),this._kb.on("arrowleft",()=>{this._handleArrowKey(-1,0)}),this._kb.on("arrowright",()=>{this._handleArrowKey(1,0)})}_handleSpace(){this.drawing&&this.current&&this._lastMousePos&&(this.current.points.push(((t,n)=>{for(var i in n||(n={}))s.call(n,i)&&o(t,i,n[i]);if(e)for(var i of e(n))r.call(n,i)&&o(t,i,n[i]);return t})({},this._lastMousePos)),this.render())}_handleArrowKey(t,e){if(!this.selected)return;this.selected.points.forEach(s=>{s.x+=1*t,s.y+=1*e}),this.render(),this.onChange&&this.onChange({type:"move",arrow:this.selected,arrows:this.getData()})}_initEvents(){this.container.onclick=t=>{if(this._toolbar&&(t.target===this._toolbar||this._toolbar.contains(t.target)))return;this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._handleClick(e,t)},this.container.onmousemove=t=>{this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._lastMousePos=e,this._handleMouseMove(t,e)},this.container.onmousedown=t=>{if((!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target))&&(this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation(),this.selected)){const e=t.target.getAttribute("data-handle");if(e){this._transformMode=e,this._transformHandle=e;const s=this._mousePos(t);if(this._transformStartPos=s,this._transformStartPoints=this.selected.points.map(t=>({x:t.x,y:t.y})),this._transformCenter=this._getArrowBBox(this.selected),"rotate"===e){const t=this._transformCenter,e=s.x-t.centerX,r=s.y-t.centerY;this._transformStartAngle=Math.atan2(r,e),this._rotationOffset=0}return void t.stopPropagation()}this.mode="move"}},this.container.onmouseup=t=>{this._transformMode&&this.selected&&this.onChange&&this.onChange({type:this._transformMode,arrow:this.selected,arrows:this.getData()}),this.mode=null,this._transformMode=null,this._transformHandle=null}}_mousePos(t){const e=this.container.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_generatePath(t,e=0){if(t.length<2)return"";if(0===e){let e=`M ${t[0].x} ${t[0].y}`;for(let s=1;s<t.length;s++)e+=` L ${t[s].x} ${t[s].y}`;return e}let s=`M ${t[0].x} ${t[0].y}`;for(let r=0;r<t.length-1;r++){const o=t[r],n=t[r+1],i=n.x-o.x,a=n.y-o.y,l=Math.hypot(i,a);if(0===l)continue;let h=i,d=a;if(r>0){const e=t[r-1];h=o.x-e.x,d=o.y-e.y}let c=i,u=a;if(r<t.length-2){const e=t[r+2];c=e.x-n.x,u=e.y-n.y}const p=Math.hypot(h,d)||1,g=Math.hypot(c,u)||1,f=h/p,_=d/p,m=c/g,b=u/g,v=l*e*.3;s+=` C ${o.x+f*v} ${o.y+_*v} ${n.x-m*v} ${n.y-b*v} ${n.x} ${n.y}`}return s}_generateArrowHead(t,e=8){if(t.length<2)return"";const s=t[t.length-1];let r=t[t.length-2];if(t.length>=3){Math.hypot(s.x-r.x,s.y-r.y)<5&&(r=t[t.length-3])}const o=s.x-r.x,n=s.y-r.y,i=Math.hypot(o,n);if(i<1)return"";const a=o/i,l=n/i,h=e/8,d=25*h,c=20*h,u=s.x,p=s.y,g=a*(d/2),f=l*(d/2),_=u+g-a*d,m=p+f-l*d,b=-l;return`M ${u+g} ${p+f} L ${_+b*c} ${m+a*c} L ${_-b*c} ${m-a*c} Z`}_createArrowGroup(t,e){var s,r;const o=document.createElementNS("http://www.w3.org/2000/svg","g");o.setAttribute("data-index",e);const n=t.color||this._defaultColor,i=t.strokeWidth||this._strokeWidth,a=null!=(r=null!=(s=t.curveRate)?s:t.cornerRoundness)?r:0,l=document.createElementNS("http://www.w3.org/2000/svg","path");l.setAttribute("class","ae-arrow-path"),l.style.stroke=n,l.style.strokeWidth=i+"px",l.setAttribute("d",this._generatePath(t.points,a)),o.appendChild(l);const h=document.createElementNS("http://www.w3.org/2000/svg","path");if(h.setAttribute("fill",n),h.setAttribute("d",this._generateArrowHead(t.points,i)),o.appendChild(h),t===this.selected){const e=this._getArrowBBox(t),s=document.createElementNS("http://www.w3.org/2000/svg","rect");s.setAttribute("class","ae-transform-box"),s.setAttribute("x",e.minX-10),s.setAttribute("y",e.minY-10),s.setAttribute("width",e.width+20),s.setAttribute("height",e.height+20),o.appendChild(s);const r=document.createElementNS("http://www.w3.org/2000/svg","circle");r.setAttribute("class","ae-transform-handle"),r.setAttribute("cx",e.maxX+10),r.setAttribute("cy",e.maxY+10),r.setAttribute("r",6),r.setAttribute("data-handle","scale"),o.appendChild(r);const n=e.minY-30,i=e.centerX,a=document.createElementNS("http://www.w3.org/2000/svg","line");a.setAttribute("class","ae-rotate-line"),a.setAttribute("x1",e.centerX),a.setAttribute("y1",e.minY-10),a.setAttribute("x2",i),a.setAttribute("y2",n),o.appendChild(a);const l=document.createElementNS("http://www.w3.org/2000/svg","circle");l.setAttribute("class","ae-rotate-handle"),l.setAttribute("cx",i),l.setAttribute("cy",n),l.setAttribute("r",8),l.setAttribute("data-handle","rotate"),o.appendChild(l)}return o}render(){if(this.svg.querySelectorAll("g").forEach(t=>t.remove()),this.arrows.forEach((t,e)=>{const s=this._createArrowGroup(t,e);this.svg.appendChild(s)}),this.current){const t=this._createArrowGroup(this.current,this.arrows.length);this.svg.appendChild(t)}}_isDoubleClick(t){const e=Date.now(),s=e-this.lastClickTime;return this.lastClickTime=e,s<300&&this.lastClickPos&&Math.hypot(t.x-this.lastClickPos.x,t.y-this.lastClickPos.y)<10?(this.lastClickPos=null,!0):(this.lastClickPos=t,!1)}_handleClick(t,e){if(!this.isCtrl||e.ctrlKey)if(this._shouldBlockClick)this._shouldBlockClick=!1;else if(this._isDoubleClick(t)){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}else{if(this.selected){for(const e of this.arrows)if(this._hitArrow(e,t))return void this.render();return this.selected=null,this._hideToolbar(),void this.render()}for(const e of this.arrows)if(this._hitArrow(e,t))return this.selected=e,this._showToolbar(),void this.render();this.drawing?this.current.points.push(t):(this.drawing=!0,this.current={points:[t,t],color:this._defaultColor},this.svg.classList.add("ae-d2-svg-fixed")),this.render()}}_handleEnter(){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_handleEsc(){this.drawing&&(this.drawing=!1,this.current=null,this.svg.classList.remove("ae-d2-svg-fixed")),this.selected&&(this.selected=null),this._hideColorPicker(),this._hideToolbar(),this.render()}_handleDelete(){if(this.selected){const t=this.selected,e=this.arrows.indexOf(this.selected);e>-1&&this.arrows.splice(e,1),this.selected=null,this._hideToolbar(),this.render(),this.onRemove&&this.onRemove({arrow:t,arrows:this.getData()})}}_showColorPicker(t){if(this._showingColorPicker)return void this._hideColorPicker();this._showingColorPicker=!0;const e=document.createElement("div");e.className="ae-color-picker-popup";const s=document.createElement("span");s.textContent="选择颜色",s.style.cssText="font-size: 12px; color: #666;";const r=document.createElement("input");r.type="color",r.value=this.selected.color||this._defaultColor,r.showPicker(),e.appendChild(s),e.appendChild(r);const o=this.container.getBoundingClientRect(),n=this._getArrowBBox(this.selected),i=o.left+n.minX-50,a=o.top+n.maxY+15;e.style.left=i+"px",e.style.top=a+"px",r.addEventListener("input",t=>{this.selected.color=t.target.value,this._defaultColor=t.target.value,this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()})});const l=t=>{e.contains(t.target)||(this._hideColorPicker(),document.removeEventListener("click",l))};document.body.appendChild(e),this._colorPickerPopup=e,document.addEventListener("click",l)}_hideColorPicker(){this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this._showingColorPicker=!1}deleteSelected(){this.selected&&(this.arrows=this.arrows.filter(t=>t!==this.selected),this.selected=null,this.render())}_handleMouseMove(t,e){if(!this._toolbarDragging&&(!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target)))if(!this.isCtrl||t.ctrlKey){if(this.drawing&&(this.current.points[this.current.points.length-1]=e,this.render()),this._transformMode&&this.selected)return"rotate"===this._transformMode?this._handleRotate(e):"scale"===this._transformMode&&this._handleScale(e),void this.render();if(this.selected&&"move"===this.mode){const e=t.movementX,s=t.movementY;0===e&&0===s||(this._shouldBlockClick=!0),this.selected.points.forEach(t=>{t.x+=e,t.y+=s}),this.render()}}else if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_getArrowBBox(t){const e=t.points;let s=1/0,r=1/0,o=-1/0,n=-1/0;for(const i of e)s=Math.min(s,i.x),r=Math.min(r,i.y),o=Math.max(o,i.x),n=Math.max(n,i.y);return{minX:s,minY:r,maxX:o,maxY:n,width:o-s,height:n-r,centerX:(s+o)/2,centerY:(r+n)/2}}_handleRotate(t){const e=this._transformCenter,s=e.centerX,r=e.centerY,o=Math.atan2(t.y-r,t.x-s)-Math.atan2(this._transformStartPos.y-r,this._transformStartPos.x-s),n=Math.cos(o),i=Math.sin(o);this.selected.points.forEach((t,e)=>{const o=this._transformStartPoints[e].x-s,a=this._transformStartPoints[e].y-r;t.x=s+o*n-a*i,t.y=r+o*i+a*n})}_handleScale(t){const e=this._transformCenter,s=e.centerX,r=e.centerY,o=this._transformStartPoints,n=this._transformStartPos,i=t.x-s,a=t.y-r,l=n.x-s,h=n.y-r,d=Math.hypot(i,a)/Math.hypot(l,h);this.selected.points.forEach((t,e)=>{t.x=s+(o[e].x-s)*d,t.y=r+(o[e].y-r)*d})}_hitArrow(t,e){for(let s=0;s<t.points.length-1;s++)if(this._dist(e,t.points[s],t.points[s+1])<15)return!0;return!1}_dist(t,e,s){const r=s.x-e.x,o=s.y-e.y,n=((t.x-e.x)*r+(t.y-e.y)*o)/(r*r+o*o),i=Math.max(0,Math.min(1,n)),a=e.x+i*r,l=e.y+i*o;return Math.hypot(t.x-a,t.y-l)}getData(){return this.arrows.map(t=>{var e,s;return{points:t.points,curveRate:null!=(s=null!=(e=t.curveRate)?e:t.cornerRoundness)?s:0,strokeWidth:t.strokeWidth,color:t.color}})}setData(t){this.arrows=t.map(t=>{var e,s;return{points:t.points,curveRate:null!=(e=t.curveRate)?e:0,strokeWidth:null!=(s=t.strokeWidth)?s:8,color:t.color}}),this.render()}clear(){this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.render()}destroy(){this._kb&&this._kb.destroy&&this._kb.destroy(),this.container.onclick=null,this.container.onmousemove=null,this.container.onmousedown=null,this.container.onmouseup=null,this.container.ondblclick=null,this.svg&&(this.svg.remove(),this.svg=null),this._toolbar&&(this._toolbar.remove(),this._toolbar=null),this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this._transformMode=null,this._transformHandle=null}};
|
|
1
|
+
"use strict";var t=Object.defineProperty,e=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,n=Object.prototype.propertyIsEnumerable,o=(e,s,n)=>s in e?t(e,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[s]=n,r=(t,r)=>{for(var a in r||(r={}))s.call(r,a)&&o(t,a,r[a]);if(e)for(var a of e(r))n.call(r,a)&&o(t,a,r[a]);return t};Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("@wbiokr/keybinding");if("undefined"!=typeof document){const t=document.createElement("style");t.textContent='\n.ae-d2-container {\n position: relative;\n width: 1000px;\n height: 600px;\n background: #fff;\n margin: auto;\n}\n\n.ae-d2-svg {\n width: 100%;\n height: 100%;\n position: absolute;\n left: 0;\n top: 0;\n z-index: 10;\n}\n\n\n.ae-arrow-path {\n fill: none;\n stroke-linejoin: round;\n cursor: pointer;\n}\n\n.ae-arrow-path:hover {\n stroke: #00aaff;\n}\n\n.ae-transform-box {\n fill: none;\n stroke: #00aaff;\n stroke-width: 2;\n stroke-dasharray: 4;\n}\n\n.ae-transform-handle {\n fill: #fff;\n stroke: #00aaff;\n stroke-width: 2;\n cursor: pointer;\n}\n\n.ae-transform-handle:hover {\n fill: #00aaff;\n}\n\n.ae-rotate-handle {\n fill: #fff;\n stroke: #ff6600;\n stroke-width: 2;\n cursor: grab;\n}\n\n.ae-rotate-handle:hover {\n fill: #ff6600;\n}\n\n.ae-rotate-line {\n stroke: #ff6600;\n stroke-width: 1;\n stroke-dasharray: 4;\n}\n\n/* 工具条样式 */\n.ae-toolbar {\n position: fixed;\n display: none;\n flex-direction: column;\n gap: 10px;\n padding: 12px;\n background: #fff;\n border: 1px solid #ddd;\n border-radius: 8px;\n box-shadow: 0 2px 12px rgba(0,0,0,0.15);\n z-index: 10000;\n pointer-events: auto;\n min-width: 140px;\n}\n\n.ae-toolbar-drag-handle {\n cursor: grab;\n text-align: center;\n padding: 4px;\n color: #999;\n font-size: 14px;\n line-height: 1;\n user-select: none;\n border-bottom: 1px solid #eee;\n margin: -12px -12px 8px -12px;\n padding-top: 8px;\n padding-bottom: 8px;\n border-radius: 8px 8px 0 0;\n}\n\n.ae-toolbar-drag-handle:active {\n cursor: grabbing;\n}\n\n.ae-toolbar-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-toolbar-row {\n display: flex;\n gap: 8px;\n}\n\n.ae-toolbar-label {\n font-size: 11px;\n color: #666;\n}\n\n.ae-scale-btn {\n flex: 1;\n padding: 6px 8px;\n background: #f0f0f0;\n color: #333;\n border: 1px solid #ccc;\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n transition: background 0.2s;\n}\n\n.ae-scale-btn:hover {\n background: #e0e0e0;\n}\n\n.ae-scale-btn:active {\n background: #d0d0d0;\n}\n\n.ae-toolbar input[type="color"] {\n width: 40px;\n height: 30px;\n border: 1px solid #ddd;\n border-radius: 4px;\n cursor: pointer;\n padding: 0;\n background: none;\n}\n\n.ae-toolbar input[type="range"] {\n width: 120px;\n cursor: pointer;\n}\n\n.ae-toolbar-value {\n font-size: 10px;\n color: #999;\n text-align: right;\n}\n',document.head.appendChild(t)}exports.ArrowEditor=class{constructor(t,e={}){var s;this.container="string"==typeof t?document.querySelector(t):t,this.svg=null,this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this.lastClickTime=0,this.lastClickPos=null,this._shouldBlockClick=!1,this._defaultColor="#2b8cff",this.isCtrl=e.isCtrl||!1,this.stopPropagation=e.stopPropagation||!1,this.preventDefault=e.preventDefault||!1,this.onDrawEnd=e.onDrawEnd||null,this.onRemove=e.onRemove||null,this.onChange=e.onChange||null,this._defaultColor=e.defaultColor||this._defaultColor,this._strokeWidth=e.defaultStrokeWidth||8,this._curveRate=null!=(s=e.defaultCurveRate)?s:0,this._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._lastMousePos=null,this._createSVG(),this._initKeybindings(),this._initEvents()}_createSVG(){if("undefined"!=typeof getComputedStyle){"static"===getComputedStyle(this.container).position&&(this.container.style.position="relative")}this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.setAttribute("class","ae-d2-svg"),this.container.appendChild(this.svg);const t=document.createElementNS("http://www.w3.org/2000/svg","defs");this.svg.appendChild(t);const e=document.createElementNS("http://www.w3.org/2000/svg","marker");e.setAttribute("id","ae-arrowhead"),e.setAttribute("markerWidth","10"),e.setAttribute("markerHeight","10"),e.setAttribute("refX","9"),e.setAttribute("refY","5"),e.setAttribute("orient","auto");const s=document.createElementNS("http://www.w3.org/2000/svg","polygon");s.setAttribute("points","0,0 10,5 0,10 2,5"),s.setAttribute("fill",this._defaultColor),e.appendChild(s),t.appendChild(e)}_createToolbar(){var t,e;this._toolbar&&this._toolbar.remove(),this._toolbar=document.createElement("div"),this._toolbar.className="ae-toolbar";const s=this.selected.color||this._defaultColor,n=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0;this._toolbar.innerHTML=`\n <div class="ae-toolbar-drag-handle">:::</div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">颜色</span>\n <input type="color" class="ae-color-input" value="${s}" />\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">粗细</span>\n <input type="range" class="ae-stroke-input" min="1" max="60" value="${n}" />\n <span class="ae-toolbar-value">${n}px</span>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">曲线率</span>\n <input type="range" class="ae-round-input" min="0" max="1" step="0.1" value="${o}" />\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">缩放</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-axis="x">X 缩放</button>\n <button class="ae-scale-btn" data-axis="y">Y 缩放</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">3D 旋转</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-axis="x-rotate">X 轴</button>\n <button class="ae-scale-btn" data-axis="y-rotate">Y 轴</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">2.5D 挤出</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-mode="extrude-up">上挤出</button>\n <button class="ae-scale-btn" data-mode="extrude-down">下挤出</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-mode="extrude-left">左挤出</button>\n <button class="ae-scale-btn" data-mode="extrude-right">右挤出</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-mode="reset">重置</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">2.5D 透视</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-perspective="top">上透视</button>\n <button class="ae-scale-btn" data-perspective="bottom">下透视</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-perspective="left">左透视</button>\n <button class="ae-scale-btn" data-perspective="right">右透视</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">倾斜</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-skew="x-left">左倾斜</button>\n <button class="ae-scale-btn" data-skew="x-right">右倾斜</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-skew="y-up">上倾斜</button>\n <button class="ae-scale-btn" data-skew="y-down">下倾斜</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-mode="reset">重置</button>\n </div>\n </div>\n `;this._toolbar.querySelector(".ae-color-input").addEventListener("input",t=>{this.selected&&(this.selected.color=t.target.value,this._defaultColor=t.target.value,this._updateMarkerColor(t.target.value),this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()}))});const a=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value");a.addEventListener("input",t=>{this.selected&&(this.selected.strokeWidth=parseInt(t.target.value),i.textContent=t.target.value+"px",this.render(),this.onChange&&this.onChange({type:"strokeWidth",arrow:this.selected,value:parseInt(t.target.value),arrows:this.getData()}))});this._toolbar.querySelector(".ae-round-input").addEventListener("input",t=>{this.selected&&(this.selected.curveRate=parseFloat(t.target.value),this.render(),this.onChange&&this.onChange({type:"curveRate",arrow:this.selected,value:parseFloat(t.target.value),arrows:this.getData()}))});this._toolbar.querySelectorAll(".ae-scale-btn[data-axis]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.axis;if("x-rotate"===e)return void this._startRotate3D("x");if("y-rotate"===e)return void this._startRotate3D("y");this._transformMode="scale",this._transformAxis=e,this._transformCenter=this._getArrowBBox(this.selected),this._transformStartPoints=this.selected.points.map(t=>r({},t));const s=this._getArrowBBox(this.selected);this._transformStartPos="x"===e?{x:s.maxX+10,y:s.centerY}:{x:s.centerX,y:s.maxY+10};const n=t=>{const s=this._mousePos(t);"x"===e?this._handleScaleX(s):this._handleScaleY(s),this.render()},o=()=>{document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",o),this.onChange&&this.onChange({type:"scale",arrow:this.selected,arrows:this.getData()}),this._transformMode=null,this._transformAxis=null};document.addEventListener("mousemove",n),document.addEventListener("mouseup",o)})});this._toolbar.querySelectorAll(".ae-scale-btn[data-mode]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.mode;"extrude-up"===e?this._applyExtrude(0,-15):"extrude-down"===e?this._applyExtrude(0,15):"extrude-left"===e?this._applyExtrude(-15,0):"extrude-right"===e?this._applyExtrude(15,0):"reset"===e&&this._resetExtrude()})});this._toolbar.querySelectorAll(".ae-scale-btn[data-perspective]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.perspective;"top"===e?this._applyPerspective("top"):"bottom"===e?this._applyPerspective("bottom"):"left"===e?this._applyPerspective("left"):"right"===e&&this._applyPerspective("right")})});this._toolbar.querySelectorAll(".ae-scale-btn[data-skew]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.skew;"x-left"===e?this._applySkew("x-left"):"x-right"===e?this._applySkew("x-right"):"y-up"===e?this._applySkew("y-up"):"y-down"===e&&this._applySkew("y-down")})});const l=this._toolbar.querySelector(".ae-toolbar-drag-handle");this._setupToolbarDrag(l),this._toolbar.addEventListener("mousedown",t=>{t.stopPropagation()}),this._toolbar.addEventListener("mouseup",t=>{t.stopPropagation()}),document.body.appendChild(this._toolbar)}_setupToolbarDrag(t){let e=!1,s={x:0,y:0};t.addEventListener("mousedown",t=>{e=!0,this._toolbarDragging=!0;const n=this._toolbar.getBoundingClientRect();s.x=t.clientX-n.left,s.y=t.clientY-n.top,t.preventDefault(),t.stopPropagation();const o=t=>{if(!e)return;let n=t.clientX-s.x,o=t.clientY-s.y;this._toolbar.style.left=n+"px",this._toolbar.style.top=o+"px"},r=t=>{e=!1,this._toolbarDragging=!1,document.removeEventListener("mousemove",o),document.removeEventListener("mouseup",r),this._toolbar.removeEventListener("mouseup",r),t.preventDefault(),t.stopPropagation()};document.addEventListener("mousemove",o),document.addEventListener("mouseup",r),this._toolbar.addEventListener("mouseup",r)})}_showToolbar(){var t,e;if(this.selected){this._toolbar||this._createToolbar(),this._toolbar.style.display="flex";const s=this.selected.color||this._defaultColor,n=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0,r=this._toolbar.querySelector(".ae-color-input"),a=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value"),l=this._toolbar.querySelector(".ae-round-input");r&&(r.value=s),a&&(a.value=n,i.textContent=n+"px"),l&&(l.value=o);const h=this.container.getBoundingClientRect(),c=this._getArrowBBox(this.selected),d=this._toolbar.offsetWidth||150,u=this._toolbar.offsetHeight||120;let p=h.left+c.maxX+20;p+d>window.innerWidth-10&&(p=h.left+c.minX-d-20);let g=h.top+c.centerY-u/2;g<10&&(g=10),g+u>window.innerHeight-10&&(g=window.innerHeight-u-10),this._toolbar.style.left=p+"px",this._toolbar.style.top=g+"px"}}_hideToolbar(){this._toolbar&&(this._toolbar.style.display="none")}_updateMarkerColor(t){const e=this.svg.querySelector("#ae-arrowhead polygon");e&&e.setAttribute("fill",t)}_initKeybindings(){this._kb=new a.Keybinding("arrow-editor-"+Math.random(),this.container),this._kb.on("enter",()=>{this._handleEnter()}),this._kb.on("esc",()=>{this._handleEsc()}),this._kb.on("delete",()=>{this._handleDelete()}),this._kb.on("backspace",()=>{this._handleDelete()}),this._kb.on("space",()=>{this._handleSpace()}),this._kb.on("arrowup",()=>{this._handleArrowKey(0,-1)}),this._kb.on("arrowdown",()=>{this._handleArrowKey(0,1)}),this._kb.on("arrowleft",()=>{this._handleArrowKey(-1,0)}),this._kb.on("arrowright",()=>{this._handleArrowKey(1,0)})}_handleSpace(){this.drawing&&this.current&&this._lastMousePos&&(this.current.points.push(r({},this._lastMousePos)),this.render())}_handleArrowKey(t,e){if(!this.selected)return;this.selected.points.forEach(s=>{s.x+=1*t,s.y+=1*e}),this.render(),this.onChange&&this.onChange({type:"move",arrow:this.selected,arrows:this.getData()})}_initEvents(){this.container.onclick=t=>{if(this._toolbar&&(t.target===this._toolbar||this._toolbar.contains(t.target)))return;this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._handleClick(e,t)},this.container.onmousemove=t=>{this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._lastMousePos=e,this._handleMouseMove(t,e)},this.container.onmousedown=t=>{if((!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target))&&(this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation(),this.selected)){const e=t.target.getAttribute("data-handle");if(e){this._transformMode="scaleX"===e||"scaleY"===e?"scale":e,this._transformHandle=e,this._transformAxis="scaleX"===e?"x":"scaleY"===e?"y":null;const s=this._mousePos(t);if(this._transformStartPos=s,this._transformStartPoints=this.selected.points.map(t=>({x:t.x,y:t.y})),this._transformCenter=this._getArrowBBox(this.selected),"rotate"===e){const t=this._transformCenter,e=s.x-t.centerX,n=s.y-t.centerY;this._transformStartAngle=Math.atan2(n,e),this._rotationOffset=0}return void t.stopPropagation()}this.mode="move"}},this.container.onmouseup=t=>{this._transformMode&&this.selected&&this.onChange&&this.onChange({type:this._transformMode,arrow:this.selected,arrows:this.getData()}),this.mode=null,this._transformMode=null,this._transformHandle=null,this._transformAxis=null}}_mousePos(t){const e=this.container.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_generatePath(t,e=0){if(t.length<2)return"";if(0===e){let e=`M ${t[0].x} ${t[0].y}`;for(let s=1;s<t.length;s++)e+=` L ${t[s].x} ${t[s].y}`;return e}let s=`M ${t[0].x} ${t[0].y}`;for(let n=0;n<t.length-1;n++){const o=t[n],r=t[n+1],a=r.x-o.x,i=r.y-o.y,l=Math.hypot(a,i);if(0===l)continue;let h=a,c=i;if(n>0){const e=t[n-1];h=o.x-e.x,c=o.y-e.y}let d=a,u=i;if(n<t.length-2){const e=t[n+2];d=e.x-r.x,u=e.y-r.y}const p=Math.hypot(h,c)||1,g=Math.hypot(d,u)||1,m=h/p,b=c/p,_=d/g,f=u/g,x=l*e*.3;s+=` C ${o.x+m*x} ${o.y+b*x} ${r.x-_*x} ${r.y-f*x} ${r.x} ${r.y}`}return s}_generateArrowHead(t,e=8){if(t.length<2)return"";const s=t[t.length-1];let n=t[t.length-2];if(t.length>=3){Math.hypot(s.x-n.x,s.y-n.y)<5&&(n=t[t.length-3])}const o=s.x-n.x,r=s.y-n.y,a=Math.hypot(o,r);if(a<1)return"";const i=o/a,l=r/a,h=e/8,c=22*h,d=20*h,u=s.x,p=s.y,g=i*(c/2),m=l*(c/2),b=u+g-i*c,_=p+m-l*c,f=-l;return`M ${u+g} ${p+m} L ${b+f*d} ${_+i*d} L ${b-f*d} ${_-i*d} Z`}_createArrowGroup(t,e){var s,n;const o=document.createElementNS("http://www.w3.org/2000/svg","g");o.setAttribute("data-index",e);const r=t.color||this._defaultColor,a=t.strokeWidth||this._strokeWidth,i=null!=(n=null!=(s=t.curveRate)?s:t.cornerRoundness)?n:0,l=t.extrude||{x:0,y:0};if(Math.max(Math.abs(l.x),Math.abs(l.y))>0){const e=l.x>0?1:-1,s=l.y>0?1:-1,n=Math.max(Math.abs(l.x),Math.abs(l.y));for(let r=1;r<=n;r++){const n=e*r,l=s*r,h=document.createElementNS("http://www.w3.org/2000/svg","path");h.setAttribute("class","ae-arrow-path"),h.style.stroke="#ccc",h.style.strokeWidth=a+"px",h.style.opacity="0.15",h.setAttribute("d",this._generatePath(t.points.map(t=>({x:t.x+n,y:t.y+l})),i)),o.appendChild(h);const c=document.createElementNS("http://www.w3.org/2000/svg","path");c.setAttribute("fill","#ccc"),c.setAttribute("fill-opacity","0.15"),c.setAttribute("d",this._generateArrowHead(t.points.map(t=>({x:t.x+n,y:t.y+l})),a)),o.appendChild(c)}}const h=document.createElementNS("http://www.w3.org/2000/svg","path");h.setAttribute("class","ae-arrow-path"),h.style.stroke=r,h.style.strokeWidth=a+"px",h.setAttribute("d",this._generatePath(t.points,i)),o.appendChild(h);const c=document.createElementNS("http://www.w3.org/2000/svg","path");if(c.setAttribute("fill",r),c.setAttribute("d",this._generateArrowHead(t.points,a)),o.appendChild(c),t===this.selected){const e=this._getArrowBBox(t),s=document.createElementNS("http://www.w3.org/2000/svg","rect");s.setAttribute("class","ae-transform-box"),s.setAttribute("x",e.minX-10),s.setAttribute("y",e.minY-10),s.setAttribute("width",e.width+20),s.setAttribute("height",e.height+20),o.appendChild(s);const n=document.createElementNS("http://www.w3.org/2000/svg","circle");n.setAttribute("class","ae-transform-handle"),n.setAttribute("cx",e.maxX+10),n.setAttribute("cy",e.maxY+10),n.setAttribute("r",6),n.setAttribute("data-handle","scale"),o.appendChild(n);const r=document.createElementNS("http://www.w3.org/2000/svg","circle");r.setAttribute("class","ae-transform-handle"),r.setAttribute("cx",e.maxX+10),r.setAttribute("cy",e.centerY),r.setAttribute("r",6),r.setAttribute("data-handle","scaleX"),o.appendChild(r);const a=document.createElementNS("http://www.w3.org/2000/svg","circle");a.setAttribute("class","ae-transform-handle"),a.setAttribute("cx",e.centerX),a.setAttribute("cy",e.maxY+10),a.setAttribute("r",6),a.setAttribute("data-handle","scaleY"),o.appendChild(a);const i=e.minY-30,l=e.centerX,h=document.createElementNS("http://www.w3.org/2000/svg","line");h.setAttribute("class","ae-rotate-line"),h.setAttribute("x1",e.centerX),h.setAttribute("y1",e.minY-10),h.setAttribute("x2",l),h.setAttribute("y2",i),o.appendChild(h);const c=document.createElementNS("http://www.w3.org/2000/svg","circle");c.setAttribute("class","ae-rotate-handle"),c.setAttribute("cx",l),c.setAttribute("cy",i),c.setAttribute("r",8),c.setAttribute("data-handle","rotate"),o.appendChild(c)}return o}render(){if(this.svg.querySelectorAll("g").forEach(t=>t.remove()),this.arrows.forEach((t,e)=>{const s=this._createArrowGroup(t,e);this.svg.appendChild(s)}),this.current){const t=this._createArrowGroup(this.current,this.arrows.length);this.svg.appendChild(t)}}_isDoubleClick(t){const e=Date.now(),s=e-this.lastClickTime;return this.lastClickTime=e,s<300&&this.lastClickPos&&Math.hypot(t.x-this.lastClickPos.x,t.y-this.lastClickPos.y)<10?(this.lastClickPos=null,!0):(this.lastClickPos=t,!1)}_handleClick(t,e){if(!this.isCtrl||e.ctrlKey)if(this._shouldBlockClick)this._shouldBlockClick=!1;else if(this._isDoubleClick(t)){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}else{if(this.selected){for(const e of this.arrows)if(this._hitArrow(e,t))return void this.render();return this.selected=null,this._hideToolbar(),void this.render()}for(const e of this.arrows)if(this._hitArrow(e,t))return this.selected=e,this._showToolbar(),void this.render();this.drawing?this.current.points.push(t):(this.drawing=!0,this.current={points:[t,t],color:this._defaultColor},this.svg.classList.add("ae-d2-svg-fixed")),this.render()}}_handleEnter(){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_handleEsc(){this.drawing&&(this.drawing=!1,this.current=null,this.svg.classList.remove("ae-d2-svg-fixed")),this.selected&&(this.selected=null),this._hideColorPicker(),this._hideToolbar(),this.render()}_handleDelete(){if(this.selected){const t=this.selected,e=this.arrows.indexOf(this.selected);e>-1&&this.arrows.splice(e,1),this.selected=null,this._hideToolbar(),this.render(),this.onRemove&&this.onRemove({arrow:t,arrows:this.getData()})}}_showColorPicker(t){if(this._showingColorPicker)return void this._hideColorPicker();this._showingColorPicker=!0;const e=document.createElement("div");e.className="ae-color-picker-popup";const s=document.createElement("span");s.textContent="选择颜色",s.style.cssText="font-size: 12px; color: #666;";const n=document.createElement("input");n.type="color",n.value=this.selected.color||this._defaultColor,n.showPicker(),e.appendChild(s),e.appendChild(n);const o=this.container.getBoundingClientRect(),r=this._getArrowBBox(this.selected),a=o.left+r.minX-50,i=o.top+r.maxY+15;e.style.left=a+"px",e.style.top=i+"px",n.addEventListener("input",t=>{this.selected.color=t.target.value,this._defaultColor=t.target.value,this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()})});const l=t=>{e.contains(t.target)||(this._hideColorPicker(),document.removeEventListener("click",l))};document.body.appendChild(e),this._colorPickerPopup=e,document.addEventListener("click",l)}_hideColorPicker(){this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this._showingColorPicker=!1}deleteSelected(){this.selected&&(this.arrows=this.arrows.filter(t=>t!==this.selected),this.selected=null,this.render())}_handleMouseMove(t,e){if(!this._toolbarDragging&&(!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target)))if(!this.isCtrl||t.ctrlKey){if(this.drawing&&(this.current.points[this.current.points.length-1]=e,this.render()),this._transformMode&&this.selected)return"rotate"===this._transformMode?this._handleRotate(e):"scale"===this._transformMode?"x"===this._transformAxis?this._handleScaleX(e):"y"===this._transformAxis?this._handleScaleY(e):this._handleScale(e):"rotate3d"===this._transformMode&&this._handleRotate3D(e),void this.render();if(this.selected&&"move"===this.mode){const e=t.movementX,s=t.movementY;0===e&&0===s||(this._shouldBlockClick=!0),this.selected.points.forEach(t=>{t.x+=e,t.y+=s}),this.render()}}else if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_getArrowBBox(t){const e=t.points;let s=1/0,n=1/0,o=-1/0,r=-1/0;for(const a of e)s=Math.min(s,a.x),n=Math.min(n,a.y),o=Math.max(o,a.x),r=Math.max(r,a.y);return{minX:s,minY:n,maxX:o,maxY:r,width:o-s,height:r-n,centerX:(s+o)/2,centerY:(n+r)/2}}_handleRotate(t){const e=this._transformCenter,s=e.centerX,n=e.centerY,o=Math.atan2(t.y-n,t.x-s)-Math.atan2(this._transformStartPos.y-n,this._transformStartPos.x-s),r=Math.cos(o),a=Math.sin(o);this.selected.points.forEach((t,e)=>{const o=this._transformStartPoints[e].x-s,i=this._transformStartPoints[e].y-n;t.x=s+o*r-i*a,t.y=n+o*a+i*r})}_handleScale(t){const e=this._transformCenter,s=e.centerX,n=e.centerY,o=this._transformStartPoints,r=this._transformStartPos,a=t.x-s,i=t.y-n,l=r.x-s,h=r.y-n,c=Math.hypot(a,i)/Math.hypot(l,h);this.selected.points.forEach((t,e)=>{t.x=s+(o[e].x-s)*c,t.y=n+(o[e].y-n)*c})}_handleScaleX(t){const e=this._transformCenter.centerX,s=this._transformStartPoints,n=this._transformStartPos,o=t.x-e,r=n.x-e,a=0!==r?o/r:1;this.selected.points.forEach((t,n)=>{t.x=e+(s[n].x-e)*a,t.y=s[n].y})}_handleScaleY(t){const e=this._transformCenter.centerY,s=this._transformStartPoints,n=this._transformStartPos,o=t.y-e,r=n.y-e,a=0!==r?o/r:1;this.selected.points.forEach((t,n)=>{t.x=s[n].x,t.y=e+(s[n].y-e)*a})}_startRotate3D(t){if(!this.selected)return;this._transformMode="rotate3d",this._transformAxis=t,this._transformCenter=this._getArrowBBox(this.selected),this._transformStartPoints=this.selected.points.map(t=>r({},t)),this._rotation3DStartAngle=0;const e=this._getArrowBBox(this.selected);this._transformStartPos="x"===t?{x:e.maxX+50,y:e.centerY}:{x:e.centerX,y:e.maxY+50};const s=t=>{const e=this._mousePos(t);this._handleRotate3D(e),this.render()},n=()=>{document.removeEventListener("mousemove",s),document.removeEventListener("mouseup",n),this.onChange&&this.onChange({type:"rotate3d",arrow:this.selected,value:t,arrows:this.getData()}),this._transformMode=null,this._transformAxis=null};document.addEventListener("mousemove",s),document.addEventListener("mouseup",n)}_handleRotate3D(t){const e=this._transformCenter,s=this._transformStartPoints;if("x"===this._transformAxis){const n=t.y-this._transformStartPos.y,o=Math.max(-90,Math.min(90,.9*-n)),r=Math.cos(o*Math.PI/180);this.selected.points.forEach((t,n)=>{t.x=s[n].x,t.y=e.centerY+(s[n].y-e.centerY)*r})}else{const n=t.x-this._transformStartPos.x,o=Math.max(-90,Math.min(90,.9*n)),r=Math.cos(o*Math.PI/180);this.selected.points.forEach((t,n)=>{t.x=e.centerX+(s[n].x-e.centerX)*r,t.y=s[n].y})}}_applyExtrude(t,e){this.selected&&(this._originalPoints||(this._originalPoints=this.selected.points.map(t=>r({},t))),this.selected.extrude={x:t,y:e},this.render(),this.onChange&&this.onChange({type:"extrude",arrow:this.selected,value:{x:t,y:e},arrows:this.getData()}))}_applySkew(t){if(!this.selected)return;const e=this._getArrowBBox(this.selected),s=e.centerX,n=e.centerY;this._originalPoints||(this._originalPoints=this.selected.points.map(t=>r({},t)));const o=.3;this.selected.points.forEach((r,a)=>{const i=this._originalPoints[a];if("x-left"===t){const t=i.y-n,s=e.height||1,a=t/s*o*s;r.x=i.x-a,r.y=i.y}else if("x-right"===t){const t=i.y-n,s=e.height||1,a=t/s*o*s;r.x=i.x+a,r.y=i.y}else if("y-up"===t){const t=i.x-s,n=e.width||1,a=t/n*o*n;r.x=i.x,r.y=i.y-a}else if("y-down"===t){const t=i.x-s,n=e.width||1,a=t/n*o*n;r.x=i.x,r.y=i.y+a}}),this.render(),this.onChange&&this.onChange({type:"skew",arrow:this.selected,value:t,arrows:this.getData()})}_applyPerspective(t){if(!this.selected)return;const e=this._getArrowBBox(this.selected),s=e.centerX,n=e.centerY;this._originalPoints||(this._originalPoints=this.selected.points.map(t=>r({},t)));const o=.3;this.selected.points.forEach((r,a)=>{const i=this._originalPoints[a];if("top"===t){const t=1-(1-(i.y-e.minY)/(e.height||1))*o;r.x=s+(i.x-s)*t,r.y=i.y}else if("bottom"===t){const t=1-(1-(e.maxY-i.y)/(e.height||1))*o;r.x=s+(i.x-s)*t,r.y=i.y}else if("left"===t){const t=1-(1-(i.x-e.minX)/(e.width||1))*o;r.x=i.x,r.y=n+(i.y-n)*t}else if("right"===t){const t=1-(1-(e.maxX-i.x)/(e.width||1))*o;r.x=i.x,r.y=n+(i.y-n)*t}}),this.render(),this.onChange&&this.onChange({type:"perspective",arrow:this.selected,value:t,arrows:this.getData()})}_resetExtrude(){this.selected&&(this.selected.extrude=null,this._originalPoints=null,this.render(),this.onChange&&this.onChange({type:"reset",arrow:this.selected,arrows:this.getData()}))}_hitArrow(t,e){for(let s=0;s<t.points.length-1;s++)if(this._dist(e,t.points[s],t.points[s+1])<15)return!0;return!1}_dist(t,e,s){const n=s.x-e.x,o=s.y-e.y,r=((t.x-e.x)*n+(t.y-e.y)*o)/(n*n+o*o),a=Math.max(0,Math.min(1,r)),i=e.x+a*n,l=e.y+a*o;return Math.hypot(t.x-i,t.y-l)}getData(){return this.arrows.map(t=>{var e,s;return{points:t.points,curveRate:null!=(s=null!=(e=t.curveRate)?e:t.cornerRoundness)?s:0,strokeWidth:t.strokeWidth,color:t.color}})}setData(t){this.arrows=t.map(t=>{var e,s;return{points:t.points,curveRate:null!=(e=t.curveRate)?e:0,strokeWidth:null!=(s=t.strokeWidth)?s:8,color:t.color}}),this.render()}clear(){this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.render()}destroy(){this._kb&&this._kb.destroy&&this._kb.destroy(),this.container.onclick=null,this.container.onmousemove=null,this.container.onmousedown=null,this.container.onmouseup=null,this.container.ondblclick=null,this.svg&&(this.svg.remove(),this.svg=null),this._toolbar&&(this._toolbar.remove(),this._toolbar=null),this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this._transformMode=null,this._transformHandle=null,this._originalPoints=null}};
|
|
2
2
|
//# sourceMappingURL=bundle.cjs.js.map
|
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: absolute;\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: 100;\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-label {\r\n font-size: 11px;\r\n color: #666;\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 `\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 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 this.container.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 const containerRect = this.container.getBoundingClientRect()\r\n let newLeft = moveEvent.clientX - containerRect.left - dragOffset.x\r\n let newTop = moveEvent.clientY - containerRect.top - dragOffset.y\r\n const toolbarWidth = this._toolbar.offsetWidth\r\n const toolbarHeight = this._toolbar.offsetHeight\r\n newLeft = Math.max(0, Math.min(newLeft, containerRect.width - toolbarWidth))\r\n newTop = Math.max(0, Math.min(newTop, containerRect.height - toolbarHeight))\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 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 = bbox.maxX + 20\r\n if (left + toolbarWidth > this.container.offsetWidth) {\r\n left = bbox.minX - toolbarWidth - 20\r\n }\r\n\r\n // 垂直居中于箭头\r\n let top = bbox.centerY - toolbarHeight / 2\r\n if (top < 0) top = 0\r\n if (top + toolbarHeight > this.container.offsetHeight) {\r\n top = this.container.offsetHeight - toolbarHeight\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\r\n this._transformHandle = handle\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 }\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 = 25 * 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 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 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 // 旋转手柄(顶部中间)\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 this._handleScale(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 _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 }\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","dragHandle","_setupToolbarDrag","isDragging","dragOffset","x","y","_toolbarDragging","rect","getBoundingClientRect","clientX","left","clientY","top","onMove","moveEvent","containerRect","newLeft","newTop","toolbarWidth","offsetWidth","toolbarHeight","offsetHeight","Math","max","min","width","height","onUp","removeEventListener","_showToolbar","display","colorInput","roundInput","bbox","_getArrowBBox","maxX","minX","centerY","_hideToolbar","_kb","Keybinding","random","on","_handleEnter","_handleEsc","_handleDelete","_handleSpace","_handleArrowKey","points","push","__spreadValues","dx","dy","forEach","pt","onclick","contains","p","_mousePos","_handleClick","onmousemove","_handleMouseMove","onmousedown","handle","getAttribute","map","center","centerX","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","path","stroke","arrowHead","minY","scaleHandle","maxY","rotateY","rotateX","rotateLine","rotateHandle","querySelectorAll","_isDoubleClick","now","Date","dt","ctrlKey","classList","a","_hitArrow","add","_hideColorPicker","indexOf","splice","_showColorPicker","_showingColorPicker","popup","label","cssText","showPicker","ev","closeHandler","body","_colorPickerPopup","deleteSelected","filter","_handleRotate","_handleScale","movementX","movementY","Infinity","angleDiff","cos","sin","relX","relY","startPoints","startPos","startDx","startDy","_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\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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"}
|
package/dist/bundle.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var t=Object.defineProperty,e=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable,o=(e,s,r)=>s in e?t(e,s,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[s]=r;import{Keybinding as n}from"@wbiokr/keybinding";if("undefined"!=typeof document){const t=document.createElement("style");t.textContent='\n.ae-d2-container {\n position: relative;\n width: 1000px;\n height: 600px;\n background: #fff;\n margin: auto;\n}\n\n.ae-d2-svg {\n width: 100%;\n height: 100%;\n position: absolute;\n left: 0;\n top: 0;\n z-index: 10;\n}\n\n\n.ae-arrow-path {\n fill: none;\n stroke-linejoin: round;\n cursor: pointer;\n}\n\n.ae-arrow-path:hover {\n stroke: #00aaff;\n}\n\n.ae-transform-box {\n fill: none;\n stroke: #00aaff;\n stroke-width: 2;\n stroke-dasharray: 4;\n}\n\n.ae-transform-handle {\n fill: #fff;\n stroke: #00aaff;\n stroke-width: 2;\n cursor: pointer;\n}\n\n.ae-transform-handle:hover {\n fill: #00aaff;\n}\n\n.ae-rotate-handle {\n fill: #fff;\n stroke: #ff6600;\n stroke-width: 2;\n cursor: grab;\n}\n\n.ae-rotate-handle:hover {\n fill: #ff6600;\n}\n\n.ae-rotate-line {\n stroke: #ff6600;\n stroke-width: 1;\n stroke-dasharray: 4;\n}\n\n/* 工具条样式 */\n.ae-toolbar {\n position: absolute;\n display: none;\n flex-direction: column;\n gap: 10px;\n padding: 12px;\n background: #fff;\n border: 1px solid #ddd;\n border-radius: 8px;\n box-shadow: 0 2px 12px rgba(0,0,0,0.15);\n z-index: 100;\n pointer-events: auto;\n min-width: 140px;\n}\n\n.ae-toolbar-drag-handle {\n cursor: grab;\n text-align: center;\n padding: 4px;\n color: #999;\n font-size: 14px;\n line-height: 1;\n user-select: none;\n border-bottom: 1px solid #eee;\n margin: -12px -12px 8px -12px;\n padding-top: 8px;\n padding-bottom: 8px;\n border-radius: 8px 8px 0 0;\n}\n\n.ae-toolbar-drag-handle:active {\n cursor: grabbing;\n}\n\n.ae-toolbar-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-toolbar-label {\n font-size: 11px;\n color: #666;\n}\n\n.ae-toolbar input[type="color"] {\n width: 40px;\n height: 30px;\n border: 1px solid #ddd;\n border-radius: 4px;\n cursor: pointer;\n padding: 0;\n background: none;\n}\n\n.ae-toolbar input[type="range"] {\n width: 120px;\n cursor: pointer;\n}\n\n.ae-toolbar-value {\n font-size: 10px;\n color: #999;\n text-align: right;\n}\n',document.head.appendChild(t)}class i{constructor(t,e={}){var s;this.container="string"==typeof t?document.querySelector(t):t,this.svg=null,this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this.lastClickTime=0,this.lastClickPos=null,this._shouldBlockClick=!1,this._defaultColor="#2b8cff",this.isCtrl=e.isCtrl||!1,this.stopPropagation=e.stopPropagation||!1,this.preventDefault=e.preventDefault||!1,this.onDrawEnd=e.onDrawEnd||null,this.onRemove=e.onRemove||null,this.onChange=e.onChange||null,this._defaultColor=e.defaultColor||this._defaultColor,this._strokeWidth=e.defaultStrokeWidth||8,this._curveRate=null!=(s=e.defaultCurveRate)?s:0,this._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._lastMousePos=null,this._createSVG(),this._initKeybindings(),this._initEvents()}_createSVG(){if("undefined"!=typeof getComputedStyle){"static"===getComputedStyle(this.container).position&&(this.container.style.position="relative")}this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.setAttribute("class","ae-d2-svg"),this.container.appendChild(this.svg);const t=document.createElementNS("http://www.w3.org/2000/svg","defs");this.svg.appendChild(t);const e=document.createElementNS("http://www.w3.org/2000/svg","marker");e.setAttribute("id","ae-arrowhead"),e.setAttribute("markerWidth","10"),e.setAttribute("markerHeight","10"),e.setAttribute("refX","9"),e.setAttribute("refY","5"),e.setAttribute("orient","auto");const s=document.createElementNS("http://www.w3.org/2000/svg","polygon");s.setAttribute("points","0,0 10,5 0,10 2,5"),s.setAttribute("fill",this._defaultColor),e.appendChild(s),t.appendChild(e)}_createToolbar(){var t,e;this._toolbar&&this._toolbar.remove(),this._toolbar=document.createElement("div"),this._toolbar.className="ae-toolbar";const s=this.selected.color||this._defaultColor,r=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0;this._toolbar.innerHTML=`\n <div class="ae-toolbar-drag-handle">:::</div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">颜色</span>\n <input type="color" class="ae-color-input" value="${s}" />\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">粗细</span>\n <input type="range" class="ae-stroke-input" min="1" max="60" value="${r}" />\n <span class="ae-toolbar-value">${r}px</span>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">曲线率</span>\n <input type="range" class="ae-round-input" min="0" max="1" step="0.1" value="${o}" />\n </div>\n `;this._toolbar.querySelector(".ae-color-input").addEventListener("input",t=>{this.selected&&(this.selected.color=t.target.value,this._defaultColor=t.target.value,this._updateMarkerColor(t.target.value),this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()}))});const n=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value");n.addEventListener("input",t=>{this.selected&&(this.selected.strokeWidth=parseInt(t.target.value),i.textContent=t.target.value+"px",this.render(),this.onChange&&this.onChange({type:"strokeWidth",arrow:this.selected,value:parseInt(t.target.value),arrows:this.getData()}))});this._toolbar.querySelector(".ae-round-input").addEventListener("input",t=>{this.selected&&(this.selected.curveRate=parseFloat(t.target.value),this.render(),this.onChange&&this.onChange({type:"curveRate",arrow:this.selected,value:parseFloat(t.target.value),arrows:this.getData()}))});const a=this._toolbar.querySelector(".ae-toolbar-drag-handle");this._setupToolbarDrag(a),this._toolbar.addEventListener("mousedown",t=>{t.stopPropagation()}),this._toolbar.addEventListener("mouseup",t=>{t.stopPropagation()}),this.container.appendChild(this._toolbar)}_setupToolbarDrag(t){let e=!1,s={x:0,y:0};t.addEventListener("mousedown",t=>{e=!0,this._toolbarDragging=!0;const r=this._toolbar.getBoundingClientRect();s.x=t.clientX-r.left,s.y=t.clientY-r.top,t.preventDefault(),t.stopPropagation();const o=t=>{if(!e)return;const r=this.container.getBoundingClientRect();let o=t.clientX-r.left-s.x,n=t.clientY-r.top-s.y;const i=this._toolbar.offsetWidth,a=this._toolbar.offsetHeight;o=Math.max(0,Math.min(o,r.width-i)),n=Math.max(0,Math.min(n,r.height-a)),this._toolbar.style.left=o+"px",this._toolbar.style.top=n+"px"},n=t=>{e=!1,this._toolbarDragging=!1,document.removeEventListener("mousemove",o),document.removeEventListener("mouseup",n),this._toolbar.removeEventListener("mouseup",n),t.preventDefault(),t.stopPropagation()};document.addEventListener("mousemove",o),document.addEventListener("mouseup",n),this._toolbar.addEventListener("mouseup",n)})}_showToolbar(){var t,e;if(this.selected){this._toolbar||this._createToolbar(),this._toolbar.style.display="flex";const s=this.selected.color||this._defaultColor,r=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0,n=this._toolbar.querySelector(".ae-color-input"),i=this._toolbar.querySelector(".ae-stroke-input"),a=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value"),l=this._toolbar.querySelector(".ae-round-input");n&&(n.value=s),i&&(i.value=r,a.textContent=r+"px"),l&&(l.value=o);const h=this._getArrowBBox(this.selected),c=this._toolbar.offsetWidth||150,d=this._toolbar.offsetHeight||120;let u=h.maxX+20;u+c>this.container.offsetWidth&&(u=h.minX-c-20);let p=h.centerY-d/2;p<0&&(p=0),p+d>this.container.offsetHeight&&(p=this.container.offsetHeight-d),this._toolbar.style.left=u+"px",this._toolbar.style.top=p+"px"}}_hideToolbar(){this._toolbar&&(this._toolbar.style.display="none")}_updateMarkerColor(t){const e=this.svg.querySelector("#ae-arrowhead polygon");e&&e.setAttribute("fill",t)}_initKeybindings(){this._kb=new n("arrow-editor-"+Math.random(),this.container),this._kb.on("enter",()=>{this._handleEnter()}),this._kb.on("esc",()=>{this._handleEsc()}),this._kb.on("delete",()=>{this._handleDelete()}),this._kb.on("backspace",()=>{this._handleDelete()}),this._kb.on("space",()=>{this._handleSpace()}),this._kb.on("arrowup",()=>{this._handleArrowKey(0,-1)}),this._kb.on("arrowdown",()=>{this._handleArrowKey(0,1)}),this._kb.on("arrowleft",()=>{this._handleArrowKey(-1,0)}),this._kb.on("arrowright",()=>{this._handleArrowKey(1,0)})}_handleSpace(){this.drawing&&this.current&&this._lastMousePos&&(this.current.points.push(((t,n)=>{for(var i in n||(n={}))s.call(n,i)&&o(t,i,n[i]);if(e)for(var i of e(n))r.call(n,i)&&o(t,i,n[i]);return t})({},this._lastMousePos)),this.render())}_handleArrowKey(t,e){if(!this.selected)return;this.selected.points.forEach(s=>{s.x+=1*t,s.y+=1*e}),this.render(),this.onChange&&this.onChange({type:"move",arrow:this.selected,arrows:this.getData()})}_initEvents(){this.container.onclick=t=>{if(this._toolbar&&(t.target===this._toolbar||this._toolbar.contains(t.target)))return;this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._handleClick(e,t)},this.container.onmousemove=t=>{this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._lastMousePos=e,this._handleMouseMove(t,e)},this.container.onmousedown=t=>{if((!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target))&&(this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation(),this.selected)){const e=t.target.getAttribute("data-handle");if(e){this._transformMode=e,this._transformHandle=e;const s=this._mousePos(t);if(this._transformStartPos=s,this._transformStartPoints=this.selected.points.map(t=>({x:t.x,y:t.y})),this._transformCenter=this._getArrowBBox(this.selected),"rotate"===e){const t=this._transformCenter,e=s.x-t.centerX,r=s.y-t.centerY;this._transformStartAngle=Math.atan2(r,e),this._rotationOffset=0}return void t.stopPropagation()}this.mode="move"}},this.container.onmouseup=t=>{this._transformMode&&this.selected&&this.onChange&&this.onChange({type:this._transformMode,arrow:this.selected,arrows:this.getData()}),this.mode=null,this._transformMode=null,this._transformHandle=null}}_mousePos(t){const e=this.container.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_generatePath(t,e=0){if(t.length<2)return"";if(0===e){let e=`M ${t[0].x} ${t[0].y}`;for(let s=1;s<t.length;s++)e+=` L ${t[s].x} ${t[s].y}`;return e}let s=`M ${t[0].x} ${t[0].y}`;for(let r=0;r<t.length-1;r++){const o=t[r],n=t[r+1],i=n.x-o.x,a=n.y-o.y,l=Math.hypot(i,a);if(0===l)continue;let h=i,c=a;if(r>0){const e=t[r-1];h=o.x-e.x,c=o.y-e.y}let d=i,u=a;if(r<t.length-2){const e=t[r+2];d=e.x-n.x,u=e.y-n.y}const p=Math.hypot(h,c)||1,g=Math.hypot(d,u)||1,f=h/p,_=c/p,m=d/g,b=u/g,v=l*e*.3;s+=` C ${o.x+f*v} ${o.y+_*v} ${n.x-m*v} ${n.y-b*v} ${n.x} ${n.y}`}return s}_generateArrowHead(t,e=8){if(t.length<2)return"";const s=t[t.length-1];let r=t[t.length-2];if(t.length>=3){Math.hypot(s.x-r.x,s.y-r.y)<5&&(r=t[t.length-3])}const o=s.x-r.x,n=s.y-r.y,i=Math.hypot(o,n);if(i<1)return"";const a=o/i,l=n/i,h=e/8,c=25*h,d=20*h,u=s.x,p=s.y,g=a*(c/2),f=l*(c/2),_=u+g-a*c,m=p+f-l*c,b=-l;return`M ${u+g} ${p+f} L ${_+b*d} ${m+a*d} L ${_-b*d} ${m-a*d} Z`}_createArrowGroup(t,e){var s,r;const o=document.createElementNS("http://www.w3.org/2000/svg","g");o.setAttribute("data-index",e);const n=t.color||this._defaultColor,i=t.strokeWidth||this._strokeWidth,a=null!=(r=null!=(s=t.curveRate)?s:t.cornerRoundness)?r:0,l=document.createElementNS("http://www.w3.org/2000/svg","path");l.setAttribute("class","ae-arrow-path"),l.style.stroke=n,l.style.strokeWidth=i+"px",l.setAttribute("d",this._generatePath(t.points,a)),o.appendChild(l);const h=document.createElementNS("http://www.w3.org/2000/svg","path");if(h.setAttribute("fill",n),h.setAttribute("d",this._generateArrowHead(t.points,i)),o.appendChild(h),t===this.selected){const e=this._getArrowBBox(t),s=document.createElementNS("http://www.w3.org/2000/svg","rect");s.setAttribute("class","ae-transform-box"),s.setAttribute("x",e.minX-10),s.setAttribute("y",e.minY-10),s.setAttribute("width",e.width+20),s.setAttribute("height",e.height+20),o.appendChild(s);const r=document.createElementNS("http://www.w3.org/2000/svg","circle");r.setAttribute("class","ae-transform-handle"),r.setAttribute("cx",e.maxX+10),r.setAttribute("cy",e.maxY+10),r.setAttribute("r",6),r.setAttribute("data-handle","scale"),o.appendChild(r);const n=e.minY-30,i=e.centerX,a=document.createElementNS("http://www.w3.org/2000/svg","line");a.setAttribute("class","ae-rotate-line"),a.setAttribute("x1",e.centerX),a.setAttribute("y1",e.minY-10),a.setAttribute("x2",i),a.setAttribute("y2",n),o.appendChild(a);const l=document.createElementNS("http://www.w3.org/2000/svg","circle");l.setAttribute("class","ae-rotate-handle"),l.setAttribute("cx",i),l.setAttribute("cy",n),l.setAttribute("r",8),l.setAttribute("data-handle","rotate"),o.appendChild(l)}return o}render(){if(this.svg.querySelectorAll("g").forEach(t=>t.remove()),this.arrows.forEach((t,e)=>{const s=this._createArrowGroup(t,e);this.svg.appendChild(s)}),this.current){const t=this._createArrowGroup(this.current,this.arrows.length);this.svg.appendChild(t)}}_isDoubleClick(t){const e=Date.now(),s=e-this.lastClickTime;return this.lastClickTime=e,s<300&&this.lastClickPos&&Math.hypot(t.x-this.lastClickPos.x,t.y-this.lastClickPos.y)<10?(this.lastClickPos=null,!0):(this.lastClickPos=t,!1)}_handleClick(t,e){if(!this.isCtrl||e.ctrlKey)if(this._shouldBlockClick)this._shouldBlockClick=!1;else if(this._isDoubleClick(t)){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}else{if(this.selected){for(const e of this.arrows)if(this._hitArrow(e,t))return void this.render();return this.selected=null,this._hideToolbar(),void this.render()}for(const e of this.arrows)if(this._hitArrow(e,t))return this.selected=e,this._showToolbar(),void this.render();this.drawing?this.current.points.push(t):(this.drawing=!0,this.current={points:[t,t],color:this._defaultColor},this.svg.classList.add("ae-d2-svg-fixed")),this.render()}}_handleEnter(){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_handleEsc(){this.drawing&&(this.drawing=!1,this.current=null,this.svg.classList.remove("ae-d2-svg-fixed")),this.selected&&(this.selected=null),this._hideColorPicker(),this._hideToolbar(),this.render()}_handleDelete(){if(this.selected){const t=this.selected,e=this.arrows.indexOf(this.selected);e>-1&&this.arrows.splice(e,1),this.selected=null,this._hideToolbar(),this.render(),this.onRemove&&this.onRemove({arrow:t,arrows:this.getData()})}}_showColorPicker(t){if(this._showingColorPicker)return void this._hideColorPicker();this._showingColorPicker=!0;const e=document.createElement("div");e.className="ae-color-picker-popup";const s=document.createElement("span");s.textContent="选择颜色",s.style.cssText="font-size: 12px; color: #666;";const r=document.createElement("input");r.type="color",r.value=this.selected.color||this._defaultColor,r.showPicker(),e.appendChild(s),e.appendChild(r);const o=this.container.getBoundingClientRect(),n=this._getArrowBBox(this.selected),i=o.left+n.minX-50,a=o.top+n.maxY+15;e.style.left=i+"px",e.style.top=a+"px",r.addEventListener("input",t=>{this.selected.color=t.target.value,this._defaultColor=t.target.value,this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()})});const l=t=>{e.contains(t.target)||(this._hideColorPicker(),document.removeEventListener("click",l))};document.body.appendChild(e),this._colorPickerPopup=e,document.addEventListener("click",l)}_hideColorPicker(){this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this._showingColorPicker=!1}deleteSelected(){this.selected&&(this.arrows=this.arrows.filter(t=>t!==this.selected),this.selected=null,this.render())}_handleMouseMove(t,e){if(!this._toolbarDragging&&(!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target)))if(!this.isCtrl||t.ctrlKey){if(this.drawing&&(this.current.points[this.current.points.length-1]=e,this.render()),this._transformMode&&this.selected)return"rotate"===this._transformMode?this._handleRotate(e):"scale"===this._transformMode&&this._handleScale(e),void this.render();if(this.selected&&"move"===this.mode){const e=t.movementX,s=t.movementY;0===e&&0===s||(this._shouldBlockClick=!0),this.selected.points.forEach(t=>{t.x+=e,t.y+=s}),this.render()}}else if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_getArrowBBox(t){const e=t.points;let s=1/0,r=1/0,o=-1/0,n=-1/0;for(const i of e)s=Math.min(s,i.x),r=Math.min(r,i.y),o=Math.max(o,i.x),n=Math.max(n,i.y);return{minX:s,minY:r,maxX:o,maxY:n,width:o-s,height:n-r,centerX:(s+o)/2,centerY:(r+n)/2}}_handleRotate(t){const e=this._transformCenter,s=e.centerX,r=e.centerY,o=Math.atan2(t.y-r,t.x-s)-Math.atan2(this._transformStartPos.y-r,this._transformStartPos.x-s),n=Math.cos(o),i=Math.sin(o);this.selected.points.forEach((t,e)=>{const o=this._transformStartPoints[e].x-s,a=this._transformStartPoints[e].y-r;t.x=s+o*n-a*i,t.y=r+o*i+a*n})}_handleScale(t){const e=this._transformCenter,s=e.centerX,r=e.centerY,o=this._transformStartPoints,n=this._transformStartPos,i=t.x-s,a=t.y-r,l=n.x-s,h=n.y-r,c=Math.hypot(i,a)/Math.hypot(l,h);this.selected.points.forEach((t,e)=>{t.x=s+(o[e].x-s)*c,t.y=r+(o[e].y-r)*c})}_hitArrow(t,e){for(let s=0;s<t.points.length-1;s++)if(this._dist(e,t.points[s],t.points[s+1])<15)return!0;return!1}_dist(t,e,s){const r=s.x-e.x,o=s.y-e.y,n=((t.x-e.x)*r+(t.y-e.y)*o)/(r*r+o*o),i=Math.max(0,Math.min(1,n)),a=e.x+i*r,l=e.y+i*o;return Math.hypot(t.x-a,t.y-l)}getData(){return this.arrows.map(t=>{var e,s;return{points:t.points,curveRate:null!=(s=null!=(e=t.curveRate)?e:t.cornerRoundness)?s:0,strokeWidth:t.strokeWidth,color:t.color}})}setData(t){this.arrows=t.map(t=>{var e,s;return{points:t.points,curveRate:null!=(e=t.curveRate)?e:0,strokeWidth:null!=(s=t.strokeWidth)?s:8,color:t.color}}),this.render()}clear(){this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.render()}destroy(){this._kb&&this._kb.destroy&&this._kb.destroy(),this.container.onclick=null,this.container.onmousemove=null,this.container.onmousedown=null,this.container.onmouseup=null,this.container.ondblclick=null,this.svg&&(this.svg.remove(),this.svg=null),this._toolbar&&(this._toolbar.remove(),this._toolbar=null),this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this._transformMode=null,this._transformHandle=null}}export{i as ArrowEditor};
|
|
1
|
+
var t=Object.defineProperty,e=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,n=Object.prototype.propertyIsEnumerable,o=(e,s,n)=>s in e?t(e,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[s]=n,r=(t,r)=>{for(var a in r||(r={}))s.call(r,a)&&o(t,a,r[a]);if(e)for(var a of e(r))n.call(r,a)&&o(t,a,r[a]);return t};import{Keybinding as a}from"@wbiokr/keybinding";if("undefined"!=typeof document){const t=document.createElement("style");t.textContent='\n.ae-d2-container {\n position: relative;\n width: 1000px;\n height: 600px;\n background: #fff;\n margin: auto;\n}\n\n.ae-d2-svg {\n width: 100%;\n height: 100%;\n position: absolute;\n left: 0;\n top: 0;\n z-index: 10;\n}\n\n\n.ae-arrow-path {\n fill: none;\n stroke-linejoin: round;\n cursor: pointer;\n}\n\n.ae-arrow-path:hover {\n stroke: #00aaff;\n}\n\n.ae-transform-box {\n fill: none;\n stroke: #00aaff;\n stroke-width: 2;\n stroke-dasharray: 4;\n}\n\n.ae-transform-handle {\n fill: #fff;\n stroke: #00aaff;\n stroke-width: 2;\n cursor: pointer;\n}\n\n.ae-transform-handle:hover {\n fill: #00aaff;\n}\n\n.ae-rotate-handle {\n fill: #fff;\n stroke: #ff6600;\n stroke-width: 2;\n cursor: grab;\n}\n\n.ae-rotate-handle:hover {\n fill: #ff6600;\n}\n\n.ae-rotate-line {\n stroke: #ff6600;\n stroke-width: 1;\n stroke-dasharray: 4;\n}\n\n/* 工具条样式 */\n.ae-toolbar {\n position: fixed;\n display: none;\n flex-direction: column;\n gap: 10px;\n padding: 12px;\n background: #fff;\n border: 1px solid #ddd;\n border-radius: 8px;\n box-shadow: 0 2px 12px rgba(0,0,0,0.15);\n z-index: 10000;\n pointer-events: auto;\n min-width: 140px;\n}\n\n.ae-toolbar-drag-handle {\n cursor: grab;\n text-align: center;\n padding: 4px;\n color: #999;\n font-size: 14px;\n line-height: 1;\n user-select: none;\n border-bottom: 1px solid #eee;\n margin: -12px -12px 8px -12px;\n padding-top: 8px;\n padding-bottom: 8px;\n border-radius: 8px 8px 0 0;\n}\n\n.ae-toolbar-drag-handle:active {\n cursor: grabbing;\n}\n\n.ae-toolbar-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.ae-toolbar-row {\n display: flex;\n gap: 8px;\n}\n\n.ae-toolbar-label {\n font-size: 11px;\n color: #666;\n}\n\n.ae-scale-btn {\n flex: 1;\n padding: 6px 8px;\n background: #f0f0f0;\n color: #333;\n border: 1px solid #ccc;\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n transition: background 0.2s;\n}\n\n.ae-scale-btn:hover {\n background: #e0e0e0;\n}\n\n.ae-scale-btn:active {\n background: #d0d0d0;\n}\n\n.ae-toolbar input[type="color"] {\n width: 40px;\n height: 30px;\n border: 1px solid #ddd;\n border-radius: 4px;\n cursor: pointer;\n padding: 0;\n background: none;\n}\n\n.ae-toolbar input[type="range"] {\n width: 120px;\n cursor: pointer;\n}\n\n.ae-toolbar-value {\n font-size: 10px;\n color: #999;\n text-align: right;\n}\n',document.head.appendChild(t)}class i{constructor(t,e={}){var s;this.container="string"==typeof t?document.querySelector(t):t,this.svg=null,this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this.lastClickTime=0,this.lastClickPos=null,this._shouldBlockClick=!1,this._defaultColor="#2b8cff",this.isCtrl=e.isCtrl||!1,this.stopPropagation=e.stopPropagation||!1,this.preventDefault=e.preventDefault||!1,this.onDrawEnd=e.onDrawEnd||null,this.onRemove=e.onRemove||null,this.onChange=e.onChange||null,this._defaultColor=e.defaultColor||this._defaultColor,this._strokeWidth=e.defaultStrokeWidth||8,this._curveRate=null!=(s=e.defaultCurveRate)?s:0,this._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._lastMousePos=null,this._createSVG(),this._initKeybindings(),this._initEvents()}_createSVG(){if("undefined"!=typeof getComputedStyle){"static"===getComputedStyle(this.container).position&&(this.container.style.position="relative")}this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.setAttribute("class","ae-d2-svg"),this.container.appendChild(this.svg);const t=document.createElementNS("http://www.w3.org/2000/svg","defs");this.svg.appendChild(t);const e=document.createElementNS("http://www.w3.org/2000/svg","marker");e.setAttribute("id","ae-arrowhead"),e.setAttribute("markerWidth","10"),e.setAttribute("markerHeight","10"),e.setAttribute("refX","9"),e.setAttribute("refY","5"),e.setAttribute("orient","auto");const s=document.createElementNS("http://www.w3.org/2000/svg","polygon");s.setAttribute("points","0,0 10,5 0,10 2,5"),s.setAttribute("fill",this._defaultColor),e.appendChild(s),t.appendChild(e)}_createToolbar(){var t,e;this._toolbar&&this._toolbar.remove(),this._toolbar=document.createElement("div"),this._toolbar.className="ae-toolbar";const s=this.selected.color||this._defaultColor,n=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0;this._toolbar.innerHTML=`\n <div class="ae-toolbar-drag-handle">:::</div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">颜色</span>\n <input type="color" class="ae-color-input" value="${s}" />\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">粗细</span>\n <input type="range" class="ae-stroke-input" min="1" max="60" value="${n}" />\n <span class="ae-toolbar-value">${n}px</span>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">曲线率</span>\n <input type="range" class="ae-round-input" min="0" max="1" step="0.1" value="${o}" />\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">缩放</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-axis="x">X 缩放</button>\n <button class="ae-scale-btn" data-axis="y">Y 缩放</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">3D 旋转</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-axis="x-rotate">X 轴</button>\n <button class="ae-scale-btn" data-axis="y-rotate">Y 轴</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">2.5D 挤出</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-mode="extrude-up">上挤出</button>\n <button class="ae-scale-btn" data-mode="extrude-down">下挤出</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-mode="extrude-left">左挤出</button>\n <button class="ae-scale-btn" data-mode="extrude-right">右挤出</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-mode="reset">重置</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">2.5D 透视</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-perspective="top">上透视</button>\n <button class="ae-scale-btn" data-perspective="bottom">下透视</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-perspective="left">左透视</button>\n <button class="ae-scale-btn" data-perspective="right">右透视</button>\n </div>\n </div>\n <div class="ae-toolbar-item">\n <span class="ae-toolbar-label">倾斜</span>\n <div class="ae-toolbar-row">\n <button class="ae-scale-btn" data-skew="x-left">左倾斜</button>\n <button class="ae-scale-btn" data-skew="x-right">右倾斜</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-skew="y-up">上倾斜</button>\n <button class="ae-scale-btn" data-skew="y-down">下倾斜</button>\n </div>\n <div class="ae-toolbar-row" style="margin-top:4px;">\n <button class="ae-scale-btn" data-mode="reset">重置</button>\n </div>\n </div>\n `;this._toolbar.querySelector(".ae-color-input").addEventListener("input",t=>{this.selected&&(this.selected.color=t.target.value,this._defaultColor=t.target.value,this._updateMarkerColor(t.target.value),this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()}))});const a=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value");a.addEventListener("input",t=>{this.selected&&(this.selected.strokeWidth=parseInt(t.target.value),i.textContent=t.target.value+"px",this.render(),this.onChange&&this.onChange({type:"strokeWidth",arrow:this.selected,value:parseInt(t.target.value),arrows:this.getData()}))});this._toolbar.querySelector(".ae-round-input").addEventListener("input",t=>{this.selected&&(this.selected.curveRate=parseFloat(t.target.value),this.render(),this.onChange&&this.onChange({type:"curveRate",arrow:this.selected,value:parseFloat(t.target.value),arrows:this.getData()}))});this._toolbar.querySelectorAll(".ae-scale-btn[data-axis]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.axis;if("x-rotate"===e)return void this._startRotate3D("x");if("y-rotate"===e)return void this._startRotate3D("y");this._transformMode="scale",this._transformAxis=e,this._transformCenter=this._getArrowBBox(this.selected),this._transformStartPoints=this.selected.points.map(t=>r({},t));const s=this._getArrowBBox(this.selected);this._transformStartPos="x"===e?{x:s.maxX+10,y:s.centerY}:{x:s.centerX,y:s.maxY+10};const n=t=>{const s=this._mousePos(t);"x"===e?this._handleScaleX(s):this._handleScaleY(s),this.render()},o=()=>{document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",o),this.onChange&&this.onChange({type:"scale",arrow:this.selected,arrows:this.getData()}),this._transformMode=null,this._transformAxis=null};document.addEventListener("mousemove",n),document.addEventListener("mouseup",o)})});this._toolbar.querySelectorAll(".ae-scale-btn[data-mode]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.mode;"extrude-up"===e?this._applyExtrude(0,-15):"extrude-down"===e?this._applyExtrude(0,15):"extrude-left"===e?this._applyExtrude(-15,0):"extrude-right"===e?this._applyExtrude(15,0):"reset"===e&&this._resetExtrude()})});this._toolbar.querySelectorAll(".ae-scale-btn[data-perspective]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.perspective;"top"===e?this._applyPerspective("top"):"bottom"===e?this._applyPerspective("bottom"):"left"===e?this._applyPerspective("left"):"right"===e&&this._applyPerspective("right")})});this._toolbar.querySelectorAll(".ae-scale-btn[data-skew]").forEach(t=>{t.addEventListener("click",t=>{t.stopPropagation();const e=t.target.dataset.skew;"x-left"===e?this._applySkew("x-left"):"x-right"===e?this._applySkew("x-right"):"y-up"===e?this._applySkew("y-up"):"y-down"===e&&this._applySkew("y-down")})});const l=this._toolbar.querySelector(".ae-toolbar-drag-handle");this._setupToolbarDrag(l),this._toolbar.addEventListener("mousedown",t=>{t.stopPropagation()}),this._toolbar.addEventListener("mouseup",t=>{t.stopPropagation()}),document.body.appendChild(this._toolbar)}_setupToolbarDrag(t){let e=!1,s={x:0,y:0};t.addEventListener("mousedown",t=>{e=!0,this._toolbarDragging=!0;const n=this._toolbar.getBoundingClientRect();s.x=t.clientX-n.left,s.y=t.clientY-n.top,t.preventDefault(),t.stopPropagation();const o=t=>{if(!e)return;let n=t.clientX-s.x,o=t.clientY-s.y;this._toolbar.style.left=n+"px",this._toolbar.style.top=o+"px"},r=t=>{e=!1,this._toolbarDragging=!1,document.removeEventListener("mousemove",o),document.removeEventListener("mouseup",r),this._toolbar.removeEventListener("mouseup",r),t.preventDefault(),t.stopPropagation()};document.addEventListener("mousemove",o),document.addEventListener("mouseup",r),this._toolbar.addEventListener("mouseup",r)})}_showToolbar(){var t,e;if(this.selected){this._toolbar||this._createToolbar(),this._toolbar.style.display="flex";const s=this.selected.color||this._defaultColor,n=this.selected.strokeWidth||this._strokeWidth,o=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0,r=this._toolbar.querySelector(".ae-color-input"),a=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value"),l=this._toolbar.querySelector(".ae-round-input");r&&(r.value=s),a&&(a.value=n,i.textContent=n+"px"),l&&(l.value=o);const h=this.container.getBoundingClientRect(),c=this._getArrowBBox(this.selected),d=this._toolbar.offsetWidth||150,u=this._toolbar.offsetHeight||120;let p=h.left+c.maxX+20;p+d>window.innerWidth-10&&(p=h.left+c.minX-d-20);let g=h.top+c.centerY-u/2;g<10&&(g=10),g+u>window.innerHeight-10&&(g=window.innerHeight-u-10),this._toolbar.style.left=p+"px",this._toolbar.style.top=g+"px"}}_hideToolbar(){this._toolbar&&(this._toolbar.style.display="none")}_updateMarkerColor(t){const e=this.svg.querySelector("#ae-arrowhead polygon");e&&e.setAttribute("fill",t)}_initKeybindings(){this._kb=new a("arrow-editor-"+Math.random(),this.container),this._kb.on("enter",()=>{this._handleEnter()}),this._kb.on("esc",()=>{this._handleEsc()}),this._kb.on("delete",()=>{this._handleDelete()}),this._kb.on("backspace",()=>{this._handleDelete()}),this._kb.on("space",()=>{this._handleSpace()}),this._kb.on("arrowup",()=>{this._handleArrowKey(0,-1)}),this._kb.on("arrowdown",()=>{this._handleArrowKey(0,1)}),this._kb.on("arrowleft",()=>{this._handleArrowKey(-1,0)}),this._kb.on("arrowright",()=>{this._handleArrowKey(1,0)})}_handleSpace(){this.drawing&&this.current&&this._lastMousePos&&(this.current.points.push(r({},this._lastMousePos)),this.render())}_handleArrowKey(t,e){if(!this.selected)return;this.selected.points.forEach(s=>{s.x+=1*t,s.y+=1*e}),this.render(),this.onChange&&this.onChange({type:"move",arrow:this.selected,arrows:this.getData()})}_initEvents(){this.container.onclick=t=>{if(this._toolbar&&(t.target===this._toolbar||this._toolbar.contains(t.target)))return;this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._handleClick(e,t)},this.container.onmousemove=t=>{this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation();const e=this._mousePos(t);this._lastMousePos=e,this._handleMouseMove(t,e)},this.container.onmousedown=t=>{if((!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target))&&(this.preventDefault&&t.preventDefault(),this.stopPropagation&&t.stopPropagation(),this.selected)){const e=t.target.getAttribute("data-handle");if(e){this._transformMode="scaleX"===e||"scaleY"===e?"scale":e,this._transformHandle=e,this._transformAxis="scaleX"===e?"x":"scaleY"===e?"y":null;const s=this._mousePos(t);if(this._transformStartPos=s,this._transformStartPoints=this.selected.points.map(t=>({x:t.x,y:t.y})),this._transformCenter=this._getArrowBBox(this.selected),"rotate"===e){const t=this._transformCenter,e=s.x-t.centerX,n=s.y-t.centerY;this._transformStartAngle=Math.atan2(n,e),this._rotationOffset=0}return void t.stopPropagation()}this.mode="move"}},this.container.onmouseup=t=>{this._transformMode&&this.selected&&this.onChange&&this.onChange({type:this._transformMode,arrow:this.selected,arrows:this.getData()}),this.mode=null,this._transformMode=null,this._transformHandle=null,this._transformAxis=null}}_mousePos(t){const e=this.container.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}_generatePath(t,e=0){if(t.length<2)return"";if(0===e){let e=`M ${t[0].x} ${t[0].y}`;for(let s=1;s<t.length;s++)e+=` L ${t[s].x} ${t[s].y}`;return e}let s=`M ${t[0].x} ${t[0].y}`;for(let n=0;n<t.length-1;n++){const o=t[n],r=t[n+1],a=r.x-o.x,i=r.y-o.y,l=Math.hypot(a,i);if(0===l)continue;let h=a,c=i;if(n>0){const e=t[n-1];h=o.x-e.x,c=o.y-e.y}let d=a,u=i;if(n<t.length-2){const e=t[n+2];d=e.x-r.x,u=e.y-r.y}const p=Math.hypot(h,c)||1,g=Math.hypot(d,u)||1,m=h/p,b=c/p,_=d/g,f=u/g,x=l*e*.3;s+=` C ${o.x+m*x} ${o.y+b*x} ${r.x-_*x} ${r.y-f*x} ${r.x} ${r.y}`}return s}_generateArrowHead(t,e=8){if(t.length<2)return"";const s=t[t.length-1];let n=t[t.length-2];if(t.length>=3){Math.hypot(s.x-n.x,s.y-n.y)<5&&(n=t[t.length-3])}const o=s.x-n.x,r=s.y-n.y,a=Math.hypot(o,r);if(a<1)return"";const i=o/a,l=r/a,h=e/8,c=22*h,d=20*h,u=s.x,p=s.y,g=i*(c/2),m=l*(c/2),b=u+g-i*c,_=p+m-l*c,f=-l;return`M ${u+g} ${p+m} L ${b+f*d} ${_+i*d} L ${b-f*d} ${_-i*d} Z`}_createArrowGroup(t,e){var s,n;const o=document.createElementNS("http://www.w3.org/2000/svg","g");o.setAttribute("data-index",e);const r=t.color||this._defaultColor,a=t.strokeWidth||this._strokeWidth,i=null!=(n=null!=(s=t.curveRate)?s:t.cornerRoundness)?n:0,l=t.extrude||{x:0,y:0};if(Math.max(Math.abs(l.x),Math.abs(l.y))>0){const e=l.x>0?1:-1,s=l.y>0?1:-1,n=Math.max(Math.abs(l.x),Math.abs(l.y));for(let r=1;r<=n;r++){const n=e*r,l=s*r,h=document.createElementNS("http://www.w3.org/2000/svg","path");h.setAttribute("class","ae-arrow-path"),h.style.stroke="#ccc",h.style.strokeWidth=a+"px",h.style.opacity="0.15",h.setAttribute("d",this._generatePath(t.points.map(t=>({x:t.x+n,y:t.y+l})),i)),o.appendChild(h);const c=document.createElementNS("http://www.w3.org/2000/svg","path");c.setAttribute("fill","#ccc"),c.setAttribute("fill-opacity","0.15"),c.setAttribute("d",this._generateArrowHead(t.points.map(t=>({x:t.x+n,y:t.y+l})),a)),o.appendChild(c)}}const h=document.createElementNS("http://www.w3.org/2000/svg","path");h.setAttribute("class","ae-arrow-path"),h.style.stroke=r,h.style.strokeWidth=a+"px",h.setAttribute("d",this._generatePath(t.points,i)),o.appendChild(h);const c=document.createElementNS("http://www.w3.org/2000/svg","path");if(c.setAttribute("fill",r),c.setAttribute("d",this._generateArrowHead(t.points,a)),o.appendChild(c),t===this.selected){const e=this._getArrowBBox(t),s=document.createElementNS("http://www.w3.org/2000/svg","rect");s.setAttribute("class","ae-transform-box"),s.setAttribute("x",e.minX-10),s.setAttribute("y",e.minY-10),s.setAttribute("width",e.width+20),s.setAttribute("height",e.height+20),o.appendChild(s);const n=document.createElementNS("http://www.w3.org/2000/svg","circle");n.setAttribute("class","ae-transform-handle"),n.setAttribute("cx",e.maxX+10),n.setAttribute("cy",e.maxY+10),n.setAttribute("r",6),n.setAttribute("data-handle","scale"),o.appendChild(n);const r=document.createElementNS("http://www.w3.org/2000/svg","circle");r.setAttribute("class","ae-transform-handle"),r.setAttribute("cx",e.maxX+10),r.setAttribute("cy",e.centerY),r.setAttribute("r",6),r.setAttribute("data-handle","scaleX"),o.appendChild(r);const a=document.createElementNS("http://www.w3.org/2000/svg","circle");a.setAttribute("class","ae-transform-handle"),a.setAttribute("cx",e.centerX),a.setAttribute("cy",e.maxY+10),a.setAttribute("r",6),a.setAttribute("data-handle","scaleY"),o.appendChild(a);const i=e.minY-30,l=e.centerX,h=document.createElementNS("http://www.w3.org/2000/svg","line");h.setAttribute("class","ae-rotate-line"),h.setAttribute("x1",e.centerX),h.setAttribute("y1",e.minY-10),h.setAttribute("x2",l),h.setAttribute("y2",i),o.appendChild(h);const c=document.createElementNS("http://www.w3.org/2000/svg","circle");c.setAttribute("class","ae-rotate-handle"),c.setAttribute("cx",l),c.setAttribute("cy",i),c.setAttribute("r",8),c.setAttribute("data-handle","rotate"),o.appendChild(c)}return o}render(){if(this.svg.querySelectorAll("g").forEach(t=>t.remove()),this.arrows.forEach((t,e)=>{const s=this._createArrowGroup(t,e);this.svg.appendChild(s)}),this.current){const t=this._createArrowGroup(this.current,this.arrows.length);this.svg.appendChild(t)}}_isDoubleClick(t){const e=Date.now(),s=e-this.lastClickTime;return this.lastClickTime=e,s<300&&this.lastClickPos&&Math.hypot(t.x-this.lastClickPos.x,t.y-this.lastClickPos.y)<10?(this.lastClickPos=null,!0):(this.lastClickPos=t,!1)}_handleClick(t,e){if(!this.isCtrl||e.ctrlKey)if(this._shouldBlockClick)this._shouldBlockClick=!1;else if(this._isDoubleClick(t)){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}else{if(this.selected){for(const e of this.arrows)if(this._hitArrow(e,t))return void this.render();return this.selected=null,this._hideToolbar(),void this.render()}for(const e of this.arrows)if(this._hitArrow(e,t))return this.selected=e,this._showToolbar(),void this.render();this.drawing?this.current.points.push(t):(this.drawing=!0,this.current={points:[t,t],color:this._defaultColor},this.svg.classList.add("ae-d2-svg-fixed")),this.render()}}_handleEnter(){if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_handleEsc(){this.drawing&&(this.drawing=!1,this.current=null,this.svg.classList.remove("ae-d2-svg-fixed")),this.selected&&(this.selected=null),this._hideColorPicker(),this._hideToolbar(),this.render()}_handleDelete(){if(this.selected){const t=this.selected,e=this.arrows.indexOf(this.selected);e>-1&&this.arrows.splice(e,1),this.selected=null,this._hideToolbar(),this.render(),this.onRemove&&this.onRemove({arrow:t,arrows:this.getData()})}}_showColorPicker(t){if(this._showingColorPicker)return void this._hideColorPicker();this._showingColorPicker=!0;const e=document.createElement("div");e.className="ae-color-picker-popup";const s=document.createElement("span");s.textContent="选择颜色",s.style.cssText="font-size: 12px; color: #666;";const n=document.createElement("input");n.type="color",n.value=this.selected.color||this._defaultColor,n.showPicker(),e.appendChild(s),e.appendChild(n);const o=this.container.getBoundingClientRect(),r=this._getArrowBBox(this.selected),a=o.left+r.minX-50,i=o.top+r.maxY+15;e.style.left=a+"px",e.style.top=i+"px",n.addEventListener("input",t=>{this.selected.color=t.target.value,this._defaultColor=t.target.value,this.render(),this.onChange&&this.onChange({type:"color",arrow:this.selected,value:t.target.value,arrows:this.getData()})});const l=t=>{e.contains(t.target)||(this._hideColorPicker(),document.removeEventListener("click",l))};document.body.appendChild(e),this._colorPickerPopup=e,document.addEventListener("click",l)}_hideColorPicker(){this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this._showingColorPicker=!1}deleteSelected(){this.selected&&(this.arrows=this.arrows.filter(t=>t!==this.selected),this.selected=null,this.render())}_handleMouseMove(t,e){if(!this._toolbarDragging&&(!this._toolbar||t.target!==this._toolbar&&!this._toolbar.contains(t.target)))if(!this.isCtrl||t.ctrlKey){if(this.drawing&&(this.current.points[this.current.points.length-1]=e,this.render()),this._transformMode&&this.selected)return"rotate"===this._transformMode?this._handleRotate(e):"scale"===this._transformMode?"x"===this._transformAxis?this._handleScaleX(e):"y"===this._transformAxis?this._handleScaleY(e):this._handleScale(e):"rotate3d"===this._transformMode&&this._handleRotate3D(e),void this.render();if(this.selected&&"move"===this.mode){const e=t.movementX,s=t.movementY;0===e&&0===s||(this._shouldBlockClick=!0),this.selected.points.forEach(t=>{t.x+=e,t.y+=s}),this.render()}}else if(this.drawing&&this.current&&this.current.points.length>=2){this.drawing=!1,this.arrows.push(this.current);const t=this.current;this.current=null,this.svg.classList.remove("ae-d2-svg-fixed"),this.render(),this.onDrawEnd&&this.onDrawEnd({arrow:t,arrows:this.getData()})}}_getArrowBBox(t){const e=t.points;let s=1/0,n=1/0,o=-1/0,r=-1/0;for(const a of e)s=Math.min(s,a.x),n=Math.min(n,a.y),o=Math.max(o,a.x),r=Math.max(r,a.y);return{minX:s,minY:n,maxX:o,maxY:r,width:o-s,height:r-n,centerX:(s+o)/2,centerY:(n+r)/2}}_handleRotate(t){const e=this._transformCenter,s=e.centerX,n=e.centerY,o=Math.atan2(t.y-n,t.x-s)-Math.atan2(this._transformStartPos.y-n,this._transformStartPos.x-s),r=Math.cos(o),a=Math.sin(o);this.selected.points.forEach((t,e)=>{const o=this._transformStartPoints[e].x-s,i=this._transformStartPoints[e].y-n;t.x=s+o*r-i*a,t.y=n+o*a+i*r})}_handleScale(t){const e=this._transformCenter,s=e.centerX,n=e.centerY,o=this._transformStartPoints,r=this._transformStartPos,a=t.x-s,i=t.y-n,l=r.x-s,h=r.y-n,c=Math.hypot(a,i)/Math.hypot(l,h);this.selected.points.forEach((t,e)=>{t.x=s+(o[e].x-s)*c,t.y=n+(o[e].y-n)*c})}_handleScaleX(t){const e=this._transformCenter.centerX,s=this._transformStartPoints,n=this._transformStartPos,o=t.x-e,r=n.x-e,a=0!==r?o/r:1;this.selected.points.forEach((t,n)=>{t.x=e+(s[n].x-e)*a,t.y=s[n].y})}_handleScaleY(t){const e=this._transformCenter.centerY,s=this._transformStartPoints,n=this._transformStartPos,o=t.y-e,r=n.y-e,a=0!==r?o/r:1;this.selected.points.forEach((t,n)=>{t.x=s[n].x,t.y=e+(s[n].y-e)*a})}_startRotate3D(t){if(!this.selected)return;this._transformMode="rotate3d",this._transformAxis=t,this._transformCenter=this._getArrowBBox(this.selected),this._transformStartPoints=this.selected.points.map(t=>r({},t)),this._rotation3DStartAngle=0;const e=this._getArrowBBox(this.selected);this._transformStartPos="x"===t?{x:e.maxX+50,y:e.centerY}:{x:e.centerX,y:e.maxY+50};const s=t=>{const e=this._mousePos(t);this._handleRotate3D(e),this.render()},n=()=>{document.removeEventListener("mousemove",s),document.removeEventListener("mouseup",n),this.onChange&&this.onChange({type:"rotate3d",arrow:this.selected,value:t,arrows:this.getData()}),this._transformMode=null,this._transformAxis=null};document.addEventListener("mousemove",s),document.addEventListener("mouseup",n)}_handleRotate3D(t){const e=this._transformCenter,s=this._transformStartPoints;if("x"===this._transformAxis){const n=t.y-this._transformStartPos.y,o=Math.max(-90,Math.min(90,.9*-n)),r=Math.cos(o*Math.PI/180);this.selected.points.forEach((t,n)=>{t.x=s[n].x,t.y=e.centerY+(s[n].y-e.centerY)*r})}else{const n=t.x-this._transformStartPos.x,o=Math.max(-90,Math.min(90,.9*n)),r=Math.cos(o*Math.PI/180);this.selected.points.forEach((t,n)=>{t.x=e.centerX+(s[n].x-e.centerX)*r,t.y=s[n].y})}}_applyExtrude(t,e){this.selected&&(this._originalPoints||(this._originalPoints=this.selected.points.map(t=>r({},t))),this.selected.extrude={x:t,y:e},this.render(),this.onChange&&this.onChange({type:"extrude",arrow:this.selected,value:{x:t,y:e},arrows:this.getData()}))}_applySkew(t){if(!this.selected)return;const e=this._getArrowBBox(this.selected),s=e.centerX,n=e.centerY;this._originalPoints||(this._originalPoints=this.selected.points.map(t=>r({},t)));const o=.3;this.selected.points.forEach((r,a)=>{const i=this._originalPoints[a];if("x-left"===t){const t=i.y-n,s=e.height||1,a=t/s*o*s;r.x=i.x-a,r.y=i.y}else if("x-right"===t){const t=i.y-n,s=e.height||1,a=t/s*o*s;r.x=i.x+a,r.y=i.y}else if("y-up"===t){const t=i.x-s,n=e.width||1,a=t/n*o*n;r.x=i.x,r.y=i.y-a}else if("y-down"===t){const t=i.x-s,n=e.width||1,a=t/n*o*n;r.x=i.x,r.y=i.y+a}}),this.render(),this.onChange&&this.onChange({type:"skew",arrow:this.selected,value:t,arrows:this.getData()})}_applyPerspective(t){if(!this.selected)return;const e=this._getArrowBBox(this.selected),s=e.centerX,n=e.centerY;this._originalPoints||(this._originalPoints=this.selected.points.map(t=>r({},t)));const o=.3;this.selected.points.forEach((r,a)=>{const i=this._originalPoints[a];if("top"===t){const t=1-(1-(i.y-e.minY)/(e.height||1))*o;r.x=s+(i.x-s)*t,r.y=i.y}else if("bottom"===t){const t=1-(1-(e.maxY-i.y)/(e.height||1))*o;r.x=s+(i.x-s)*t,r.y=i.y}else if("left"===t){const t=1-(1-(i.x-e.minX)/(e.width||1))*o;r.x=i.x,r.y=n+(i.y-n)*t}else if("right"===t){const t=1-(1-(e.maxX-i.x)/(e.width||1))*o;r.x=i.x,r.y=n+(i.y-n)*t}}),this.render(),this.onChange&&this.onChange({type:"perspective",arrow:this.selected,value:t,arrows:this.getData()})}_resetExtrude(){this.selected&&(this.selected.extrude=null,this._originalPoints=null,this.render(),this.onChange&&this.onChange({type:"reset",arrow:this.selected,arrows:this.getData()}))}_hitArrow(t,e){for(let s=0;s<t.points.length-1;s++)if(this._dist(e,t.points[s],t.points[s+1])<15)return!0;return!1}_dist(t,e,s){const n=s.x-e.x,o=s.y-e.y,r=((t.x-e.x)*n+(t.y-e.y)*o)/(n*n+o*o),a=Math.max(0,Math.min(1,r)),i=e.x+a*n,l=e.y+a*o;return Math.hypot(t.x-i,t.y-l)}getData(){return this.arrows.map(t=>{var e,s;return{points:t.points,curveRate:null!=(s=null!=(e=t.curveRate)?e:t.cornerRoundness)?s:0,strokeWidth:t.strokeWidth,color:t.color}})}setData(t){this.arrows=t.map(t=>{var e,s;return{points:t.points,curveRate:null!=(e=t.curveRate)?e:0,strokeWidth:null!=(s=t.strokeWidth)?s:8,color:t.color}}),this.render()}clear(){this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.render()}destroy(){this._kb&&this._kb.destroy&&this._kb.destroy(),this.container.onclick=null,this.container.onmousemove=null,this.container.onmousedown=null,this.container.onmouseup=null,this.container.ondblclick=null,this.svg&&(this.svg.remove(),this.svg=null),this._toolbar&&(this._toolbar.remove(),this._toolbar=null),this._colorPickerPopup&&(this._colorPickerPopup.remove(),this._colorPickerPopup=null),this.arrows=[],this.drawing=!1,this.current=null,this.selected=null,this.mode=null,this._transformMode=null,this._transformHandle=null,this._originalPoints=null}}export{i as ArrowEditor};
|
|
2
2
|
//# sourceMappingURL=bundle.esm.js.map
|
package/dist/bundle.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.esm.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: absolute;\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: 100;\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-label {\r\n font-size: 11px;\r\n color: #666;\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 `\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 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 this.container.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 const containerRect = this.container.getBoundingClientRect()\r\n let newLeft = moveEvent.clientX - containerRect.left - dragOffset.x\r\n let newTop = moveEvent.clientY - containerRect.top - dragOffset.y\r\n const toolbarWidth = this._toolbar.offsetWidth\r\n const toolbarHeight = this._toolbar.offsetHeight\r\n newLeft = Math.max(0, Math.min(newLeft, containerRect.width - toolbarWidth))\r\n newTop = Math.max(0, Math.min(newTop, containerRect.height - toolbarHeight))\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 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 = bbox.maxX + 20\r\n if (left + toolbarWidth > this.container.offsetWidth) {\r\n left = bbox.minX - toolbarWidth - 20\r\n }\r\n\r\n // 垂直居中于箭头\r\n let top = bbox.centerY - toolbarHeight / 2\r\n if (top < 0) top = 0\r\n if (top + toolbarHeight > this.container.offsetHeight) {\r\n top = this.container.offsetHeight - toolbarHeight\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\r\n this._transformHandle = handle\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 }\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 = 25 * 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 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 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 // 旋转手柄(顶部中间)\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 this._handleScale(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 _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 }\r\n}\r\n"],"names":["document","styleEl","createElement","textContent","head","appendChild","ArrowEditor","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","dragHandle","_setupToolbarDrag","isDragging","dragOffset","x","y","_toolbarDragging","rect","getBoundingClientRect","clientX","left","clientY","top","onMove","moveEvent","containerRect","newLeft","newTop","toolbarWidth","offsetWidth","toolbarHeight","offsetHeight","Math","max","min","width","height","onUp","removeEventListener","_showToolbar","display","colorInput","roundInput","bbox","_getArrowBBox","maxX","minX","centerY","_hideToolbar","_kb","Keybinding","random","on","_handleEnter","_handleEsc","_handleDelete","_handleSpace","_handleArrowKey","points","push","__spreadValues","dx","dy","forEach","pt","onclick","contains","p","_mousePos","_handleClick","onmousemove","_handleMouseMove","onmousedown","handle","getAttribute","map","center","centerX","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","path","stroke","arrowHead","minY","scaleHandle","maxY","rotateY","rotateX","rotateLine","rotateHandle","querySelectorAll","_isDoubleClick","now","Date","dt","ctrlKey","classList","a","_hitArrow","add","_hideColorPicker","indexOf","splice","_showColorPicker","_showingColorPicker","popup","label","cssText","showPicker","ev","closeHandler","body","_colorPickerPopup","deleteSelected","filter","_handleRotate","_handleScale","movementX","movementY","Infinity","angleDiff","cos","sin","relX","relY","startPoints","startPos","startDx","startDy","_dist","b","t","tt","py","setData","data","item","clear","destroy","ondblclick"],"mappings":"yQAwIA,GAAwB,oBAAbA,SAA0B,CACnC,MAAMC,EAAUD,SAASE,cAAc,SACvCD,EAAQE,YAvIK,u/DAwIbH,SAASI,KAAKC,YAAYJ,EAC5B,CAEO,MAAMK,EAEX,WAAAC,CAAYC,EAAWC,EAAU,UAC/BC,KAAKF,UAAiC,iBAAdA,EAAyBR,SAASW,cAAcH,GAAaA,EACrFE,KAAKE,IAAM,KAEXF,KAAKG,OAAS,GACdH,KAAKI,SAAU,EACfJ,KAAKK,QAAU,KACfL,KAAKM,SAAW,KAChBN,KAAKO,KAAO,KACZP,KAAKQ,cAAgB,EACrBR,KAAKS,aAAe,KACpBT,KAAKU,mBAAoB,EACzBV,KAAKW,cAAgB,UAGrBX,KAAKY,OAASb,EAAQa,SAAU,EAChCZ,KAAKa,gBAAkBd,EAAQc,kBAAmB,EAClDb,KAAKc,eAAiBf,EAAQe,iBAAkB,EAChDd,KAAKe,UAAYhB,EAAQgB,WAAa,KACtCf,KAAKgB,SAAWjB,EAAQiB,UAAY,KACpChB,KAAKiB,SAAWlB,EAAQkB,UAAY,KAGpCjB,KAAKW,cAAgBZ,EAAQmB,cAAgBlB,KAAKW,cAClDX,KAAKmB,aAAepB,EAAQqB,oBAAsB,EAClDpB,KAAKqB,WAAa,OAAAC,EAAAvB,EAAQwB,kBAARD,EAA4B,EAG9CtB,KAAKwB,eAAiB,KACtBxB,KAAKyB,iBAAmB,KACxBzB,KAAK0B,mBAAqB,KAC1B1B,KAAK2B,sBAAwB,KAC7B3B,KAAK4B,iBAAmB,KACxB5B,KAAK6B,qBAAuB,KAC5B7B,KAAK8B,gBAAkB,EAGvB9B,KAAK+B,SAAW,KAGhB/B,KAAKgC,cAAgB,KAErBhC,KAAKiC,aACLjC,KAAKkC,mBACLlC,KAAKmC,aACP,CAEA,UAAAF,GAEE,GAAgC,oBAArBG,iBAAkC,CAEX,WADTA,iBAAiBpC,KAAKF,WAC1BuC,WACjBrC,KAAKF,UAAUwC,MAAMD,SAAW,WAEpC,CAGArC,KAAKE,IAAMZ,SAASiD,gBAAgB,6BAA8B,OAClEvC,KAAKE,IAAIsC,aAAa,QAAS,aAC/BxC,KAAKF,UAAUH,YAAYK,KAAKE,KAGhC,MAAMuC,EAAOnD,SAASiD,gBAAgB,6BAA8B,QACpEvC,KAAKE,IAAIP,YAAY8C,GAErB,MAAMC,EAASpD,SAASiD,gBAAgB,6BAA8B,UACtEG,EAAOF,aAAa,KAAM,gBAC1BE,EAAOF,aAAa,cAAe,MACnCE,EAAOF,aAAa,eAAgB,MACpCE,EAAOF,aAAa,OAAQ,KAC5BE,EAAOF,aAAa,OAAQ,KAC5BE,EAAOF,aAAa,SAAU,QAE9B,MAAMG,EAAUrD,SAASiD,gBAAgB,6BAA8B,WACvEI,EAAQH,aAAa,SAAU,qBAC/BG,EAAQH,aAAa,OAAQxC,KAAKW,eAElC+B,EAAO/C,YAAYgD,GACnBF,EAAK9C,YAAY+C,EACnB,CAEA,cAAAE,WACM5C,KAAK+B,UACP/B,KAAK+B,SAASc,SAGhB7C,KAAK+B,SAAWzC,SAASE,cAAc,OACvCQ,KAAK+B,SAASe,UAAY,aAE1B,MAAMC,EAAQ/C,KAAKM,SAASyC,OAAS/C,KAAKW,cACpCqC,EAAchD,KAAKM,SAAS0C,aAAehD,KAAKmB,aAChD8B,EAAY,OAAAC,EAAA,cAAK5C,SAAS2C,aAAajD,KAAKM,SAAS6C,iBAAzCD,EAA4D,EAE9ElD,KAAK+B,SAASqB,UAAY,2MAI8BL,2LAIkBC,iDACrCA,0MAI8CC,4BAKhEjD,KAAK+B,SAAS9B,cAAc,mBACpCoD,iBAAiB,QAAUC,IAC/BtD,KAAKM,WACVN,KAAKM,SAASyC,MAAQO,EAAEC,OAAOC,MAC/BxD,KAAKW,cAAgB2C,EAAEC,OAAOC,MAC9BxD,KAAKyD,mBAAmBH,EAAEC,OAAOC,OACjCxD,KAAK0D,SACD1D,KAAKiB,UACPjB,KAAKiB,SAAS,CAAE0C,KAAM,QAASC,MAAO5D,KAAKM,SAAUkD,MAAOF,EAAEC,OAAOC,MAAOrD,OAAQH,KAAK6D,eAK7F,MAAMC,EAAc9D,KAAK+B,SAAS9B,cAAc,oBAC1C8D,EAAc/D,KAAK+B,SAAS9B,cAAc,wCAChD6D,EAAYT,iBAAiB,QAAUC,IAChCtD,KAAKM,WACVN,KAAKM,SAAS0C,YAAcgB,SAASV,EAAEC,OAAOC,OAC9CO,EAAYtE,YAAc6D,EAAEC,OAAOC,MAAQ,KAC3CxD,KAAK0D,SACD1D,KAAKiB,UACPjB,KAAKiB,SAAS,CAAE0C,KAAM,cAAeC,MAAO5D,KAAKM,SAAUkD,MAAOQ,SAASV,EAAEC,OAAOC,OAAQrD,OAAQH,KAAK6D,eAK1F7D,KAAK+B,SAAS9B,cAAc,mBACpCoD,iBAAiB,QAAUC,IAC/BtD,KAAKM,WACVN,KAAKM,SAAS2C,UAAYgB,WAAWX,EAAEC,OAAOC,OAC9CxD,KAAK0D,SACD1D,KAAKiB,UACPjB,KAAKiB,SAAS,CAAE0C,KAAM,YAAaC,MAAO5D,KAAKM,SAAUkD,MAAOS,WAAWX,EAAEC,OAAOC,OAAQrD,OAAQH,KAAK6D,eAK7G,MAAMK,EAAalE,KAAK+B,SAAS9B,cAAc,2BAC/CD,KAAKmE,kBAAkBD,GAGvBlE,KAAK+B,SAASsB,iBAAiB,YAAcC,IAC3CA,EAAEzC,oBAEJb,KAAK+B,SAASsB,iBAAiB,UAAYC,IACzCA,EAAEzC,oBAGJb,KAAKF,UAAUH,YAAYK,KAAK+B,SAClC,CAGA,iBAAAoC,CAAkBD,GAChB,IAAIE,GAAa,EACbC,EAAa,CAAEC,EAAG,EAAGC,EAAG,GAE5BL,EAAWb,iBAAiB,YAAcC,IACxCc,GAAa,EACbpE,KAAKwE,kBAAmB,EACxB,MAAMC,EAAOzE,KAAK+B,SAAS2C,wBAC3BL,EAAWC,EAAIhB,EAAEqB,QAAUF,EAAKG,KAChCP,EAAWE,EAAIjB,EAAEuB,QAAUJ,EAAKK,IAChCxB,EAAExC,iBACFwC,EAAEzC,kBAEF,MAAMkE,EAAUC,IACd,IAAKZ,EAAY,OACjB,MAAMa,EAAgBjF,KAAKF,UAAU4E,wBACrC,IAAIQ,EAAUF,EAAUL,QAAUM,EAAcL,KAAOP,EAAWC,EAC9Da,EAASH,EAAUH,QAAUI,EAAcH,IAAMT,EAAWE,EAChE,MAAMa,EAAepF,KAAK+B,SAASsD,YAC7BC,EAAgBtF,KAAK+B,SAASwD,aACpCL,EAAUM,KAAKC,IAAI,EAAGD,KAAKE,IAAIR,EAASD,EAAcU,MAAQP,IAC9DD,EAASK,KAAKC,IAAI,EAAGD,KAAKE,IAAIP,EAAQF,EAAcW,OAASN,IAC7DtF,KAAK+B,SAASO,MAAMsC,KAAOM,EAAU,KACrClF,KAAK+B,SAASO,MAAMwC,IAAMK,EAAS,MAG/BU,EAAQvC,IACZc,GAAa,EACbpE,KAAKwE,kBAAmB,EACxBlF,SAASwG,oBAAoB,YAAaf,GAC1CzF,SAASwG,oBAAoB,UAAWD,GACxC7F,KAAK+B,SAAS+D,oBAAoB,UAAWD,GAE7CvC,EAAExC,iBACFwC,EAAEzC,mBAGJvB,SAAS+D,iBAAiB,YAAa0B,GACvCzF,SAAS+D,iBAAiB,UAAWwC,GAErC7F,KAAK+B,SAASsB,iBAAiB,UAAWwC,IAE9C,CAEA,YAAAE,WACE,GAAI/F,KAAKM,SAAU,CACZN,KAAK+B,UACR/B,KAAK4C,iBAEP5C,KAAK+B,SAASO,MAAM0D,QAAU,OAG9B,MAAMjD,EAAQ/C,KAAKM,SAASyC,OAAS/C,KAAKW,cACpCqC,EAAchD,KAAKM,SAAS0C,aAAehD,KAAKmB,aAChD8B,EAAY,OAAAC,EAAA,cAAK5C,SAAS2C,aAAajD,KAAKM,SAAS6C,iBAAzCD,EAA4D,EAExE+C,EAAajG,KAAK+B,SAAS9B,cAAc,mBACzC6D,EAAc9D,KAAK+B,SAAS9B,cAAc,oBAC1C8D,EAAc/D,KAAK+B,SAAS9B,cAAc,wCAC1CiG,EAAalG,KAAK+B,SAAS9B,cAAc,mBAE3CgG,MAAuBzC,MAAQT,GAC/Be,IACFA,EAAYN,MAAQR,EACpBe,EAAYtE,YAAcuD,EAAc,MAEtCkD,MAAuB1C,MAAQP,GAGnC,MAAMkD,EAAOnG,KAAKoG,cAAcpG,KAAKM,UAC/B8E,EAAepF,KAAK+B,SAASsD,aAAe,IAC5CC,EAAgBtF,KAAK+B,SAASwD,cAAgB,IAGpD,IAAIX,EAAOuB,EAAKE,KAAO,GACnBzB,EAAOQ,EAAepF,KAAKF,UAAUuF,cACvCT,EAAOuB,EAAKG,KAAOlB,EAAe,IAIpC,IAAIN,EAAMqB,EAAKI,QAAUjB,EAAgB,EACrCR,EAAM,IAAGA,EAAM,GACfA,EAAMQ,EAAgBtF,KAAKF,UAAUyF,eACvCT,EAAM9E,KAAKF,UAAUyF,aAAeD,GAGtCtF,KAAK+B,SAASO,MAAMsC,KAAOA,EAAO,KAClC5E,KAAK+B,SAASO,MAAMwC,IAAMA,EAAM,IAClC,CACF,CAEA,YAAA0B,GACMxG,KAAK+B,WACP/B,KAAK+B,SAASO,MAAM0D,QAAU,OAElC,CAEA,kBAAAvC,CAAmBV,GACjB,MAAML,EAAS1C,KAAKE,IAAID,cAAc,yBAClCyC,GACFA,EAAOF,aAAa,OAAQO,EAEhC,CAEA,gBAAAb,GAEElC,KAAKyG,IAAM,IAAIC,EAAW,gBAAkBlB,KAAKmB,SAAU3G,KAAKF,WAGhEE,KAAKyG,IAAIG,GAAG,QAAS,KACnB5G,KAAK6G,iBAIP7G,KAAKyG,IAAIG,GAAG,MAAO,KACjB5G,KAAK8G,eAIP9G,KAAKyG,IAAIG,GAAG,SAAU,KACpB5G,KAAK+G,kBAGP/G,KAAKyG,IAAIG,GAAG,YAAa,KACvB5G,KAAK+G,kBAIP/G,KAAKyG,IAAIG,GAAG,QAAS,KACnB5G,KAAKgH,iBAIPhH,KAAKyG,IAAIG,GAAG,UAAW,KACrB5G,KAAKiH,gBAAgB,GAAG,KAG1BjH,KAAKyG,IAAIG,GAAG,YAAa,KACvB5G,KAAKiH,gBAAgB,EAAG,KAG1BjH,KAAKyG,IAAIG,GAAG,YAAa,KACvB5G,KAAKiH,mBAAoB,KAG3BjH,KAAKyG,IAAIG,GAAG,aAAc,KACxB5G,KAAKiH,gBAAgB,EAAG,IAE5B,CAGA,YAAAD,GAEOhH,KAAKI,SAAYJ,KAAKK,SAGvBL,KAAKgC,gBACPhC,KAAKK,QAAQ6G,OAAOC,wHAAKC,CAAA,CAAA,EAAKpH,KAAKgC,gBACnChC,KAAK0D,SAET,CAGA,eAAAuD,CAAgBI,EAAIC,GAClB,IAAKtH,KAAKM,SAAU,OAGpBN,KAAKM,SAAS4G,OAAOK,QAAQC,IAC3BA,EAAGlD,GAFQ,EAEH+C,EACRG,EAAGjD,GAHQ,EAGH+C,IAGVtH,KAAK0D,SAGD1D,KAAKiB,UACPjB,KAAKiB,SAAS,CAAE0C,KAAM,OAAQC,MAAO5D,KAAKM,SAAUH,OAAQH,KAAK6D,WAErE,CAEA,WAAA1B,GACEnC,KAAKF,UAAU2H,QAAUnE,IAEvB,GAAItD,KAAK+B,WAAauB,EAAEC,SAAWvD,KAAK+B,UAAY/B,KAAK+B,SAAS2F,SAASpE,EAAEC,SAC3E,OAEEvD,KAAKc,gBAAgBwC,EAAExC,iBACvBd,KAAKa,iBAAiByC,EAAEzC,kBAC5B,MAAM8G,EAAI3H,KAAK4H,UAAUtE,GACzBtD,KAAK6H,aAAaF,EAAGrE,IAGvBtD,KAAKF,UAAUgI,YAAcxE,IACvBtD,KAAKc,gBAAgBwC,EAAExC,iBACvBd,KAAKa,iBAAiByC,EAAEzC,kBAC5B,MAAM8G,EAAI3H,KAAK4H,UAAUtE,GAEzBtD,KAAKgC,cAAgB2F,EACrB3H,KAAK+H,iBAAiBzE,EAAGqE,IAG3B3H,KAAKF,UAAUkI,YAAc1E,IAE3B,KAAItD,KAAK+B,UAAauB,EAAEC,SAAWvD,KAAK+B,WAAY/B,KAAK+B,SAAS2F,SAASpE,EAAEC,WAIzEvD,KAAKc,gBAAgBwC,EAAExC,iBACvBd,KAAKa,iBAAiByC,EAAEzC,kBAExBb,KAAKM,UAAU,CACjB,MAAM2H,EAAS3E,EAAEC,OAAO2E,aAAa,eACrC,GAAID,EAAQ,CACVjI,KAAKwB,eAAiByG,EACtBjI,KAAKyB,iBAAmBwG,EACxB,MAAMN,EAAI3H,KAAK4H,UAAUtE,GAKzB,GAJAtD,KAAK0B,mBAAqBiG,EAC1B3H,KAAK2B,sBAAwB3B,KAAKM,SAAS4G,OAAOiB,IAAIX,IAAA,CAASlD,EAAGkD,EAAGlD,EAAGC,EAAGiD,EAAGjD,KAC9EvE,KAAK4B,iBAAmB5B,KAAKoG,cAAcpG,KAAKM,UAEjC,WAAX2H,EAAqB,CACvB,MAAMG,EAASpI,KAAK4B,iBACdyF,EAAKM,EAAErD,EAAI8D,EAAOC,QAClBf,EAAKK,EAAEpD,EAAI6D,EAAO7B,QACxBvG,KAAK6B,qBAAuB2D,KAAK8C,MAAMhB,EAAID,GAC3CrH,KAAK8B,gBAAkB,CACzB,CAGA,YADAwB,EAAEzC,iBAEJ,CAEAb,KAAKO,KAAO,MACd,GAGFP,KAAKF,UAAUyI,UAAajF,IAEtBtD,KAAKwB,gBAAkBxB,KAAKM,UAC1BN,KAAKiB,UACPjB,KAAKiB,SAAS,CAAE0C,KAAM3D,KAAKwB,eAAgBoC,MAAO5D,KAAKM,SAAUH,OAAQH,KAAK6D,YAGlF7D,KAAKO,KAAO,KACZP,KAAKwB,eAAiB,KACtBxB,KAAKyB,iBAAmB,KAE5B,CAEA,SAAAmG,CAAUtE,GACR,MAAMkF,EAAIxI,KAAKF,UAAU4E,wBACzB,MAAO,CACLJ,EAAGhB,EAAEqB,QAAU6D,EAAE5D,KACjBL,EAAGjB,EAAEuB,QAAU2D,EAAE1D,IAErB,CAEA,aAAA2D,CAAcC,EAAKzF,EAAY,GAC7B,GAAIyF,EAAIC,OAAS,EAAG,MAAO,GAG3B,GAAkB,IAAd1F,EAAiB,CACnB,IAAI2F,EAAI,KAAKF,EAAI,GAAGpE,KAAKoE,EAAI,GAAGnE,IAChC,IAAA,IAASsE,EAAI,EAAGA,EAAIH,EAAIC,OAAQE,IAC9BD,GAAK,MAAMF,EAAIG,GAAGvE,KAAKoE,EAAIG,GAAGtE,IAEhC,OAAOqE,CACT,CAIA,IAAIA,EAAI,KAAKF,EAAI,GAAGpE,KAAKoE,EAAI,GAAGnE,IAEhC,IAAA,IAASsE,EAAI,EAAGA,EAAIH,EAAIC,OAAS,EAAGE,IAAK,CACvC,MAAMC,EAAOJ,EAAIG,GACXE,EAAOL,EAAIG,EAAI,GAGfxB,EAAK0B,EAAKzE,EAAIwE,EAAKxE,EACnBgD,EAAKyB,EAAKxE,EAAIuE,EAAKvE,EACnByE,EAAMxD,KAAKyD,MAAM5B,EAAIC,GAE3B,GAAY,IAAR0B,EAAW,SAGf,IAAIE,EAAO7B,EACP8B,EAAO7B,EAEX,GAAIuB,EAAI,EAAG,CACT,MAAMO,EAAOV,EAAIG,EAAI,GACrBK,EAAOJ,EAAKxE,EAAI8E,EAAK9E,EACrB6E,EAAOL,EAAKvE,EAAI6E,EAAK7E,CACvB,CAGA,IAAI8E,EAAQhC,EACRiC,EAAQhC,EAEZ,GAAIuB,EAAIH,EAAIC,OAAS,EAAG,CACtB,MAAMY,EAAQb,EAAIG,EAAI,GACtBQ,EAAQE,EAAMjF,EAAIyE,EAAKzE,EACvBgF,EAAQC,EAAMhF,EAAIwE,EAAKxE,CACzB,CAGA,MAAMiF,EAAQhE,KAAKyD,MAAMC,EAAMC,IAAS,EAClCM,EAASjE,KAAKyD,MAAMI,EAAOC,IAAU,EACrCI,EAAOR,EAAOM,EACdG,EAAOR,EAAOK,EACdI,EAAQP,EAAQI,EAChBI,EAAQP,EAAQG,EAGhBK,EAAcd,EAAM/F,EAAY,GAUtC2F,GAAK,MAPQE,EAAKxE,EAAIoF,EAAOI,KAChBhB,EAAKvE,EAAIoF,EAAOG,KAGhBf,EAAKzE,EAAIsF,EAAQE,KACjBf,EAAKxE,EAAIsF,EAAQC,KAEaf,EAAKzE,KAAKyE,EAAKxE,GAC5D,CAEA,OAAOqE,CACT,CAEA,kBAAAmB,CAAmBrB,EAAK1F,EAAc,GACpC,GAAI0F,EAAIC,OAAS,EAAG,MAAO,GAE3B,MAAMqB,EAAOtB,EAAIA,EAAIC,OAAS,GAC9B,IAAIS,EAAOV,EAAIA,EAAIC,OAAS,GAE5B,GAAID,EAAIC,QAAU,EAAG,CACNnD,KAAKyD,MAAMe,EAAK1F,EAAI8E,EAAK9E,EAAG0F,EAAKzF,EAAI6E,EAAK7E,GAC5C,IACT6E,EAAOV,EAAIA,EAAIC,OAAS,GAE5B,CAEA,MAAMtB,EAAK2C,EAAK1F,EAAI8E,EAAK9E,EACnBgD,EAAK0C,EAAKzF,EAAI6E,EAAK7E,EACnByE,EAAMxD,KAAKyD,MAAM5B,EAAIC,GAE3B,GAAI0B,EAAM,EAAG,MAAO,GAEpB,MAAMiB,EAAK5C,EAAK2B,EACVkB,EAAK5C,EAAK0B,EAGVmB,EAAQnH,EAAc,EACtBoH,EAAW,GAAKD,EAChBE,EAAa,GAAKF,EAElBG,EAAKN,EAAK1F,EACViG,EAAKP,EAAKzF,EAGViG,EAAUP,GAAMG,EAAW,GAC3BK,EAAUP,GAAME,EAAW,GAO3BM,EAAQJ,EAAKE,EAAUP,EAAKG,EAC5BO,EAAQJ,EAAKE,EAAUP,EAAKE,EAG5BQ,GAAMV,EAUZ,MAAO,KAlBMI,EAAKE,KACLD,EAAKE,OAWJC,EAAQE,EAAKP,KACbM,EAJHV,EAIgBI,OACZK,EAAQE,EAAKP,KACbM,EANJV,EAMiBI,KAI9B,CAEA,iBAAAQ,CAAkBjH,EAAOkH,WACvB,MAAMC,EAAIzL,SAASiD,gBAAgB,6BAA8B,KACjEwI,EAAEvI,aAAa,aAAcsI,GAE7B,MAAM/H,EAAQa,EAAMb,OAAS/C,KAAKW,cAC5BqC,EAAcY,EAAMZ,aAAehD,KAAKmB,aACxC8B,EAAY,OAAAC,EAAA,OAAA5B,EAAAsC,EAAMX,WAAN3B,EAAmBsC,EAAMT,iBAAzBD,EAA4C,EAExD8H,EAAO1L,SAASiD,gBAAgB,6BAA8B,QACpEyI,EAAKxI,aAAa,QAAS,iBAC3BwI,EAAK1I,MAAM2I,OAASlI,EACpBiI,EAAK1I,MAAMU,YAAcA,EAAc,KACvCgI,EAAKxI,aAAa,IAAKxC,KAAKyI,cAAc7E,EAAMsD,OAAQjE,IACxD8H,EAAEpL,YAAYqL,GAEd,MAAME,EAAY5L,SAASiD,gBAAgB,6BAA8B,QAKzE,GAJA2I,EAAU1I,aAAa,OAAQO,GAC/BmI,EAAU1I,aAAa,IAAKxC,KAAK+J,mBAAmBnG,EAAMsD,OAAQlE,IAClE+H,EAAEpL,YAAYuL,GAEVtH,IAAU5D,KAAKM,SAAU,CAC3B,MAAM6F,EAAOnG,KAAKoG,cAAcxC,GAG1Ba,EAAOnF,SAASiD,gBAAgB,6BAA8B,QACpEkC,EAAKjC,aAAa,QAAS,oBAC3BiC,EAAKjC,aAAa,IAAK2D,EAAKG,KAAO,IACnC7B,EAAKjC,aAAa,IAAK2D,EAAKgF,KAAO,IACnC1G,EAAKjC,aAAa,QAAS2D,EAAKR,MAAQ,IACxClB,EAAKjC,aAAa,SAAU2D,EAAKP,OAAS,IAC1CmF,EAAEpL,YAAY8E,GAGd,MAAM2G,EAAc9L,SAASiD,gBAAgB,6BAA8B,UAC3E6I,EAAY5I,aAAa,QAAS,uBAClC4I,EAAY5I,aAAa,KAAM2D,EAAKE,KAAO,IAC3C+E,EAAY5I,aAAa,KAAM2D,EAAKkF,KAAO,IAC3CD,EAAY5I,aAAa,IAAK,GAC9B4I,EAAY5I,aAAa,cAAe,SACxCuI,EAAEpL,YAAYyL,GAGd,MAAME,EAAUnF,EAAKgF,KAAO,GACtBI,EAAUpF,EAAKkC,QACfmD,EAAalM,SAASiD,gBAAgB,6BAA8B,QAC1EiJ,EAAWhJ,aAAa,QAAS,kBACjCgJ,EAAWhJ,aAAa,KAAM2D,EAAKkC,SACnCmD,EAAWhJ,aAAa,KAAM2D,EAAKgF,KAAO,IAC1CK,EAAWhJ,aAAa,KAAM+I,GAC9BC,EAAWhJ,aAAa,KAAM8I,GAC9BP,EAAEpL,YAAY6L,GAEd,MAAMC,EAAenM,SAASiD,gBAAgB,6BAA8B,UAC5EkJ,EAAajJ,aAAa,QAAS,oBACnCiJ,EAAajJ,aAAa,KAAM+I,GAChCE,EAAajJ,aAAa,KAAM8I,GAChCG,EAAajJ,aAAa,IAAK,GAC/BiJ,EAAajJ,aAAa,cAAe,UACzCuI,EAAEpL,YAAY8L,EAChB,CAEA,OAAOV,CACT,CAEA,MAAArH,GAQE,GAPA1D,KAAKE,IAAIwL,iBAAiB,KAAKnE,QAAQwD,GAAKA,EAAElI,UAE9C7C,KAAKG,OAAOoH,QAAQ,CAAC3D,EAAOkH,KAC1B,MAAMC,EAAI/K,KAAK6K,kBAAkBjH,EAAOkH,GACxC9K,KAAKE,IAAIP,YAAYoL,KAGnB/K,KAAKK,QAAS,CAChB,MAAM0K,EAAI/K,KAAK6K,kBAAkB7K,KAAKK,QAASL,KAAKG,OAAOwI,QAC3D3I,KAAKE,IAAIP,YAAYoL,EACvB,CACF,CAEA,cAAAY,CAAehE,GACb,MAAMiE,EAAMC,KAAKD,MACXE,EAAKF,EAAM5L,KAAKQ,cAGtB,OAFAR,KAAKQ,cAAgBoL,EAEjBE,EAAK,KAAO9L,KAAKS,cAAgB+E,KAAKyD,MAAMtB,EAAErD,EAAItE,KAAKS,aAAa6D,EAAGqD,EAAEpD,EAAIvE,KAAKS,aAAa8D,GAAK,IACtGvE,KAAKS,aAAe,MACb,IAGTT,KAAKS,aAAekH,GACb,EACT,CAEA,YAAAE,CAAaF,EAAGrE,GAEd,IAAItD,KAAKY,QAAW0C,EAAEyI,QAKtB,GAAI/L,KAAKU,kBACPV,KAAKU,mBAAoB,OAI3B,GAAIV,KAAK2L,eAAehE,IACtB,GAAI3H,KAAKI,SAAWJ,KAAKK,SAAWL,KAAKK,QAAQ6G,OAAOyB,QAAU,EAAG,CACnE3I,KAAKI,SAAU,EACfJ,KAAKG,OAAOgH,KAAKnH,KAAKK,SACtB,MAAMuD,EAAQ5D,KAAKK,QACnBL,KAAKK,QAAU,KACfL,KAAKE,IAAI8L,UAAUnJ,OAAO,mBAC1B7C,KAAK0D,SACD1D,KAAKe,WACPf,KAAKe,UAAU,CAAE6C,QAAOzD,OAAQH,KAAK6D,WAEzC,MAXF,CAgBA,GAAI7D,KAAKM,SAAU,CACjB,IAAA,MAAW2L,KAAKjM,KAAKG,OACnB,GAAIH,KAAKkM,UAAUD,EAAGtE,GAEpB,YADA3H,KAAK0D,SAQT,OAHA1D,KAAKM,SAAW,KAChBN,KAAKwG,oBACLxG,KAAK0D,QAEP,CAGA,IAAA,MAAWuI,KAAKjM,KAAKG,OACnB,GAAIH,KAAKkM,UAAUD,EAAGtE,GAIpB,OAHA3H,KAAKM,SAAW2L,EAChBjM,KAAK+F,oBACL/F,KAAK0D,SAML1D,KAAKI,QAEPJ,KAAKK,QAAQ6G,OAAOC,KAAKQ,IAGzB3H,KAAKI,SAAU,EACfJ,KAAKK,QAAU,CACb6G,OAAQ,CAACS,EAAGA,GACZ5E,MAAO/C,KAAKW,eAGdX,KAAKE,IAAI8L,UAAUG,IAAI,oBAGzBnM,KAAK0D,QA1CL,CA2CF,CAEA,YAAAmD,GAEE,GAAI7G,KAAKI,SAAWJ,KAAKK,SAAWL,KAAKK,QAAQ6G,OAAOyB,QAAU,EAAG,CACnE3I,KAAKI,SAAU,EACfJ,KAAKG,OAAOgH,KAAKnH,KAAKK,SACtB,MAAMuD,EAAQ5D,KAAKK,QACnBL,KAAKK,QAAU,KACfL,KAAKE,IAAI8L,UAAUnJ,OAAO,mBAC1B7C,KAAK0D,SACD1D,KAAKe,WACPf,KAAKe,UAAU,CAAE6C,QAAOzD,OAAQH,KAAK6D,WAEzC,CACF,CAEA,UAAAiD,GAEM9G,KAAKI,UACPJ,KAAKI,SAAU,EACfJ,KAAKK,QAAU,KACfL,KAAKE,IAAI8L,UAAUnJ,OAAO,oBAExB7C,KAAKM,WACPN,KAAKM,SAAW,MAElBN,KAAKoM,mBACLpM,KAAKwG,eACLxG,KAAK0D,QACP,CAEA,aAAAqD,GAEE,GAAI/G,KAAKM,SAAU,CACjB,MAAMsD,EAAQ5D,KAAKM,SACbwK,EAAQ9K,KAAKG,OAAOkM,QAAQrM,KAAKM,UACnCwK,GAAQ,GACV9K,KAAKG,OAAOmM,OAAOxB,EAAO,GAE5B9K,KAAKM,SAAW,KAChBN,KAAKwG,eACLxG,KAAK0D,SACD1D,KAAKgB,UACPhB,KAAKgB,SAAS,CAAE4C,QAAOzD,OAAQH,KAAK6D,WAExC,CACF,CAEA,gBAAA0I,CAAiBjJ,GACf,GAAItD,KAAKwM,oBAEP,YADAxM,KAAKoM,mBAIPpM,KAAKwM,qBAAsB,EAG3B,MAAMC,EAAQnN,SAASE,cAAc,OACrCiN,EAAM3J,UAAY,wBAElB,MAAM4J,EAAQpN,SAASE,cAAc,QACrCkN,EAAMjN,YAAc,OACpBiN,EAAMpK,MAAMqK,QAAU,gCAEtB,MAAM1G,EAAa3G,SAASE,cAAc,SAC1CyG,EAAWtC,KAAO,QAClBsC,EAAWzC,MAAQxD,KAAKM,SAASyC,OAAS/C,KAAKW,cAE/CsF,EAAW2G,aAEXH,EAAM9M,YAAY+M,GAClBD,EAAM9M,YAAYsG,GAGlB,MAAMxB,EAAOzE,KAAKF,UAAU4E,wBACtByB,EAAOnG,KAAKoG,cAAcpG,KAAKM,UAC/BgE,EAAIG,EAAKG,KAAOuB,EAAKG,KAAO,GAC5B/B,EAAIE,EAAKK,IAAMqB,EAAKkF,KAAO,GAEjCoB,EAAMnK,MAAMsC,KAAON,EAAI,KACvBmI,EAAMnK,MAAMwC,IAAMP,EAAI,KAGtB0B,EAAW5C,iBAAiB,QAAUwJ,IACpC7M,KAAKM,SAASyC,MAAQ8J,EAAGtJ,OAAOC,MAChCxD,KAAKW,cAAgBkM,EAAGtJ,OAAOC,MAC/BxD,KAAK0D,SACD1D,KAAKiB,UACPjB,KAAKiB,SAAS,CAAE0C,KAAM,QAASC,MAAO5D,KAAKM,SAAUkD,MAAOqJ,EAAGtJ,OAAOC,MAAOrD,OAAQH,KAAK6D,cAK9F,MAAMiJ,EAAgBD,IACfJ,EAAM/E,SAASmF,EAAGtJ,UACrBvD,KAAKoM,mBACL9M,SAASwG,oBAAoB,QAASgH,KAI1CxN,SAASyN,KAAKpN,YAAY8M,GAC1BzM,KAAKgN,kBAAoBP,EAEzBnN,SAAS+D,iBAAiB,QAASyJ,EACrC,CAEA,gBAAAV,GACMpM,KAAKgN,oBACPhN,KAAKgN,kBAAkBnK,SACvB7C,KAAKgN,kBAAoB,MAE3BhN,KAAKwM,qBAAsB,CAC7B,CAGA,cAAAS,GACMjN,KAAKM,WACPN,KAAKG,OAASH,KAAKG,OAAO+M,OAAOjB,GAAKA,IAAMjM,KAAKM,UACjDN,KAAKM,SAAW,KAChBN,KAAK0D,SAET,CAEA,gBAAAqE,CAAiBzE,EAAGqE,GAElB,IAAI3H,KAAKwE,oBAKLxE,KAAK+B,UAAauB,EAAEC,SAAWvD,KAAK+B,WAAY/B,KAAK+B,SAAS2F,SAASpE,EAAEC,SAK7E,IAAIvD,KAAKY,QAAW0C,EAAEyI,QAAtB,CAsBA,GANI/L,KAAKI,UACPJ,KAAKK,QAAQ6G,OAAOlH,KAAKK,QAAQ6G,OAAOyB,OAAS,GAAKhB,EACtD3H,KAAK0D,UAIH1D,KAAKwB,gBAAkBxB,KAAKM,SAO9B,MAN4B,WAAxBN,KAAKwB,eACPxB,KAAKmN,cAAcxF,GACc,UAAxB3H,KAAKwB,gBACdxB,KAAKoN,aAAazF,QAEpB3H,KAAK0D,SAIP,GAAI1D,KAAKM,UAA0B,SAAdN,KAAKO,KAAiB,CACzC,MAAM8G,EAAK/D,EAAE+J,UACP/F,EAAKhE,EAAEgK,UAGF,IAAPjG,GAAmB,IAAPC,IACdtH,KAAKU,mBAAoB,GAG3BV,KAAKM,SAAS4G,OAAOK,QAAQC,IAC3BA,EAAGlD,GAAK+C,EACRG,EAAGjD,GAAK+C,IAGVtH,KAAK0D,QACP,CAjCA,MAZE,GAAI1D,KAAKI,SAAWJ,KAAKK,SAAWL,KAAKK,QAAQ6G,OAAOyB,QAAU,EAAG,CACnE3I,KAAKI,SAAU,EACfJ,KAAKG,OAAOgH,KAAKnH,KAAKK,SACtB,MAAMuD,EAAQ5D,KAAKK,QACnBL,KAAKK,QAAU,KACfL,KAAKE,IAAI8L,UAAUnJ,OAAO,mBAC1B7C,KAAK0D,SACD1D,KAAKe,WACPf,KAAKe,UAAU,CAAE6C,QAAOzD,OAAQH,KAAK6D,WAEzC,CAoCJ,CAEA,aAAAuC,CAAcxC,GACZ,MAAMsD,EAAStD,EAAMsD,OACrB,IAAIZ,EAAOiH,IAAUpC,EAAOoC,IAAUlH,OAAkBgF,GAAOkC,IAE/D,IAAA,MAAW/F,KAAMN,EACfZ,EAAOd,KAAKE,IAAIY,EAAMkB,EAAGlD,GACzB6G,EAAO3F,KAAKE,IAAIyF,EAAM3D,EAAGjD,GACzB8B,EAAOb,KAAKC,IAAIY,EAAMmB,EAAGlD,GACzB+G,EAAO7F,KAAKC,IAAI4F,EAAM7D,EAAGjD,GAG3B,MAAO,CACL+B,OACA6E,OACA9E,OACAgF,OACA1F,MAAOU,EAAOC,EACdV,OAAQyF,EAAOF,EACf9C,SAAU/B,EAAOD,GAAQ,EACzBE,SAAU4E,EAAOE,GAAQ,EAE7B,CAEA,aAAA8B,CAAcxF,GACZ,MAAMS,EAASpI,KAAK4B,iBACdyG,EAAUD,EAAOC,QACjB9B,EAAU6B,EAAO7B,QAKjBiH,EAFehI,KAAK8C,MAAMX,EAAEpD,EAAIgC,EAASoB,EAAErD,EAAI+D,GAClC7C,KAAK8C,MAAMtI,KAAK0B,mBAAmB6C,EAAIgC,EAASvG,KAAK0B,mBAAmB4C,EAAI+D,GAIzFoF,EAAMjI,KAAKiI,IAAID,GACfE,EAAMlI,KAAKkI,IAAIF,GAErBxN,KAAKM,SAAS4G,OAAOK,QAAQ,CAACC,EAAIqB,KAChC,MAAM8E,EAAO3N,KAAK2B,sBAAsBkH,GAAGvE,EAAI+D,EACzCuF,EAAO5N,KAAK2B,sBAAsBkH,GAAGtE,EAAIgC,EAC/CiB,EAAGlD,EAAI+D,EAAUsF,EAAOF,EAAMG,EAAOF,EACrClG,EAAGjD,EAAIgC,EAAUoH,EAAOD,EAAME,EAAOH,GAEzC,CAEA,YAAAL,CAAazF,GACX,MAAMS,EAASpI,KAAK4B,iBACdyG,EAAUD,EAAOC,QACjB9B,EAAU6B,EAAO7B,QACjBsH,EAAc7N,KAAK2B,sBACnBmM,EAAW9N,KAAK0B,mBAGhB2F,EAAKM,EAAErD,EAAI+D,EACXf,EAAKK,EAAEpD,EAAIgC,EACXwH,EAAUD,EAASxJ,EAAI+D,EACvB2F,EAAUF,EAASvJ,EAAIgC,EAIvB4D,EAFc3E,KAAKyD,MAAM5B,EAAIC,GACjB9B,KAAKyD,MAAM8E,EAASC,GAItChO,KAAKM,SAAS4G,OAAOK,QAAQ,CAACC,EAAIqB,KAChCrB,EAAGlD,EAAI+D,GAAWwF,EAAYhF,GAAGvE,EAAI+D,GAAW8B,EAChD3C,EAAGjD,EAAIgC,GAAWsH,EAAYhF,GAAGtE,EAAIgC,GAAW4D,GAEpD,CAEA,SAAA+B,CAAUD,EAAGtE,GACX,IAAA,IAASkB,EAAI,EAAGA,EAAIoD,EAAE/E,OAAOyB,OAAS,EAAGE,IACvC,GAAI7I,KAAKiO,MAAMtG,EAAGsE,EAAE/E,OAAO2B,GAAIoD,EAAE/E,OAAO2B,EAAI,IAAM,GAChD,OAAO,EAEX,OAAO,CACT,CAEA,KAAAoF,CAAMtG,EAAGsE,EAAGiC,GACV,MAAM7G,EAAK6G,EAAE5J,EAAI2H,EAAE3H,EACbgD,EAAK4G,EAAE3J,EAAI0H,EAAE1H,EACb4J,IAAMxG,EAAErD,EAAI2H,EAAE3H,GAAK+C,GAAMM,EAAEpD,EAAI0H,EAAE1H,GAAK+C,IAAOD,EAAKA,EAAKC,EAAKA,GAC5D8G,EAAK5I,KAAKC,IAAI,EAAGD,KAAKE,IAAI,EAAGyI,IAC7BvD,EAAKqB,EAAE3H,EAAI8J,EAAK/G,EAChBgH,EAAKpC,EAAE1H,EAAI6J,EAAK9G,EACtB,OAAO9B,KAAKyD,MAAMtB,EAAErD,EAAIsG,EAAIjD,EAAEpD,EAAI8J,EACpC,CAGA,OAAAxK,GACE,OAAO7D,KAAKG,OAAOgI,IAAIvE,YAAU,MAAA,CAC/BsD,OAAQtD,EAAMsD,OACdjE,UAAW,OAAAC,EAAA,OAAA5B,EAAAsC,EAAMX,WAAN3B,EAAmBsC,EAAMT,iBAAzBD,EAA4C,EACvDF,YAAaY,EAAMZ,YACnBD,MAAOa,EAAMb,QAEjB,CAGA,OAAAuL,CAAQC,GACNvO,KAAKG,OAASoO,EAAKpG,IAAIqG,YAAS,MAAA,CAC9BtH,OAAQsH,EAAKtH,OACbjE,UAAW,OAAA3B,EAAAkN,EAAKvL,WAAL3B,EAAkB,EAC7B0B,YAAa,OAAAE,EAAAsL,EAAKxL,aAALE,EAAoB,EACjCH,MAAOyL,EAAKzL,SAEd/C,KAAK0D,QACP,CAGA,KAAA+K,GACEzO,KAAKG,OAAS,GACdH,KAAKI,SAAU,EACfJ,KAAKK,QAAU,KACfL,KAAKM,SAAW,KAChBN,KAAK0D,QACP,CAGA,OAAAgL,GAEM1O,KAAKyG,KAAOzG,KAAKyG,IAAIiI,SACvB1O,KAAKyG,IAAIiI,UAIX1O,KAAKF,UAAU2H,QAAU,KACzBzH,KAAKF,UAAUgI,YAAc,KAC7B9H,KAAKF,UAAUkI,YAAc,KAC7BhI,KAAKF,UAAUyI,UAAY,KAC3BvI,KAAKF,UAAU6O,WAAa,KAGxB3O,KAAKE,MACPF,KAAKE,IAAI2C,SACT7C,KAAKE,IAAM,MAITF,KAAK+B,WACP/B,KAAK+B,SAASc,SACd7C,KAAK+B,SAAW,MAId/B,KAAKgN,oBACPhN,KAAKgN,kBAAkBnK,SACvB7C,KAAKgN,kBAAoB,MAI3BhN,KAAKG,OAAS,GACdH,KAAKI,SAAU,EACfJ,KAAKK,QAAU,KACfL,KAAKM,SAAW,KAChBN,KAAKO,KAAO,KACZP,KAAKwB,eAAiB,KACtBxB,KAAKyB,iBAAmB,IAC1B"}
|
|
1
|
+
{"version":3,"file":"bundle.esm.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","ArrowEditor","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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"}
|