@wbiokr/arrow 1.0.4 → 1.0.5
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 +2 -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
package/dist/bundle.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=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-linecap: round;\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: 20;\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\n.ae-delete-btn {\n width: 100%;\n padding: 8px 12px;\n background: #ff4d4f;\n color: #fff;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: background 0.2s;\n}\n\n.ae-delete-btn:hover {\n background: #ff7875;\n}\n\n.ae-delete-btn:active {\n background: #d9363e;\n}\n',document.head.appendChild(t)}exports.ArrowEditor=class{constructor(t,e={}){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._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._strokeWidth=8,this._curveRate=0,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,n=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="${n}" />\n </div>\n <div class="ae-toolbar-item">\n <button class="ae-delete-btn">删除箭头</button>\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 o=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value");o.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.querySelector(".ae-delete-btn").addEventListener("click",()=>{if(!this.selected)return;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()})});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 n=t=>{if(!e)return;const r=this.container.getBoundingClientRect();let n=t.clientX-r.left-s.x,o=t.clientY-r.top-s.y;const i=this._toolbar.offsetWidth,a=this._toolbar.offsetHeight;n=Math.max(0,Math.min(n,r.width-i)),o=Math.max(0,Math.min(o,r.height-a)),this._toolbar.style.left=n+"px",this._toolbar.style.top=o+"px"},o=t=>{e=!1,this._toolbarDragging=!1,document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",o),this._toolbar.removeEventListener("mouseup",o),t.preventDefault(),t.stopPropagation()};document.addEventListener("mousemove",n),document.addEventListener("mouseup",o),this._toolbar.addEventListener("mouseup",o)})}_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,n=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0,o=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");o&&(o.value=s),i&&(i.value=r,a.textContent=r+"px"),l&&(l.value=n);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 t.Keybinding("arrow-editor"),this._kb.on("enter",()=>{this._handleEnter()}),this._kb.on("esc",()=>{this._handleEsc()}),this._kb.on("delete",()=>{this._handleDelete()}),this._kb.on("backspace",()=>{this._handleDelete()})}_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._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 n=t[r],o=t[r+1],i=o.x-n.x,a=o.y-n.y,l=Math.hypot(i,a);if(0===l)continue;let h=i,d=a;if(r>0){const e=t[r-1];h=n.x-e.x,d=n.y-e.y}let c=i,u=a;if(r<t.length-2){const e=t[r+2];c=e.x-o.x,u=e.y-o.y}const p=Math.hypot(h,d)||1,g=Math.hypot(c,u)||1,f=h/p,m=d/p,_=c/g,b=u/g,v=l*e*.3;s+=` C ${n.x+f*v} ${n.y+m*v} ${o.x-_*v} ${o.y-b*v} ${o.x} ${o.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 n=s.x-r.x,o=s.y-r.y,i=Math.hypot(n,o);if(i<1)return"";const a=n/i,l=o/i,h=s.x,d=s.y,c=e/8,u=40*c,p=20*c,g=20*c,f=s.x+a*g,m=s.y+l*g,_=s.x-a*(u-g),b=s.y-l*(u-g),v=-l;return`M ${f} ${m} L ${_+v*p} ${b+a*p} L ${h} ${d} L ${_-v*p} ${b-a*p} Z`}_createArrowGroup(t,e){var s,r;const n=document.createElementNS("http://www.w3.org/2000/svg","g");n.setAttribute("data-index",e);const o=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=o,l.style.strokeWidth=i+"px",l.setAttribute("d",this._generatePath(t.points,a)),n.appendChild(l);const h=document.createElementNS("http://www.w3.org/2000/svg","path");if(h.setAttribute("fill",o),h.setAttribute("d",this._generateArrowHead(t.points,i)),n.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),n.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"),n.appendChild(r);const o=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",o),n.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",o),l.setAttribute("r",8),l.setAttribute("data-handle","rotate"),n.appendChild(l)}return n}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 e!==this.selected&&(this.selected=e,this._showToolbar()),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 n=this.container.getBoundingClientRect(),o=this._getArrowBBox(this.selected),i=n.left+o.minX-50,a=n.top+o.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,n=-1/0,o=-1/0;for(const i of e)s=Math.min(s,i.x),r=Math.min(r,i.y),n=Math.max(n,i.x),o=Math.max(o,i.y);return{minX:s,minY:r,maxX:n,maxY:o,width:n-s,height:o-r,centerX:(s+n)/2,centerY:(r+o)/2}}_handleRotate(t){const e=this._transformCenter,s=e.centerX,r=e.centerY,n=Math.atan2(t.y-r,t.x-s)-Math.atan2(this._transformStartPos.y-r,this._transformStartPos.x-s),o=Math.cos(n),i=Math.sin(n);this.selected.points.forEach((t,e)=>{const n=this._transformStartPoints[e].x-s,a=this._transformStartPoints[e].y-r;t.x=s+n*o-a*i,t.y=r+n*i+a*o})}_handleScale(t){const e=this._transformCenter,s=e.centerX,r=e.centerY,n=this._transformStartPoints,o=this._transformStartPos,i=t.x-s,a=t.y-r,l=o.x-s,h=o.y-r,d=Math.hypot(i,a)/Math.hypot(l,h);this.selected.points.forEach((t,e)=>{t.x=s+(n[e].x-s)*d,t.y=r+(n[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,n=s.y-e.y,o=((t.x-e.x)*r+(t.y-e.y)*n)/(r*r+n*n),i=Math.max(0,Math.min(1,o)),a=e.x+i*r,l=e.y+i*n;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,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-linecap: round;\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: 20;\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={}){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._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._strokeWidth=8,this._curveRate=0,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.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,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,w=l*e*.3;s+=` C ${o.x+f*w} ${o.y+_*w} ${n.x-m*w} ${n.y-b*w} ${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=s.x,c=s.y,d=e/8,u=40*d,p=20*d,g=20*d,f=s.x+a*g,_=s.y+l*g,m=s.x-a*(u-g),b=s.y-l*(u-g),w=-l;return`M ${f} ${_} L ${m+w*p} ${b+a*p} L ${h} ${c} L ${m-w*p} ${b-a*p} 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}};
|
|
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'\n\n// 样式注入\nconst STYLES = `\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-linecap: round;\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: 20;\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\n.ae-delete-btn {\n width: 100%;\n padding: 8px 12px;\n background: #ff4d4f;\n color: #fff;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: background 0.2s;\n}\n\n.ae-delete-btn:hover {\n background: #ff7875;\n}\n\n.ae-delete-btn:active {\n background: #d9363e;\n}\n`\n\n// 注入样式\nif (typeof document !== 'undefined') {\n const styleEl = document.createElement('style')\n styleEl.textContent = STYLES\n document.head.appendChild(styleEl)\n}\n\nexport class ArrowEditor {\n\n constructor(container, options = {}) {\n this.container = typeof container === 'string' ? document.querySelector(container) : container\n this.svg = null\n\n this.arrows = []\n this.drawing = false\n this.current = null\n this.selected = null\n this.mode = null\n this.lastClickTime = 0\n this.lastClickPos = null\n this._shouldBlockClick = false\n this._defaultColor = '#2b8cff'\n\n // 配置选项\n this.isCtrl = options.isCtrl || false\n this.stopPropagation = options.stopPropagation || false\n this.preventDefault = options.preventDefault || false\n this.onDrawEnd = options.onDrawEnd || null\n this.onRemove = options.onRemove || null\n this.onChange = options.onChange || null\n\n // 变换相关\n this._transformMode = null // 'rotate' | 'scale'\n this._transformHandle = null\n this._transformStartPos = null\n this._transformStartPoints = null\n this._transformCenter = null\n this._transformStartAngle = null\n this._rotationOffset = 0\n\n // 工具条相关\n this._toolbar = null\n this._strokeWidth = 8\n this._curveRate = 0\n\n this._createSVG()\n this._initKeybindings()\n this._initEvents()\n }\n\n _createSVG() {\n // 检查并设置容器的定位\n if (typeof getComputedStyle !== 'undefined') {\n const containerStyle = getComputedStyle(this.container)\n if (containerStyle.position === 'static') {\n this.container.style.position = 'relative'\n }\n }\n\n // 创建 SVG 元素\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n this.svg.setAttribute('class', 'ae-d2-svg')\n this.container.appendChild(this.svg)\n\n // 创建 defs 和 marker\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\n this.svg.appendChild(defs)\n\n const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker')\n marker.setAttribute('id', 'ae-arrowhead')\n marker.setAttribute('markerWidth', '10')\n marker.setAttribute('markerHeight', '10')\n marker.setAttribute('refX', '9')\n marker.setAttribute('refY', '5')\n marker.setAttribute('orient', 'auto')\n\n const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon')\n polygon.setAttribute('points', '0,0 10,5 0,10 2,5')\n polygon.setAttribute('fill', this._defaultColor)\n\n marker.appendChild(polygon)\n defs.appendChild(marker)\n }\n\n _createToolbar() {\n if (this._toolbar) {\n this._toolbar.remove()\n }\n\n this._toolbar = document.createElement('div')\n this._toolbar.className = 'ae-toolbar'\n\n const color = this.selected.color || this._defaultColor\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\n\n 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=\"${color}\" />\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=\"${strokeWidth}\" />\n <span class=\"ae-toolbar-value\">${strokeWidth}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=\"${curveRate}\" />\n </div>\n <div class=\"ae-toolbar-item\">\n <button class=\"ae-delete-btn\">删除箭头</button>\n </div>\n `\n\n // 颜色选择\n const colorInput = this._toolbar.querySelector('.ae-color-input')\n colorInput.addEventListener('input', (e) => {\n if (!this.selected) return\n this.selected.color = e.target.value\n this._defaultColor = e.target.value\n this._updateMarkerColor(e.target.value)\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'color', arrow: this.selected, value: e.target.value, arrows: this.getData() })\n }\n })\n\n // 粗细调整\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\n strokeInput.addEventListener('input', (e) => {\n if (!this.selected) return\n this.selected.strokeWidth = parseInt(e.target.value)\n strokeValue.textContent = e.target.value + 'px'\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'strokeWidth', arrow: this.selected, value: parseInt(e.target.value), arrows: this.getData() })\n }\n })\n\n // 曲线率调整\n const roundInput = this._toolbar.querySelector('.ae-round-input')\n roundInput.addEventListener('input', (e) => {\n if (!this.selected) return\n this.selected.curveRate = parseFloat(e.target.value)\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'curveRate', arrow: this.selected, value: parseFloat(e.target.value), arrows: this.getData() })\n }\n })\n\n // 删除按钮\n const deleteBtn = this._toolbar.querySelector('.ae-delete-btn')\n deleteBtn.addEventListener('click', () => {\n if (!this.selected) return\n const arrow = this.selected\n const index = this.arrows.indexOf(this.selected)\n if (index > -1) {\n this.arrows.splice(index, 1)\n }\n this.selected = null\n this._hideToolbar()\n this.render()\n if (this.onRemove) {\n this.onRemove({ arrow, arrows: this.getData() })\n }\n })\n\n // 拖拽功能 - 使用类实例绑定\n const dragHandle = this._toolbar.querySelector('.ae-toolbar-drag-handle')\n this._setupToolbarDrag(dragHandle)\n\n // 阻止工具条上的事件触发到容器\n this._toolbar.addEventListener('mousedown', (e) => {\n e.stopPropagation()\n })\n this._toolbar.addEventListener('mouseup', (e) => {\n e.stopPropagation()\n })\n\n this.container.appendChild(this._toolbar)\n }\n\n // 工具条拖拽设置\n _setupToolbarDrag(dragHandle) {\n let isDragging = false\n let dragOffset = { x: 0, y: 0 }\n\n dragHandle.addEventListener('mousedown', (e) => {\n isDragging = true\n this._toolbarDragging = true\n const rect = this._toolbar.getBoundingClientRect()\n dragOffset.x = e.clientX - rect.left\n dragOffset.y = e.clientY - rect.top\n e.preventDefault()\n e.stopPropagation()\n\n const onMove = (moveEvent) => {\n if (!isDragging) return\n const containerRect = this.container.getBoundingClientRect()\n let newLeft = moveEvent.clientX - containerRect.left - dragOffset.x\n let newTop = moveEvent.clientY - containerRect.top - dragOffset.y\n const toolbarWidth = this._toolbar.offsetWidth\n const toolbarHeight = this._toolbar.offsetHeight\n newLeft = Math.max(0, Math.min(newLeft, containerRect.width - toolbarWidth))\n newTop = Math.max(0, Math.min(newTop, containerRect.height - toolbarHeight))\n this._toolbar.style.left = newLeft + 'px'\n this._toolbar.style.top = newTop + 'px'\n }\n\n const onUp = (e) => {\n isDragging = false\n this._toolbarDragging = false\n document.removeEventListener('mousemove', onMove)\n document.removeEventListener('mouseup', onUp)\n this._toolbar.removeEventListener('mouseup', onUp)\n \n e.preventDefault()\n e.stopPropagation()\n }\n\n document.addEventListener('mousemove', onMove)\n document.addEventListener('mouseup', onUp)\n\n this._toolbar.addEventListener('mouseup', onUp)\n })\n }\n\n _showToolbar() {\n if (this.selected) {\n if (!this._toolbar) {\n this._createToolbar()\n }\n this._toolbar.style.display = 'flex'\n\n // 更新工具条值\n const color = this.selected.color || this._defaultColor\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\n\n const colorInput = this._toolbar.querySelector('.ae-color-input')\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\n const roundInput = this._toolbar.querySelector('.ae-round-input')\n\n if (colorInput) colorInput.value = color\n if (strokeInput) {\n strokeInput.value = strokeWidth\n strokeValue.textContent = strokeWidth + 'px'\n }\n if (roundInput) roundInput.value = curveRate\n\n // 定位到所选箭头旁边\n const bbox = this._getArrowBBox(this.selected)\n const toolbarWidth = this._toolbar.offsetWidth || 150\n const toolbarHeight = this._toolbar.offsetHeight || 120\n\n // 计算位置:放在箭头右侧,如果空间不够则放左侧\n let left = bbox.maxX + 20\n if (left + toolbarWidth > this.container.offsetWidth) {\n left = bbox.minX - toolbarWidth - 20\n }\n\n // 垂直居中于箭头\n let top = bbox.centerY - toolbarHeight / 2\n if (top < 0) top = 0\n if (top + toolbarHeight > this.container.offsetHeight) {\n top = this.container.offsetHeight - toolbarHeight\n }\n\n this._toolbar.style.left = left + 'px'\n this._toolbar.style.top = top + 'px'\n }\n }\n\n _hideToolbar() {\n if (this._toolbar) {\n this._toolbar.style.display = 'none'\n }\n }\n\n _updateMarkerColor(color) {\n const marker = this.svg.querySelector('#ae-arrowhead polygon')\n if (marker) {\n marker.setAttribute('fill', color)\n }\n }\n\n _initKeybindings() {\n // 创建快捷键实例,绑定到 container 上\n this._kb = new Keybinding('arrow-editor')\n\n // Enter: 完成绘制\n this._kb.on('enter', () => {\n this._handleEnter()\n })\n\n // Esc: 结束绘制、取消选中\n this._kb.on('esc', () => {\n this._handleEsc()\n })\n\n // Delete/Backspace: 删除选中的箭头\n this._kb.on('delete', () => {\n this._handleDelete()\n })\n\n this._kb.on('backspace', () => {\n this._handleDelete()\n })\n }\n\n _initEvents() {\n this.container.onclick = e => {\n // 点击工具条时不处理\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\n return\n }\n if (this.preventDefault) e.preventDefault()\n if (this.stopPropagation) e.stopPropagation()\n const p = this._mousePos(e)\n this._handleClick(p, e)\n }\n\n this.container.onmousemove = e => {\n if (this.preventDefault) e.preventDefault()\n if (this.stopPropagation) e.stopPropagation()\n const p = this._mousePos(e)\n this._handleMouseMove(e, p)\n }\n\n this.container.onmousedown = e => {\n // 点击工具条不触发移动\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\n return\n }\n\n if (this.preventDefault) e.preventDefault()\n if (this.stopPropagation) e.stopPropagation()\n\n if (this.selected) {\n const handle = e.target.getAttribute('data-handle')\n if (handle) {\n this._transformMode = handle\n this._transformHandle = handle\n const p = this._mousePos(e)\n this._transformStartPos = p\n this._transformStartPoints = this.selected.points.map(pt => ({ x: pt.x, y: pt.y }))\n this._transformCenter = this._getArrowBBox(this.selected)\n\n if (handle === 'rotate') {\n const center = this._transformCenter\n const dx = p.x - center.centerX\n const dy = p.y - center.centerY\n this._transformStartAngle = Math.atan2(dy, dx)\n this._rotationOffset = 0\n }\n\n e.stopPropagation()\n return\n }\n\n this.mode = 'move'\n }\n }\n\n this.container.onmouseup = (e) => {\n // 如果有变换操作,调用 onChange 回调\n if (this._transformMode && this.selected) {\n if (this.onChange) {\n this.onChange({ type: this._transformMode, arrow: this.selected, arrows: this.getData() })\n }\n }\n this.mode = null\n this._transformMode = null\n this._transformHandle = null\n }\n }\n\n _mousePos(e) {\n const r = this.container.getBoundingClientRect()\n return {\n x: e.clientX - r.left,\n y: e.clientY - r.top\n }\n }\n\n _generatePath(pts, curveRate = 0) {\n if (pts.length < 2) return ''\n\n // curveRate 为 0 时画直线\n if (curveRate === 0) {\n let d = `M ${pts[0].x} ${pts[0].y}`\n for (let i = 1; i < pts.length; i++) {\n d += ` L ${pts[i].x} ${pts[i].y}`\n }\n return d\n }\n\n // 根据曲线率计算控制点位置\n // curveRate: 0 - 直线,1 - 最弯曲\n let d = `M ${pts[0].x} ${pts[0].y}`\n\n for (let i = 0; i < pts.length - 1; i++) {\n const curr = pts[i]\n const next = pts[i + 1]\n\n // 计算当前线段的向量\n const dx = next.x - curr.x\n const dy = next.y - curr.y\n const len = Math.hypot(dx, dy)\n\n if (len === 0) continue\n\n // 计算进入当前点的切线向量(前一段线段)\n let inDx = dx\n let inDy = dy\n\n if (i > 0) {\n const prev = pts[i - 1]\n inDx = curr.x - prev.x\n inDy = curr.y - prev.y\n }\n\n // 计算出当前点的切线向量(下一段线段)\n let outDx = dx\n let outDy = dy\n\n if (i < pts.length - 2) {\n const after = pts[i + 2]\n outDx = after.x - next.x\n outDy = after.y - next.y\n }\n\n // 单位向量\n const inLen = Math.hypot(inDx, inDy) || 1\n const outLen = Math.hypot(outDx, outDy) || 1\n const uxIn = inDx / inLen\n const uyIn = inDy / inLen\n const uxOut = outDx / outLen\n const uyOut = outDy / outLen\n\n // 控制点距离:曲线率 * 线段长度 * 系数\n const controlDist = len * curveRate * 0.3\n\n // 第一个控制点:从当前点沿进入方向的切线\n const cp1X = curr.x + uxIn * controlDist\n const cp1Y = curr.y + uyIn * controlDist\n\n // 第二个控制点:从下一个点沿出去方向的切线反方向\n const cp2X = next.x - uxOut * controlDist\n const cp2Y = next.y - uyOut * controlDist\n\n d += ` C ${cp1X} ${cp1Y} ${cp2X} ${cp2Y} ${next.x} ${next.y}`\n }\n\n return d\n }\n\n _generateArrowHead(pts, strokeWidth = 8) {\n if (pts.length < 2) return ''\n\n const last = pts[pts.length - 1]\n let prev = pts[pts.length - 2]\n\n if (pts.length >= 3) {\n const dist = Math.hypot(last.x - prev.x, last.y - prev.y)\n if (dist < 5) {\n prev = pts[pts.length - 3]\n }\n }\n\n const dx = last.x - prev.x\n const dy = last.y - prev.y\n const len = Math.hypot(dx, dy)\n\n if (len < 1) return ''\n\n const ux = dx / len\n const uy = dy / len\n\n const notchX = last.x\n const notchY = last.y\n\n // 根据粗细调整箭头大小\n const scale = strokeWidth / 8\n const baseLen = 40 * scale\n const baseWidth = 20 * scale\n const notchLen = 20 * scale\n\n const tipX = last.x + ux * notchLen\n const tipY = last.y + uy * notchLen\n const baseX = last.x - ux * (baseLen - notchLen)\n const baseY = last.y - uy * (baseLen - notchLen)\n\n const px = -uy\n const py = ux\n\n const leftX = baseX + px * baseWidth\n const leftY = baseY + py * baseWidth\n const rightX = baseX - px * baseWidth\n const rightY = baseY - py * baseWidth\n\n return `M ${tipX} ${tipY} L ${leftX} ${leftY} L ${notchX} ${notchY} L ${rightX} ${rightY} Z`\n }\n\n _createArrowGroup(arrow, index) {\n const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')\n g.setAttribute('data-index', index)\n\n const color = arrow.color || this._defaultColor\n const strokeWidth = arrow.strokeWidth || this._strokeWidth\n const curveRate = arrow.curveRate ?? arrow.cornerRoundness ?? 0\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('class', 'ae-arrow-path')\n path.style.stroke = color\n path.style.strokeWidth = strokeWidth + 'px'\n path.setAttribute('d', this._generatePath(arrow.points, curveRate))\n g.appendChild(path)\n\n const arrowHead = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n arrowHead.setAttribute('fill', color)\n arrowHead.setAttribute('d', this._generateArrowHead(arrow.points, strokeWidth))\n g.appendChild(arrowHead)\n\n if (arrow === this.selected) {\n const bbox = this._getArrowBBox(arrow)\n\n // 变换框\n const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')\n rect.setAttribute('class', 'ae-transform-box')\n rect.setAttribute('x', bbox.minX - 10)\n rect.setAttribute('y', bbox.minY - 10)\n rect.setAttribute('width', bbox.width + 20)\n rect.setAttribute('height', bbox.height + 20)\n g.appendChild(rect)\n\n // 缩放手柄(右下角)\n const scaleHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n scaleHandle.setAttribute('class', 'ae-transform-handle')\n scaleHandle.setAttribute('cx', bbox.maxX + 10)\n scaleHandle.setAttribute('cy', bbox.maxY + 10)\n scaleHandle.setAttribute('r', 6)\n scaleHandle.setAttribute('data-handle', 'scale')\n g.appendChild(scaleHandle)\n\n // 旋转手柄(顶部中间)\n const rotateY = bbox.minY - 30\n const rotateX = bbox.centerX\n const rotateLine = document.createElementNS('http://www.w3.org/2000/svg', 'line')\n rotateLine.setAttribute('class', 'ae-rotate-line')\n rotateLine.setAttribute('x1', bbox.centerX)\n rotateLine.setAttribute('y1', bbox.minY - 10)\n rotateLine.setAttribute('x2', rotateX)\n rotateLine.setAttribute('y2', rotateY)\n g.appendChild(rotateLine)\n\n const rotateHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n rotateHandle.setAttribute('class', 'ae-rotate-handle')\n rotateHandle.setAttribute('cx', rotateX)\n rotateHandle.setAttribute('cy', rotateY)\n rotateHandle.setAttribute('r', 8)\n rotateHandle.setAttribute('data-handle', 'rotate')\n g.appendChild(rotateHandle)\n }\n\n return g\n }\n\n render() {\n this.svg.querySelectorAll('g').forEach(g => g.remove())\n\n this.arrows.forEach((arrow, index) => {\n const g = this._createArrowGroup(arrow, index)\n this.svg.appendChild(g)\n })\n\n if (this.current) {\n const g = this._createArrowGroup(this.current, this.arrows.length)\n this.svg.appendChild(g)\n }\n }\n\n _isDoubleClick(p) {\n const now = Date.now()\n const dt = now - this.lastClickTime\n this.lastClickTime = now\n\n if (dt < 300 && this.lastClickPos && Math.hypot(p.x - this.lastClickPos.x, p.y - this.lastClickPos.y) < 10) {\n this.lastClickPos = null\n return true\n }\n\n this.lastClickPos = p\n return false\n }\n\n _handleClick(p, e) {\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\n if (this.isCtrl && !e.ctrlKey) {\n return\n }\n\n // 如果刚才有拖拽,阻止点击事件\n if (this._shouldBlockClick) {\n this._shouldBlockClick = false\n return\n }\n\n if (this._isDoubleClick(p)) {\n if (this.drawing && this.current && this.current.points.length >= 2) {\n this.drawing = false\n this.arrows.push(this.current)\n const arrow = this.current\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n this.render()\n if (this.onDrawEnd) {\n this.onDrawEnd({ arrow, arrows: this.getData() })\n }\n }\n return\n }\n\n // 有选中的箭头时,检查是否点击到其他箭头\n if (this.selected) {\n for (const a of this.arrows) {\n if (this._hitArrow(a, p)) {\n // 点击到不同的箭头,切换选中\n if (a !== this.selected) {\n this.selected = a\n this._showToolbar()\n }\n this.render()\n return\n }\n }\n // 点击空白处,取消选中\n this.selected = null\n this._hideToolbar()\n this.render()\n return\n }\n\n // 没有选中时,检查是否点击到箭头\n for (const a of this.arrows) {\n if (this._hitArrow(a, p)) {\n this.selected = a\n this._showToolbar()\n this.render()\n return\n }\n }\n\n // 点击空白处\n if (this.drawing) {\n // 正在绘制中,添加点\n this.current.points.push(p)\n } else {\n // 开始绘制\n this.drawing = true\n this.current = {\n points: [p, p],\n color: this._defaultColor\n }\n // 添加 fixed 类,让 SVG 固定定位覆盖整个视口\n this.svg.classList.add('ae-d2-svg-fixed')\n }\n\n this.render()\n }\n\n _handleEnter() {\n // 正在绘制时,按 Enter 完成绘制\n if (this.drawing && this.current && this.current.points.length >= 2) {\n this.drawing = false\n this.arrows.push(this.current)\n const arrow = this.current\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n this.render()\n if (this.onDrawEnd) {\n this.onDrawEnd({ arrow, arrows: this.getData() })\n }\n }\n }\n\n _handleEsc() {\n // 按 Esc: 结束绘制、取消选中\n if (this.drawing) {\n this.drawing = false\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n }\n if (this.selected) {\n this.selected = null\n }\n this._hideColorPicker()\n this._hideToolbar()\n this.render()\n }\n\n _handleDelete() {\n // 删除选中的箭头\n if (this.selected) {\n const arrow = this.selected\n const index = this.arrows.indexOf(this.selected)\n if (index > -1) {\n this.arrows.splice(index, 1)\n }\n this.selected = null\n this._hideToolbar()\n this.render()\n if (this.onRemove) {\n this.onRemove({ arrow, arrows: this.getData() })\n }\n }\n }\n\n _showColorPicker(e) {\n if (this._showingColorPicker) {\n this._hideColorPicker()\n return\n }\n\n this._showingColorPicker = true\n\n // 创建颜色选择器浮窗\n const popup = document.createElement('div')\n popup.className = 'ae-color-picker-popup'\n\n const label = document.createElement('span')\n label.textContent = '选择颜色'\n label.style.cssText = 'font-size: 12px; color: #666;'\n\n const colorInput = document.createElement('input')\n colorInput.type = 'color'\n colorInput.value = this.selected.color || this._defaultColor\n // 自动打开颜色选择器\n colorInput.showPicker()\n\n popup.appendChild(label)\n popup.appendChild(colorInput)\n\n // 定位到颜色手柄位置\n const rect = this.container.getBoundingClientRect()\n const bbox = this._getArrowBBox(this.selected)\n const x = rect.left + bbox.minX - 50\n const y = rect.top + bbox.maxY + 15\n\n popup.style.left = x + 'px'\n popup.style.top = y + 'px'\n\n // 颜色改变时实时更新\n colorInput.addEventListener('input', (ev) => {\n this.selected.color = ev.target.value\n this._defaultColor = ev.target.value\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'color', arrow: this.selected, value: ev.target.value, arrows: this.getData() })\n }\n })\n\n // 点击外部关闭\n const closeHandler = (ev) => {\n if (!popup.contains(ev.target)) {\n this._hideColorPicker()\n document.removeEventListener('click', closeHandler)\n }\n }\n\n document.body.appendChild(popup)\n this._colorPickerPopup = popup\n\n document.addEventListener('click', closeHandler)\n }\n\n _hideColorPicker() {\n if (this._colorPickerPopup) {\n this._colorPickerPopup.remove()\n this._colorPickerPopup = null\n }\n this._showingColorPicker = false\n }\n\n // 删除选中的箭头\n deleteSelected() {\n if (this.selected) {\n this.arrows = this.arrows.filter(a => a !== this.selected)\n this.selected = null\n this.render()\n }\n }\n\n _handleMouseMove(e, p) {\n // 如果正在拖拽工具条,不处理\n if (this._toolbarDragging) {\n return\n }\n\n // 如果鼠标在工具条上,不处理\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\n return\n }\n\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\n if (this.isCtrl && !e.ctrlKey) {\n // 如果正在绘制中,按 Ctrl 键松开则结束绘制\n if (this.drawing && this.current && this.current.points.length >= 2) {\n this.drawing = false\n this.arrows.push(this.current)\n const arrow = this.current\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n this.render()\n if (this.onDrawEnd) {\n this.onDrawEnd({ arrow, arrows: this.getData() })\n }\n }\n return\n }\n\n if (this.drawing) {\n this.current.points[this.current.points.length - 1] = p\n this.render()\n }\n\n // 变换处理(旋转/缩放)\n if (this._transformMode && this.selected) {\n if (this._transformMode === 'rotate') {\n this._handleRotate(p)\n } else if (this._transformMode === 'scale') {\n this._handleScale(p)\n }\n this.render()\n return\n }\n\n if (this.selected && this.mode === 'move') {\n const dx = e.movementX\n const dy = e.movementY\n\n // 如果有移动,标记需要阻止点击\n if (dx !== 0 || dy !== 0) {\n this._shouldBlockClick = true\n }\n\n this.selected.points.forEach(pt => {\n pt.x += dx\n pt.y += dy\n })\n\n this.render()\n }\n }\n\n _getArrowBBox(arrow) {\n const points = arrow.points\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity\n\n for (const pt of points) {\n minX = Math.min(minX, pt.x)\n minY = Math.min(minY, pt.y)\n maxX = Math.max(maxX, pt.x)\n maxY = Math.max(maxY, pt.y)\n }\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n width: maxX - minX,\n height: maxY - minY,\n centerX: (minX + maxX) / 2,\n centerY: (minY + maxY) / 2\n }\n }\n\n _handleRotate(p) {\n const center = this._transformCenter\n const centerX = center.centerX\n const centerY = center.centerY\n\n // 计算当前角度和起始角度\n const currentAngle = Math.atan2(p.y - centerY, p.x - centerX)\n const startAngle = Math.atan2(this._transformStartPos.y - centerY, this._transformStartPos.x - centerX)\n const angleDiff = currentAngle - startAngle\n\n // 旋转点\n const cos = Math.cos(angleDiff)\n const sin = Math.sin(angleDiff)\n\n this.selected.points.forEach((pt, i) => {\n const relX = this._transformStartPoints[i].x - centerX\n const relY = this._transformStartPoints[i].y - centerY\n pt.x = centerX + relX * cos - relY * sin\n pt.y = centerY + relX * sin + relY * cos\n })\n }\n\n _handleScale(p) {\n const center = this._transformCenter\n const centerX = center.centerX\n const centerY = center.centerY\n const startPoints = this._transformStartPoints\n const startPos = this._transformStartPos\n\n // 计算缩放比例\n const dx = p.x - centerX\n const dy = p.y - centerY\n const startDx = startPos.x - centerX\n const startDy = startPos.y - centerY\n\n const currentDist = Math.hypot(dx, dy)\n const startDist = Math.hypot(startDx, startDy)\n const scale = currentDist / startDist\n\n // 应用缩放\n this.selected.points.forEach((pt, i) => {\n pt.x = centerX + (startPoints[i].x - centerX) * scale\n pt.y = centerY + (startPoints[i].y - centerY) * scale\n })\n }\n\n _hitArrow(a, p) {\n for (let i = 0; i < a.points.length - 1; i++) {\n if (this._dist(p, a.points[i], a.points[i + 1]) < 15)\n return true\n }\n return false\n }\n\n _dist(p, a, b) {\n const dx = b.x - a.x\n const dy = b.y - a.y\n const t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy)\n const tt = Math.max(0, Math.min(1, t))\n const px = a.x + tt * dx\n const py = a.y + tt * dy\n return Math.hypot(p.x - px, p.y - py)\n }\n\n // 获取所有箭头数据\n getData() {\n return this.arrows.map(arrow => ({\n points: arrow.points,\n curveRate: arrow.curveRate ?? arrow.cornerRoundness ?? 0,\n strokeWidth: arrow.strokeWidth,\n color: arrow.color\n }))\n }\n\n // 设置箭头数据\n setData(data) {\n this.arrows = data.map(item => ({\n points: item.points,\n curveRate: item.curveRate ?? 0,\n strokeWidth: item.strokeWidth ?? 8,\n color: item.color\n }))\n this.render()\n }\n\n // 清空所有箭头\n clear() {\n this.arrows = []\n this.drawing = false\n this.current = null\n this.selected = null\n this.render()\n }\n\n // 销毁编辑器,移除所有事件和元素\n destroy() {\n // 销毁键盘绑定\n if (this._kb && this._kb.destroy) {\n this._kb.destroy()\n }\n\n // 移除容器上的事件\n this.container.onclick = null\n this.container.onmousemove = null\n this.container.onmousedown = null\n this.container.onmouseup = null\n this.container.ondblclick = null\n\n // 移除 SVG 元素\n if (this.svg) {\n this.svg.remove()\n this.svg = null\n }\n\n // 移除工具条\n if (this._toolbar) {\n this._toolbar.remove()\n this._toolbar = null\n }\n\n // 移除颜色选择器\n if (this._colorPickerPopup) {\n this._colorPickerPopup.remove()\n this._colorPickerPopup = null\n }\n\n // 清空数据\n this.arrows = []\n this.drawing = false\n this.current = null\n this.selected = null\n this.mode = null\n this._transformMode = null\n this._transformHandle = null\n }\n}\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","_transformMode","_transformHandle","_transformStartPos","_transformStartPoints","_transformCenter","_transformStartAngle","_rotationOffset","_toolbar","_strokeWidth","_curveRate","_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","index","indexOf","splice","_hideToolbar","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","_kb","Keybinding","on","_handleEnter","_handleEsc","_handleDelete","onclick","contains","p","_mousePos","_handleClick","onmousemove","_handleMouseMove","onmousedown","handle","getAttribute","points","map","pt","center","dx","centerX","dy","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","notchX","notchY","scale","baseLen","baseWidth","notchLen","tipX","tipY","baseX","baseY","px","_createArrowGroup","g","_a","path","stroke","arrowHead","minY","scaleHandle","maxY","rotateY","rotateX","rotateLine","rotateHandle","querySelectorAll","forEach","_isDoubleClick","now","Date","dt","ctrlKey","push","classList","a","_hitArrow","add","_hideColorPicker","_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-linecap: round;\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: 20;\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._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 this._strokeWidth = 8\r\n this._curveRate = 0\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 const notchX = last.x\r\n const notchY = last.y\r\n\r\n // 根据粗细调整箭头大小\r\n const scale = strokeWidth / 8\r\n const baseLen = 40 * scale\r\n const baseWidth = 20 * scale\r\n const notchLen = 20 * scale\r\n\r\n const tipX = last.x + ux * notchLen\r\n const tipY = last.y + uy * notchLen\r\n const baseX = last.x - ux * (baseLen - notchLen)\r\n const baseY = last.y - uy * (baseLen - notchLen)\r\n\r\n const px = -uy\r\n const py = ux\r\n\r\n const leftX = baseX + px * baseWidth\r\n const leftY = baseY + py * baseWidth\r\n const rightX = baseX - px * baseWidth\r\n const rightY = baseY - py * baseWidth\r\n\r\n return `M ${tipX} ${tipY} L ${leftX} ${leftY} L ${notchX} ${notchY} 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","_transformMode","_transformHandle","_transformStartPos","_transformStartPoints","_transformCenter","_transformStartAngle","_rotationOffset","_toolbar","_strokeWidth","_curveRate","_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","notchX","notchY","scale","baseLen","baseWidth","notchLen","tipX","tipY","baseX","baseY","px","_createArrowGroup","index","g","_a","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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"}
|
package/dist/bundle.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Keybinding as t}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-linecap: round;\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: 20;\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\n.ae-delete-btn {\n width: 100%;\n padding: 8px 12px;\n background: #ff4d4f;\n color: #fff;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: background 0.2s;\n}\n\n.ae-delete-btn:hover {\n background: #ff7875;\n}\n\n.ae-delete-btn:active {\n background: #d9363e;\n}\n',document.head.appendChild(t)}class e{constructor(t,e={}){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._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._strokeWidth=8,this._curveRate=0,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,r=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="${r}" />\n </div>\n <div class="ae-toolbar-item">\n <button class="ae-delete-btn">删除箭头</button>\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 o=this._toolbar.querySelector(".ae-stroke-input"),i=this._toolbar.querySelector(".ae-stroke-input + .ae-toolbar-value");o.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.querySelector(".ae-delete-btn").addEventListener("click",()=>{if(!this.selected)return;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()})});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 n=this._toolbar.getBoundingClientRect();s.x=t.clientX-n.left,s.y=t.clientY-n.top,t.preventDefault(),t.stopPropagation();const r=t=>{if(!e)return;const n=this.container.getBoundingClientRect();let r=t.clientX-n.left-s.x,o=t.clientY-n.top-s.y;const i=this._toolbar.offsetWidth,a=this._toolbar.offsetHeight;r=Math.max(0,Math.min(r,n.width-i)),o=Math.max(0,Math.min(o,n.height-a)),this._toolbar.style.left=r+"px",this._toolbar.style.top=o+"px"},o=t=>{e=!1,this._toolbarDragging=!1,document.removeEventListener("mousemove",r),document.removeEventListener("mouseup",o),this._toolbar.removeEventListener("mouseup",o),t.preventDefault(),t.stopPropagation()};document.addEventListener("mousemove",r),document.addEventListener("mouseup",o),this._toolbar.addEventListener("mouseup",o)})}_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,r=null!=(e=null!=(t=this.selected.curveRate)?t:this.selected.cornerRoundness)?e:0,o=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");o&&(o.value=s),i&&(i.value=n,a.textContent=n+"px"),l&&(l.value=r);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 t("arrow-editor"),this._kb.on("enter",()=>{this._handleEnter()}),this._kb.on("esc",()=>{this._handleEsc()}),this._kb.on("delete",()=>{this._handleDelete()}),this._kb.on("backspace",()=>{this._handleDelete()})}_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._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,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}}_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 r=t[n],o=t[n+1],i=o.x-r.x,a=o.y-r.y,l=Math.hypot(i,a);if(0===l)continue;let h=i,d=a;if(n>0){const e=t[n-1];h=r.x-e.x,d=r.y-e.y}let c=i,u=a;if(n<t.length-2){const e=t[n+2];c=e.x-o.x,u=e.y-o.y}const p=Math.hypot(h,d)||1,g=Math.hypot(c,u)||1,f=h/p,m=d/p,_=c/g,b=u/g,v=l*e*.3;s+=` C ${r.x+f*v} ${r.y+m*v} ${o.x-_*v} ${o.y-b*v} ${o.x} ${o.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 r=s.x-n.x,o=s.y-n.y,i=Math.hypot(r,o);if(i<1)return"";const a=r/i,l=o/i,h=s.x,d=s.y,c=e/8,u=40*c,p=20*c,g=20*c,f=s.x+a*g,m=s.y+l*g,_=s.x-a*(u-g),b=s.y-l*(u-g),v=-l;return`M ${f} ${m} L ${_+v*p} ${b+a*p} L ${h} ${d} L ${_-v*p} ${b-a*p} Z`}_createArrowGroup(t,e){var s,n;const r=document.createElementNS("http://www.w3.org/2000/svg","g");r.setAttribute("data-index",e);const o=t.color||this._defaultColor,i=t.strokeWidth||this._strokeWidth,a=null!=(n=null!=(s=t.curveRate)?s:t.cornerRoundness)?n:0,l=document.createElementNS("http://www.w3.org/2000/svg","path");l.setAttribute("class","ae-arrow-path"),l.style.stroke=o,l.style.strokeWidth=i+"px",l.setAttribute("d",this._generatePath(t.points,a)),r.appendChild(l);const h=document.createElementNS("http://www.w3.org/2000/svg","path");if(h.setAttribute("fill",o),h.setAttribute("d",this._generateArrowHead(t.points,i)),r.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),r.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"),r.appendChild(n);const o=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",o),r.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",o),l.setAttribute("r",8),l.setAttribute("data-handle","rotate"),r.appendChild(l)}return r}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 e!==this.selected&&(this.selected=e,this._showToolbar()),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 r=this.container.getBoundingClientRect(),o=this._getArrowBBox(this.selected),i=r.left+o.minX-50,a=r.top+o.maxY+15;e.style.left=i+"px",e.style.top=a+"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&&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,n=1/0,r=-1/0,o=-1/0;for(const i of e)s=Math.min(s,i.x),n=Math.min(n,i.y),r=Math.max(r,i.x),o=Math.max(o,i.y);return{minX:s,minY:n,maxX:r,maxY:o,width:r-s,height:o-n,centerX:(s+r)/2,centerY:(n+o)/2}}_handleRotate(t){const e=this._transformCenter,s=e.centerX,n=e.centerY,r=Math.atan2(t.y-n,t.x-s)-Math.atan2(this._transformStartPos.y-n,this._transformStartPos.x-s),o=Math.cos(r),i=Math.sin(r);this.selected.points.forEach((t,e)=>{const r=this._transformStartPoints[e].x-s,a=this._transformStartPoints[e].y-n;t.x=s+r*o-a*i,t.y=n+r*i+a*o})}_handleScale(t){const e=this._transformCenter,s=e.centerX,n=e.centerY,r=this._transformStartPoints,o=this._transformStartPos,i=t.x-s,a=t.y-n,l=o.x-s,h=o.y-n,d=Math.hypot(i,a)/Math.hypot(l,h);this.selected.points.forEach((t,e)=>{t.x=s+(r[e].x-s)*d,t.y=n+(r[e].y-n)*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 n=s.x-e.x,r=s.y-e.y,o=((t.x-e.x)*n+(t.y-e.y)*r)/(n*n+r*r),i=Math.max(0,Math.min(1,o)),a=e.x+i*n,l=e.y+i*r;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{e as ArrowEditor};
|
|
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-linecap: round;\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: 20;\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={}){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._transformMode=null,this._transformHandle=null,this._transformStartPos=null,this._transformStartPoints=null,this._transformCenter=null,this._transformStartAngle=null,this._rotationOffset=0,this._toolbar=null,this._strokeWidth=8,this._curveRate=0,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,w=l*e*.3;s+=` C ${o.x+f*w} ${o.y+_*w} ${n.x-m*w} ${n.y-b*w} ${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=s.x,c=s.y,d=e/8,u=40*d,p=20*d,g=20*d,f=s.x+a*g,_=s.y+l*g,m=s.x-a*(u-g),b=s.y-l*(u-g),w=-l;return`M ${f} ${_} L ${m+w*p} ${b+a*p} L ${h} ${c} L ${m-w*p} ${b-a*p} 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};
|
|
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'\n\n// 样式注入\nconst STYLES = `\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-linecap: round;\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: 20;\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\n.ae-delete-btn {\n width: 100%;\n padding: 8px 12px;\n background: #ff4d4f;\n color: #fff;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: background 0.2s;\n}\n\n.ae-delete-btn:hover {\n background: #ff7875;\n}\n\n.ae-delete-btn:active {\n background: #d9363e;\n}\n`\n\n// 注入样式\nif (typeof document !== 'undefined') {\n const styleEl = document.createElement('style')\n styleEl.textContent = STYLES\n document.head.appendChild(styleEl)\n}\n\nexport class ArrowEditor {\n\n constructor(container, options = {}) {\n this.container = typeof container === 'string' ? document.querySelector(container) : container\n this.svg = null\n\n this.arrows = []\n this.drawing = false\n this.current = null\n this.selected = null\n this.mode = null\n this.lastClickTime = 0\n this.lastClickPos = null\n this._shouldBlockClick = false\n this._defaultColor = '#2b8cff'\n\n // 配置选项\n this.isCtrl = options.isCtrl || false\n this.stopPropagation = options.stopPropagation || false\n this.preventDefault = options.preventDefault || false\n this.onDrawEnd = options.onDrawEnd || null\n this.onRemove = options.onRemove || null\n this.onChange = options.onChange || null\n\n // 变换相关\n this._transformMode = null // 'rotate' | 'scale'\n this._transformHandle = null\n this._transformStartPos = null\n this._transformStartPoints = null\n this._transformCenter = null\n this._transformStartAngle = null\n this._rotationOffset = 0\n\n // 工具条相关\n this._toolbar = null\n this._strokeWidth = 8\n this._curveRate = 0\n\n this._createSVG()\n this._initKeybindings()\n this._initEvents()\n }\n\n _createSVG() {\n // 检查并设置容器的定位\n if (typeof getComputedStyle !== 'undefined') {\n const containerStyle = getComputedStyle(this.container)\n if (containerStyle.position === 'static') {\n this.container.style.position = 'relative'\n }\n }\n\n // 创建 SVG 元素\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n this.svg.setAttribute('class', 'ae-d2-svg')\n this.container.appendChild(this.svg)\n\n // 创建 defs 和 marker\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs')\n this.svg.appendChild(defs)\n\n const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker')\n marker.setAttribute('id', 'ae-arrowhead')\n marker.setAttribute('markerWidth', '10')\n marker.setAttribute('markerHeight', '10')\n marker.setAttribute('refX', '9')\n marker.setAttribute('refY', '5')\n marker.setAttribute('orient', 'auto')\n\n const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon')\n polygon.setAttribute('points', '0,0 10,5 0,10 2,5')\n polygon.setAttribute('fill', this._defaultColor)\n\n marker.appendChild(polygon)\n defs.appendChild(marker)\n }\n\n _createToolbar() {\n if (this._toolbar) {\n this._toolbar.remove()\n }\n\n this._toolbar = document.createElement('div')\n this._toolbar.className = 'ae-toolbar'\n\n const color = this.selected.color || this._defaultColor\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\n\n 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=\"${color}\" />\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=\"${strokeWidth}\" />\n <span class=\"ae-toolbar-value\">${strokeWidth}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=\"${curveRate}\" />\n </div>\n <div class=\"ae-toolbar-item\">\n <button class=\"ae-delete-btn\">删除箭头</button>\n </div>\n `\n\n // 颜色选择\n const colorInput = this._toolbar.querySelector('.ae-color-input')\n colorInput.addEventListener('input', (e) => {\n if (!this.selected) return\n this.selected.color = e.target.value\n this._defaultColor = e.target.value\n this._updateMarkerColor(e.target.value)\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'color', arrow: this.selected, value: e.target.value, arrows: this.getData() })\n }\n })\n\n // 粗细调整\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\n strokeInput.addEventListener('input', (e) => {\n if (!this.selected) return\n this.selected.strokeWidth = parseInt(e.target.value)\n strokeValue.textContent = e.target.value + 'px'\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'strokeWidth', arrow: this.selected, value: parseInt(e.target.value), arrows: this.getData() })\n }\n })\n\n // 曲线率调整\n const roundInput = this._toolbar.querySelector('.ae-round-input')\n roundInput.addEventListener('input', (e) => {\n if (!this.selected) return\n this.selected.curveRate = parseFloat(e.target.value)\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'curveRate', arrow: this.selected, value: parseFloat(e.target.value), arrows: this.getData() })\n }\n })\n\n // 删除按钮\n const deleteBtn = this._toolbar.querySelector('.ae-delete-btn')\n deleteBtn.addEventListener('click', () => {\n if (!this.selected) return\n const arrow = this.selected\n const index = this.arrows.indexOf(this.selected)\n if (index > -1) {\n this.arrows.splice(index, 1)\n }\n this.selected = null\n this._hideToolbar()\n this.render()\n if (this.onRemove) {\n this.onRemove({ arrow, arrows: this.getData() })\n }\n })\n\n // 拖拽功能 - 使用类实例绑定\n const dragHandle = this._toolbar.querySelector('.ae-toolbar-drag-handle')\n this._setupToolbarDrag(dragHandle)\n\n // 阻止工具条上的事件触发到容器\n this._toolbar.addEventListener('mousedown', (e) => {\n e.stopPropagation()\n })\n this._toolbar.addEventListener('mouseup', (e) => {\n e.stopPropagation()\n })\n\n this.container.appendChild(this._toolbar)\n }\n\n // 工具条拖拽设置\n _setupToolbarDrag(dragHandle) {\n let isDragging = false\n let dragOffset = { x: 0, y: 0 }\n\n dragHandle.addEventListener('mousedown', (e) => {\n isDragging = true\n this._toolbarDragging = true\n const rect = this._toolbar.getBoundingClientRect()\n dragOffset.x = e.clientX - rect.left\n dragOffset.y = e.clientY - rect.top\n e.preventDefault()\n e.stopPropagation()\n\n const onMove = (moveEvent) => {\n if (!isDragging) return\n const containerRect = this.container.getBoundingClientRect()\n let newLeft = moveEvent.clientX - containerRect.left - dragOffset.x\n let newTop = moveEvent.clientY - containerRect.top - dragOffset.y\n const toolbarWidth = this._toolbar.offsetWidth\n const toolbarHeight = this._toolbar.offsetHeight\n newLeft = Math.max(0, Math.min(newLeft, containerRect.width - toolbarWidth))\n newTop = Math.max(0, Math.min(newTop, containerRect.height - toolbarHeight))\n this._toolbar.style.left = newLeft + 'px'\n this._toolbar.style.top = newTop + 'px'\n }\n\n const onUp = (e) => {\n isDragging = false\n this._toolbarDragging = false\n document.removeEventListener('mousemove', onMove)\n document.removeEventListener('mouseup', onUp)\n this._toolbar.removeEventListener('mouseup', onUp)\n \n e.preventDefault()\n e.stopPropagation()\n }\n\n document.addEventListener('mousemove', onMove)\n document.addEventListener('mouseup', onUp)\n\n this._toolbar.addEventListener('mouseup', onUp)\n })\n }\n\n _showToolbar() {\n if (this.selected) {\n if (!this._toolbar) {\n this._createToolbar()\n }\n this._toolbar.style.display = 'flex'\n\n // 更新工具条值\n const color = this.selected.color || this._defaultColor\n const strokeWidth = this.selected.strokeWidth || this._strokeWidth\n const curveRate = this.selected.curveRate ?? this.selected.cornerRoundness ?? 0\n\n const colorInput = this._toolbar.querySelector('.ae-color-input')\n const strokeInput = this._toolbar.querySelector('.ae-stroke-input')\n const strokeValue = this._toolbar.querySelector('.ae-stroke-input + .ae-toolbar-value')\n const roundInput = this._toolbar.querySelector('.ae-round-input')\n\n if (colorInput) colorInput.value = color\n if (strokeInput) {\n strokeInput.value = strokeWidth\n strokeValue.textContent = strokeWidth + 'px'\n }\n if (roundInput) roundInput.value = curveRate\n\n // 定位到所选箭头旁边\n const bbox = this._getArrowBBox(this.selected)\n const toolbarWidth = this._toolbar.offsetWidth || 150\n const toolbarHeight = this._toolbar.offsetHeight || 120\n\n // 计算位置:放在箭头右侧,如果空间不够则放左侧\n let left = bbox.maxX + 20\n if (left + toolbarWidth > this.container.offsetWidth) {\n left = bbox.minX - toolbarWidth - 20\n }\n\n // 垂直居中于箭头\n let top = bbox.centerY - toolbarHeight / 2\n if (top < 0) top = 0\n if (top + toolbarHeight > this.container.offsetHeight) {\n top = this.container.offsetHeight - toolbarHeight\n }\n\n this._toolbar.style.left = left + 'px'\n this._toolbar.style.top = top + 'px'\n }\n }\n\n _hideToolbar() {\n if (this._toolbar) {\n this._toolbar.style.display = 'none'\n }\n }\n\n _updateMarkerColor(color) {\n const marker = this.svg.querySelector('#ae-arrowhead polygon')\n if (marker) {\n marker.setAttribute('fill', color)\n }\n }\n\n _initKeybindings() {\n // 创建快捷键实例,绑定到 container 上\n this._kb = new Keybinding('arrow-editor')\n\n // Enter: 完成绘制\n this._kb.on('enter', () => {\n this._handleEnter()\n })\n\n // Esc: 结束绘制、取消选中\n this._kb.on('esc', () => {\n this._handleEsc()\n })\n\n // Delete/Backspace: 删除选中的箭头\n this._kb.on('delete', () => {\n this._handleDelete()\n })\n\n this._kb.on('backspace', () => {\n this._handleDelete()\n })\n }\n\n _initEvents() {\n this.container.onclick = e => {\n // 点击工具条时不处理\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\n return\n }\n if (this.preventDefault) e.preventDefault()\n if (this.stopPropagation) e.stopPropagation()\n const p = this._mousePos(e)\n this._handleClick(p, e)\n }\n\n this.container.onmousemove = e => {\n if (this.preventDefault) e.preventDefault()\n if (this.stopPropagation) e.stopPropagation()\n const p = this._mousePos(e)\n this._handleMouseMove(e, p)\n }\n\n this.container.onmousedown = e => {\n // 点击工具条不触发移动\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\n return\n }\n\n if (this.preventDefault) e.preventDefault()\n if (this.stopPropagation) e.stopPropagation()\n\n if (this.selected) {\n const handle = e.target.getAttribute('data-handle')\n if (handle) {\n this._transformMode = handle\n this._transformHandle = handle\n const p = this._mousePos(e)\n this._transformStartPos = p\n this._transformStartPoints = this.selected.points.map(pt => ({ x: pt.x, y: pt.y }))\n this._transformCenter = this._getArrowBBox(this.selected)\n\n if (handle === 'rotate') {\n const center = this._transformCenter\n const dx = p.x - center.centerX\n const dy = p.y - center.centerY\n this._transformStartAngle = Math.atan2(dy, dx)\n this._rotationOffset = 0\n }\n\n e.stopPropagation()\n return\n }\n\n this.mode = 'move'\n }\n }\n\n this.container.onmouseup = (e) => {\n // 如果有变换操作,调用 onChange 回调\n if (this._transformMode && this.selected) {\n if (this.onChange) {\n this.onChange({ type: this._transformMode, arrow: this.selected, arrows: this.getData() })\n }\n }\n this.mode = null\n this._transformMode = null\n this._transformHandle = null\n }\n }\n\n _mousePos(e) {\n const r = this.container.getBoundingClientRect()\n return {\n x: e.clientX - r.left,\n y: e.clientY - r.top\n }\n }\n\n _generatePath(pts, curveRate = 0) {\n if (pts.length < 2) return ''\n\n // curveRate 为 0 时画直线\n if (curveRate === 0) {\n let d = `M ${pts[0].x} ${pts[0].y}`\n for (let i = 1; i < pts.length; i++) {\n d += ` L ${pts[i].x} ${pts[i].y}`\n }\n return d\n }\n\n // 根据曲线率计算控制点位置\n // curveRate: 0 - 直线,1 - 最弯曲\n let d = `M ${pts[0].x} ${pts[0].y}`\n\n for (let i = 0; i < pts.length - 1; i++) {\n const curr = pts[i]\n const next = pts[i + 1]\n\n // 计算当前线段的向量\n const dx = next.x - curr.x\n const dy = next.y - curr.y\n const len = Math.hypot(dx, dy)\n\n if (len === 0) continue\n\n // 计算进入当前点的切线向量(前一段线段)\n let inDx = dx\n let inDy = dy\n\n if (i > 0) {\n const prev = pts[i - 1]\n inDx = curr.x - prev.x\n inDy = curr.y - prev.y\n }\n\n // 计算出当前点的切线向量(下一段线段)\n let outDx = dx\n let outDy = dy\n\n if (i < pts.length - 2) {\n const after = pts[i + 2]\n outDx = after.x - next.x\n outDy = after.y - next.y\n }\n\n // 单位向量\n const inLen = Math.hypot(inDx, inDy) || 1\n const outLen = Math.hypot(outDx, outDy) || 1\n const uxIn = inDx / inLen\n const uyIn = inDy / inLen\n const uxOut = outDx / outLen\n const uyOut = outDy / outLen\n\n // 控制点距离:曲线率 * 线段长度 * 系数\n const controlDist = len * curveRate * 0.3\n\n // 第一个控制点:从当前点沿进入方向的切线\n const cp1X = curr.x + uxIn * controlDist\n const cp1Y = curr.y + uyIn * controlDist\n\n // 第二个控制点:从下一个点沿出去方向的切线反方向\n const cp2X = next.x - uxOut * controlDist\n const cp2Y = next.y - uyOut * controlDist\n\n d += ` C ${cp1X} ${cp1Y} ${cp2X} ${cp2Y} ${next.x} ${next.y}`\n }\n\n return d\n }\n\n _generateArrowHead(pts, strokeWidth = 8) {\n if (pts.length < 2) return ''\n\n const last = pts[pts.length - 1]\n let prev = pts[pts.length - 2]\n\n if (pts.length >= 3) {\n const dist = Math.hypot(last.x - prev.x, last.y - prev.y)\n if (dist < 5) {\n prev = pts[pts.length - 3]\n }\n }\n\n const dx = last.x - prev.x\n const dy = last.y - prev.y\n const len = Math.hypot(dx, dy)\n\n if (len < 1) return ''\n\n const ux = dx / len\n const uy = dy / len\n\n const notchX = last.x\n const notchY = last.y\n\n // 根据粗细调整箭头大小\n const scale = strokeWidth / 8\n const baseLen = 40 * scale\n const baseWidth = 20 * scale\n const notchLen = 20 * scale\n\n const tipX = last.x + ux * notchLen\n const tipY = last.y + uy * notchLen\n const baseX = last.x - ux * (baseLen - notchLen)\n const baseY = last.y - uy * (baseLen - notchLen)\n\n const px = -uy\n const py = ux\n\n const leftX = baseX + px * baseWidth\n const leftY = baseY + py * baseWidth\n const rightX = baseX - px * baseWidth\n const rightY = baseY - py * baseWidth\n\n return `M ${tipX} ${tipY} L ${leftX} ${leftY} L ${notchX} ${notchY} L ${rightX} ${rightY} Z`\n }\n\n _createArrowGroup(arrow, index) {\n const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')\n g.setAttribute('data-index', index)\n\n const color = arrow.color || this._defaultColor\n const strokeWidth = arrow.strokeWidth || this._strokeWidth\n const curveRate = arrow.curveRate ?? arrow.cornerRoundness ?? 0\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('class', 'ae-arrow-path')\n path.style.stroke = color\n path.style.strokeWidth = strokeWidth + 'px'\n path.setAttribute('d', this._generatePath(arrow.points, curveRate))\n g.appendChild(path)\n\n const arrowHead = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n arrowHead.setAttribute('fill', color)\n arrowHead.setAttribute('d', this._generateArrowHead(arrow.points, strokeWidth))\n g.appendChild(arrowHead)\n\n if (arrow === this.selected) {\n const bbox = this._getArrowBBox(arrow)\n\n // 变换框\n const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')\n rect.setAttribute('class', 'ae-transform-box')\n rect.setAttribute('x', bbox.minX - 10)\n rect.setAttribute('y', bbox.minY - 10)\n rect.setAttribute('width', bbox.width + 20)\n rect.setAttribute('height', bbox.height + 20)\n g.appendChild(rect)\n\n // 缩放手柄(右下角)\n const scaleHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n scaleHandle.setAttribute('class', 'ae-transform-handle')\n scaleHandle.setAttribute('cx', bbox.maxX + 10)\n scaleHandle.setAttribute('cy', bbox.maxY + 10)\n scaleHandle.setAttribute('r', 6)\n scaleHandle.setAttribute('data-handle', 'scale')\n g.appendChild(scaleHandle)\n\n // 旋转手柄(顶部中间)\n const rotateY = bbox.minY - 30\n const rotateX = bbox.centerX\n const rotateLine = document.createElementNS('http://www.w3.org/2000/svg', 'line')\n rotateLine.setAttribute('class', 'ae-rotate-line')\n rotateLine.setAttribute('x1', bbox.centerX)\n rotateLine.setAttribute('y1', bbox.minY - 10)\n rotateLine.setAttribute('x2', rotateX)\n rotateLine.setAttribute('y2', rotateY)\n g.appendChild(rotateLine)\n\n const rotateHandle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n rotateHandle.setAttribute('class', 'ae-rotate-handle')\n rotateHandle.setAttribute('cx', rotateX)\n rotateHandle.setAttribute('cy', rotateY)\n rotateHandle.setAttribute('r', 8)\n rotateHandle.setAttribute('data-handle', 'rotate')\n g.appendChild(rotateHandle)\n }\n\n return g\n }\n\n render() {\n this.svg.querySelectorAll('g').forEach(g => g.remove())\n\n this.arrows.forEach((arrow, index) => {\n const g = this._createArrowGroup(arrow, index)\n this.svg.appendChild(g)\n })\n\n if (this.current) {\n const g = this._createArrowGroup(this.current, this.arrows.length)\n this.svg.appendChild(g)\n }\n }\n\n _isDoubleClick(p) {\n const now = Date.now()\n const dt = now - this.lastClickTime\n this.lastClickTime = now\n\n if (dt < 300 && this.lastClickPos && Math.hypot(p.x - this.lastClickPos.x, p.y - this.lastClickPos.y) < 10) {\n this.lastClickPos = null\n return true\n }\n\n this.lastClickPos = p\n return false\n }\n\n _handleClick(p, e) {\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\n if (this.isCtrl && !e.ctrlKey) {\n return\n }\n\n // 如果刚才有拖拽,阻止点击事件\n if (this._shouldBlockClick) {\n this._shouldBlockClick = false\n return\n }\n\n if (this._isDoubleClick(p)) {\n if (this.drawing && this.current && this.current.points.length >= 2) {\n this.drawing = false\n this.arrows.push(this.current)\n const arrow = this.current\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n this.render()\n if (this.onDrawEnd) {\n this.onDrawEnd({ arrow, arrows: this.getData() })\n }\n }\n return\n }\n\n // 有选中的箭头时,检查是否点击到其他箭头\n if (this.selected) {\n for (const a of this.arrows) {\n if (this._hitArrow(a, p)) {\n // 点击到不同的箭头,切换选中\n if (a !== this.selected) {\n this.selected = a\n this._showToolbar()\n }\n this.render()\n return\n }\n }\n // 点击空白处,取消选中\n this.selected = null\n this._hideToolbar()\n this.render()\n return\n }\n\n // 没有选中时,检查是否点击到箭头\n for (const a of this.arrows) {\n if (this._hitArrow(a, p)) {\n this.selected = a\n this._showToolbar()\n this.render()\n return\n }\n }\n\n // 点击空白处\n if (this.drawing) {\n // 正在绘制中,添加点\n this.current.points.push(p)\n } else {\n // 开始绘制\n this.drawing = true\n this.current = {\n points: [p, p],\n color: this._defaultColor\n }\n // 添加 fixed 类,让 SVG 固定定位覆盖整个视口\n this.svg.classList.add('ae-d2-svg-fixed')\n }\n\n this.render()\n }\n\n _handleEnter() {\n // 正在绘制时,按 Enter 完成绘制\n if (this.drawing && this.current && this.current.points.length >= 2) {\n this.drawing = false\n this.arrows.push(this.current)\n const arrow = this.current\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n this.render()\n if (this.onDrawEnd) {\n this.onDrawEnd({ arrow, arrows: this.getData() })\n }\n }\n }\n\n _handleEsc() {\n // 按 Esc: 结束绘制、取消选中\n if (this.drawing) {\n this.drawing = false\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n }\n if (this.selected) {\n this.selected = null\n }\n this._hideColorPicker()\n this._hideToolbar()\n this.render()\n }\n\n _handleDelete() {\n // 删除选中的箭头\n if (this.selected) {\n const arrow = this.selected\n const index = this.arrows.indexOf(this.selected)\n if (index > -1) {\n this.arrows.splice(index, 1)\n }\n this.selected = null\n this._hideToolbar()\n this.render()\n if (this.onRemove) {\n this.onRemove({ arrow, arrows: this.getData() })\n }\n }\n }\n\n _showColorPicker(e) {\n if (this._showingColorPicker) {\n this._hideColorPicker()\n return\n }\n\n this._showingColorPicker = true\n\n // 创建颜色选择器浮窗\n const popup = document.createElement('div')\n popup.className = 'ae-color-picker-popup'\n\n const label = document.createElement('span')\n label.textContent = '选择颜色'\n label.style.cssText = 'font-size: 12px; color: #666;'\n\n const colorInput = document.createElement('input')\n colorInput.type = 'color'\n colorInput.value = this.selected.color || this._defaultColor\n // 自动打开颜色选择器\n colorInput.showPicker()\n\n popup.appendChild(label)\n popup.appendChild(colorInput)\n\n // 定位到颜色手柄位置\n const rect = this.container.getBoundingClientRect()\n const bbox = this._getArrowBBox(this.selected)\n const x = rect.left + bbox.minX - 50\n const y = rect.top + bbox.maxY + 15\n\n popup.style.left = x + 'px'\n popup.style.top = y + 'px'\n\n // 颜色改变时实时更新\n colorInput.addEventListener('input', (ev) => {\n this.selected.color = ev.target.value\n this._defaultColor = ev.target.value\n this.render()\n if (this.onChange) {\n this.onChange({ type: 'color', arrow: this.selected, value: ev.target.value, arrows: this.getData() })\n }\n })\n\n // 点击外部关闭\n const closeHandler = (ev) => {\n if (!popup.contains(ev.target)) {\n this._hideColorPicker()\n document.removeEventListener('click', closeHandler)\n }\n }\n\n document.body.appendChild(popup)\n this._colorPickerPopup = popup\n\n document.addEventListener('click', closeHandler)\n }\n\n _hideColorPicker() {\n if (this._colorPickerPopup) {\n this._colorPickerPopup.remove()\n this._colorPickerPopup = null\n }\n this._showingColorPicker = false\n }\n\n // 删除选中的箭头\n deleteSelected() {\n if (this.selected) {\n this.arrows = this.arrows.filter(a => a !== this.selected)\n this.selected = null\n this.render()\n }\n }\n\n _handleMouseMove(e, p) {\n // 如果正在拖拽工具条,不处理\n if (this._toolbarDragging) {\n return\n }\n\n // 如果鼠标在工具条上,不处理\n if (this._toolbar && (e.target === this._toolbar || this._toolbar.contains(e.target))) {\n return\n }\n\n // 如果配置了 isCtrl,需要按着 Ctrl 键才能绘制\n if (this.isCtrl && !e.ctrlKey) {\n // 如果正在绘制中,按 Ctrl 键松开则结束绘制\n if (this.drawing && this.current && this.current.points.length >= 2) {\n this.drawing = false\n this.arrows.push(this.current)\n const arrow = this.current\n this.current = null\n this.svg.classList.remove('ae-d2-svg-fixed')\n this.render()\n if (this.onDrawEnd) {\n this.onDrawEnd({ arrow, arrows: this.getData() })\n }\n }\n return\n }\n\n if (this.drawing) {\n this.current.points[this.current.points.length - 1] = p\n this.render()\n }\n\n // 变换处理(旋转/缩放)\n if (this._transformMode && this.selected) {\n if (this._transformMode === 'rotate') {\n this._handleRotate(p)\n } else if (this._transformMode === 'scale') {\n this._handleScale(p)\n }\n this.render()\n return\n }\n\n if (this.selected && this.mode === 'move') {\n const dx = e.movementX\n const dy = e.movementY\n\n // 如果有移动,标记需要阻止点击\n if (dx !== 0 || dy !== 0) {\n this._shouldBlockClick = true\n }\n\n this.selected.points.forEach(pt => {\n pt.x += dx\n pt.y += dy\n })\n\n this.render()\n }\n }\n\n _getArrowBBox(arrow) {\n const points = arrow.points\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity\n\n for (const pt of points) {\n minX = Math.min(minX, pt.x)\n minY = Math.min(minY, pt.y)\n maxX = Math.max(maxX, pt.x)\n maxY = Math.max(maxY, pt.y)\n }\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n width: maxX - minX,\n height: maxY - minY,\n centerX: (minX + maxX) / 2,\n centerY: (minY + maxY) / 2\n }\n }\n\n _handleRotate(p) {\n const center = this._transformCenter\n const centerX = center.centerX\n const centerY = center.centerY\n\n // 计算当前角度和起始角度\n const currentAngle = Math.atan2(p.y - centerY, p.x - centerX)\n const startAngle = Math.atan2(this._transformStartPos.y - centerY, this._transformStartPos.x - centerX)\n const angleDiff = currentAngle - startAngle\n\n // 旋转点\n const cos = Math.cos(angleDiff)\n const sin = Math.sin(angleDiff)\n\n this.selected.points.forEach((pt, i) => {\n const relX = this._transformStartPoints[i].x - centerX\n const relY = this._transformStartPoints[i].y - centerY\n pt.x = centerX + relX * cos - relY * sin\n pt.y = centerY + relX * sin + relY * cos\n })\n }\n\n _handleScale(p) {\n const center = this._transformCenter\n const centerX = center.centerX\n const centerY = center.centerY\n const startPoints = this._transformStartPoints\n const startPos = this._transformStartPos\n\n // 计算缩放比例\n const dx = p.x - centerX\n const dy = p.y - centerY\n const startDx = startPos.x - centerX\n const startDy = startPos.y - centerY\n\n const currentDist = Math.hypot(dx, dy)\n const startDist = Math.hypot(startDx, startDy)\n const scale = currentDist / startDist\n\n // 应用缩放\n this.selected.points.forEach((pt, i) => {\n pt.x = centerX + (startPoints[i].x - centerX) * scale\n pt.y = centerY + (startPoints[i].y - centerY) * scale\n })\n }\n\n _hitArrow(a, p) {\n for (let i = 0; i < a.points.length - 1; i++) {\n if (this._dist(p, a.points[i], a.points[i + 1]) < 15)\n return true\n }\n return false\n }\n\n _dist(p, a, b) {\n const dx = b.x - a.x\n const dy = b.y - a.y\n const t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy)\n const tt = Math.max(0, Math.min(1, t))\n const px = a.x + tt * dx\n const py = a.y + tt * dy\n return Math.hypot(p.x - px, p.y - py)\n }\n\n // 获取所有箭头数据\n getData() {\n return this.arrows.map(arrow => ({\n points: arrow.points,\n curveRate: arrow.curveRate ?? arrow.cornerRoundness ?? 0,\n strokeWidth: arrow.strokeWidth,\n color: arrow.color\n }))\n }\n\n // 设置箭头数据\n setData(data) {\n this.arrows = data.map(item => ({\n points: item.points,\n curveRate: item.curveRate ?? 0,\n strokeWidth: item.strokeWidth ?? 8,\n color: item.color\n }))\n this.render()\n }\n\n // 清空所有箭头\n clear() {\n this.arrows = []\n this.drawing = false\n this.current = null\n this.selected = null\n this.render()\n }\n\n // 销毁编辑器,移除所有事件和元素\n destroy() {\n // 销毁键盘绑定\n if (this._kb && this._kb.destroy) {\n this._kb.destroy()\n }\n\n // 移除容器上的事件\n this.container.onclick = null\n this.container.onmousemove = null\n this.container.onmousedown = null\n this.container.onmouseup = null\n this.container.ondblclick = null\n\n // 移除 SVG 元素\n if (this.svg) {\n this.svg.remove()\n this.svg = null\n }\n\n // 移除工具条\n if (this._toolbar) {\n this._toolbar.remove()\n this._toolbar = null\n }\n\n // 移除颜色选择器\n if (this._colorPickerPopup) {\n this._colorPickerPopup.remove()\n this._colorPickerPopup = null\n }\n\n // 清空数据\n this.arrows = []\n this.drawing = false\n this.current = null\n this.selected = null\n this.mode = null\n this._transformMode = null\n this._transformHandle = null\n }\n}\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","_transformMode","_transformHandle","_transformStartPos","_transformStartPoints","_transformCenter","_transformStartAngle","_rotationOffset","_toolbar","_strokeWidth","_curveRate","_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","index","indexOf","splice","_hideToolbar","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","_kb","Keybinding","on","_handleEnter","_handleEsc","_handleDelete","onclick","contains","p","_mousePos","_handleClick","onmousemove","_handleMouseMove","onmousedown","handle","getAttribute","points","map","pt","center","dx","centerX","dy","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","notchX","notchY","scale","baseLen","baseWidth","notchLen","tipX","tipY","baseX","baseY","px","_createArrowGroup","g","_a","path","stroke","arrowHead","minY","scaleHandle","maxY","rotateY","rotateX","rotateLine","rotateHandle","querySelectorAll","forEach","_isDoubleClick","now","Date","dt","ctrlKey","push","classList","a","_hitArrow","add","_hideColorPicker","_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.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-linecap: round;\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: 20;\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._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 this._strokeWidth = 8\r\n this._curveRate = 0\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 const notchX = last.x\r\n const notchY = last.y\r\n\r\n // 根据粗细调整箭头大小\r\n const scale = strokeWidth / 8\r\n const baseLen = 40 * scale\r\n const baseWidth = 20 * scale\r\n const notchLen = 20 * scale\r\n\r\n const tipX = last.x + ux * notchLen\r\n const tipY = last.y + uy * notchLen\r\n const baseX = last.x - ux * (baseLen - notchLen)\r\n const baseY = last.y - uy * (baseLen - notchLen)\r\n\r\n const px = -uy\r\n const py = ux\r\n\r\n const leftX = baseX + px * baseWidth\r\n const leftY = baseY + py * baseWidth\r\n const rightX = baseX - px * baseWidth\r\n const rightY = baseY - py * baseWidth\r\n\r\n return `M ${tipX} ${tipY} L ${leftX} ${leftY} L ${notchX} ${notchY} 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","_transformMode","_transformHandle","_transformStartPos","_transformStartPoints","_transformCenter","_transformStartAngle","_rotationOffset","_toolbar","_strokeWidth","_curveRate","_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","notchX","notchY","scale","baseLen","baseWidth","notchLen","tipX","tipY","baseX","baseY","px","_createArrowGroup","index","g","_a","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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"}
|