image-annotation-drawer 1.3.2 → 1.3.3
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/CHANGELOG.md +23 -0
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.3.3] - 2026-10-14
|
|
9
|
+
|
|
10
|
+
### Fixed - 拖拽 / 缩放后标题跑到图片外
|
|
11
|
+
|
|
12
|
+
- **操作结束时补做标题边缘自适应**:标题按「标注锚点 + 存储的 `titlePosition`」绘制,且自 1.3.1 起
|
|
13
|
+
拖动/缩放过程中不再实时重算(避免标题乱跳);因此把标注拖到或缩到贴边后,
|
|
14
|
+
标题会留在图片之外,且不会自行恢复。
|
|
15
|
+
- 现在在 `finishMovingAnnotation()`(拖动与缩放**共同的结束钩子**)里,对当前标注补做一次
|
|
16
|
+
边缘自适应,把标题拉回图内:
|
|
17
|
+
- 拖动**过程**中仍不重算 —— 保持 1.3.1「拖动不乱跳」的手感,只在松手/结束时收敛
|
|
18
|
+
- 仅作用于**未显式设置位置**的标题(`autoAdjustTitlePosition` 内部已判断 `titlePositionExplicit`)
|
|
19
|
+
- 无标题、图片未加载时跳过
|
|
20
|
+
- **拖拽/缩放结束时主动重绘**:事件层只在 `mousemove` 时重绘,`mouseup` 只 emit `update` 事件,
|
|
21
|
+
于是上面写回的标题位置要等到下一次 render(例如取消选中)才可见 —— 表现为
|
|
22
|
+
「松手后标题没回到图内,点了别处才跳回来」。现在在结束钩子里补一次 `renderCallback()`,
|
|
23
|
+
标题位置在松手当下即生效。
|
|
24
|
+
|
|
25
|
+
### Tests
|
|
26
|
+
|
|
27
|
+
- `__tests__/title-edge.test.ts` 新增 5 条:拖到顶部后标题翻转为 `bottom`、
|
|
28
|
+
拖动中途不重算、显式设置过位置不被改写、缩放到贴顶后同样被拉回、
|
|
29
|
+
**结束时主动重绘**(且未发生移动/缩放时不多余重绘)
|
|
30
|
+
|
|
8
31
|
## [1.3.2] - 2026-10-14
|
|
9
32
|
|
|
10
33
|
### Fixed - 移动 / 缩放已有标注时的边界约束
|
package/dist/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(t,e){const n=e.width>=0?e.start.x:e.start.x+e.width,i=e.height>=0?e.start.y:e.start.y+e.height,s=Math.abs(e.width),o=Math.abs(e.height);return t.x>=n&&t.x<=n+s&&t.y>=i&&t.y<=i+o}function e(t,e){if(e.length<3)return!1;let n=!1;for(let i=0,s=e.length-1;i<e.length;s=i++){const o=e[i].point.x,a=e[i].point.y,r=e[s].point.x,h=e[s].point.y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n}function n(t){try{const e=new URL(t).pathname.toLowerCase();return e.endsWith(".png")?"png":e.endsWith(".jpg")?"jpg":e.endsWith(".jpeg")?"jpeg":e.endsWith(".webp")?"webp":e.endsWith(".gif")?"gif":e.endsWith(".bmp")?"bmp":e.endsWith(".svg")?"svg":"jpeg"}catch(t){return"jpeg"}}function i(t,e){const n=t.split(";base64,"),i=n[0].split(":")[1],s=window.atob(n[1]),o=s.length,a=new Uint8Array(o);for(let t=0;t<o;++t)a[t]=s.charCodeAt(t);const r=new Blob([a],{type:i});return new File([r],e,{type:i})}function s(t){return new Promise((e,n)=>{const i=t.split(";base64,");if(i.length<2)return void n(new Error("Invalid base64 string"));const s=i[0].split(":")[1],o=atob(i[1]),a=new ArrayBuffer(o.length),r=new Uint8Array(a);for(let t=0;t<o.length;t++)r[t]=o.charCodeAt(t);e(new Blob([a],{type:s}))})}function o(t,e){return t<2?e?.1:-.1:t<5?e?.05:-.05:e?.02:-.02}function a(t){return"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t))}function r(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():`id-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}class h{constructor(){this.width=0,this.height=0,this.originalWidth=0,this.originalHeight=0,this.scale=1,this.minScale=1,this.maxScale=10,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}setSize(t,e){this.width=t,this.height=e}setOriginalSize(t,e){this.originalWidth=t,this.originalHeight=e}calculateInitialView(){if(0===this.originalWidth||0===this.originalHeight)return;const t=this.width/this.originalWidth,e=this.height/this.originalHeight;this.scale=Math.min(t,e),this.initialScale=this.scale,this.minScale=this.initialScale,this.offset={x:(this.width-this.originalWidth*this.scale)/2,y:(this.height-this.originalHeight*this.scale)/2},this.initialOffset=Object.assign({},this.offset),this.calculateBoundaries(),this.isInitialScale=!0}calculateBoundaries(){const t=this.originalWidth*this.scale,e=this.originalHeight*this.scale;this.maxOffsetX=0,this.maxOffsetY=0,this.minOffsetX=this.width-t,this.minOffsetY=this.height-e,this.minOffsetX>this.maxOffsetX&&([this.minOffsetX,this.maxOffsetX]=[this.maxOffsetX,this.minOffsetX]),this.minOffsetY>this.maxOffsetY&&([this.minOffsetY,this.maxOffsetY]=[this.maxOffsetY,this.minOffsetY])}constrainViewport(){this.offset.x>this.maxOffsetX?this.offset.x=this.maxOffsetX:this.offset.x<this.minOffsetX&&(this.offset.x=this.minOffsetX),this.offset.y>this.maxOffsetY?this.offset.y=this.maxOffsetY:this.offset.y<this.minOffsetY&&(this.offset.y=this.minOffsetY)}toImageCoordinates(t,e){return{x:(t-this.offset.x)/this.scale,y:(e-this.offset.y)/this.scale}}toCanvasCoordinates(t,e){return{x:this.offset.x+t*this.scale,y:this.offset.y+e*this.scale}}updateScale(t,e,n){const i=this.scale,s=(e-this.offset.x)/i,o=(n-this.offset.y)/i;this.scale=Math.max(this.minScale,Math.min(t,this.maxScale));const a=s*this.scale+this.offset.x,r=o*this.scale+this.offset.y;this.offset.x+=e-a,this.offset.y+=n-r,this.calculateBoundaries(),this.constrainViewport(),this.isInitialScale=this.scale===this.initialScale}resetToInitial(){this.scale=this.initialScale,this.offset=Object.assign({},this.initialOffset),this.calculateBoundaries(),this.isInitialScale=!0}updateOffset(t,e){this.offset.x+=t,this.offset.y+=e,this.constrainViewport()}reset(){this.scale=1,this.minScale=1,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}}const l={minX:Number.NEGATIVE_INFINITY,minY:Number.NEGATIVE_INFINITY,maxX:Number.POSITIVE_INFINITY,maxY:Number.POSITIVE_INFINITY};function d(t,e,n){return Math.min(Math.max(t,e),n)}function c(t){var e,n,i,s;const{anchor:o,boxWidth:a,boxHeight:r,position:h}=t,c=null!==(e=t.bounds)&&void 0!==e?e:l,g=null!==(n=t.gap)&&void 0!==n?n:4,x=null!==(i=h.offsetX)&&void 0!==i?i:0,u=null!==(s=h.offsetY)&&void 0!==s?s:0,f=h.align||"center";let p;switch(f){case"left":p=o.x+x;break;case"right":p=o.x+o.width-a+x;break;default:p=o.x+o.width/2-a/2+x}const y=d(p,c.minX,Math.max(c.minX,c.maxX-a)),v=x+(y-p),M=h.vertical||"top";let w,m=M;return"inside-top"===M?w=o.y+g+u:"bottom"===M?(w=o.y+o.height+g+u,w+r>c.maxY&&(m="top",w=o.y-r-g+u)):(w=o.y-r-g+u,w<c.minY&&(m="bottom",w=o.y+o.height+g+u)),w=d(w,c.minY,Math.max(c.minY,c.maxY-r)),{x:y,y:w,vertical:m,align:f,offsetX:v}}function g(t){const{x:e,y:n}=c(t);return{x:e,y:n}}function x(t,e){if("polygon"===t.type){const n=t.data;if(0===n.length)return null;let i=1/0,s=1/0,o=-1/0,a=-1/0;return n.forEach(t=>{const n=e?e.offset.x+t.point.x*e.scale:t.point.x,r=e?e.offset.y+t.point.y*e.scale:t.point.y;n<i&&(i=n),r<s&&(s=r),n>o&&(o=n),r>a&&(a=r)}),{x:i,y:s,width:o-i,height:a-s}}const n=t.data[0];return e?{x:e.offset.x+n.start.x*e.scale,y:e.offset.y+n.start.y*e.scale,width:n.width*e.scale,height:n.height*e.scale}:{x:n.start.x,y:n.start.y,width:n.width,height:n.height}}function u(t,e,n){if(!n)return e;const{originalWidth:i,originalHeight:s}=t;return i&&s?{x:Math.max(0,Math.min(e.x,i)),y:Math.max(0,Math.min(e.y,s))}:e}function f(t,e,n,i,s){t&&s.id&&t(n,{id:s.id,type:e,index:i,data:a(s)})}const p=new class{constructor(){this.type="rect"}startDrawing(t,e){t.isDrawing=!0,t.drawStartPoint=e,t.operate={type:"rect",data:[{start:Object.assign({},e),width:0,height:0}],status:"pending"}}updateDrawing(t,e){if(!t.isDrawing||"rect"!==t.operate.type)return;const n=t.operate.data[0];n.width=e.x-t.drawStartPoint.x,n.height=e.y-t.drawStartPoint.y}addPoint(t,e){return!1}finishDrawing(t){if(!t.isDrawing||"rect"!==t.operate.type)return!1;const e=t.operate.data[0];return Math.abs(e.width)>5&&Math.abs(e.height)>5&&t.pushRecord(Object.assign({},t.operate)),t.operate.data=[],t.isDrawing=!1,!0}cancelDrawing(t){t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data=[],t.isDrawing=!1,!0)}hitTest(e,n){return t(n,e.data[0])}getHandles(t,e,n){const i=t.data[0],s=e.offset.x+i.start.x*e.scale,o=e.offset.y+i.start.y*e.scale,a=i.width*e.scale,r=i.height*e.scale;return[{x:s,y:o,index:0},{x:s+a,y:o,index:1},{x:s,y:o+r,index:2},{x:s+a,y:o+r,index:3}]}move(t,e,n){const i=t.data[0];i.start.x+=e,i.start.y+=n}snapshotForResize(t){const e=t.data[0];return{start:Object.assign({},e.start),width:e.width,height:e.height}}resize(t,e,n,i){const s=t.data[0],o=i,a=o.start.x,r=o.start.x+o.width,h=o.start.y,l=o.start.y+o.height;let d,c;switch(e){case 0:d=r,c=l;break;case 1:d=a,c=l;break;case 2:d=r,c=h;break;case 3:d=a,c=h;break;default:return}const g=Math.min(n.x,d),x=Math.max(n.x,d),u=Math.min(n.y,c),f=Math.max(n.y,c);s.start.x=g,s.start.y=u,s.width=x-g,s.height=f-u;const p=n.x<d,y=n.y<c;let v;return 0===e?p||y?!p&&y?v=1:p&&!y&&(v=2):v=3:1===e?p&&!y?v=2:p&&y?v=0:p||y||(v=3):2===e?!p&&y?v=1:p&&y?v=0:p||y||(v=3):3===e&&(p&&y?v=0:!p&&y?v=1:p&&!y&&(v=2)),o.start.x=s.start.x,o.start.y=s.start.y,o.width=s.width,o.height=s.height,v}getBounds(t){const e=t.data[0];return{x:e.start.x,y:e.start.y,width:e.width,height:e.height}}};const y=new class{constructor(){this.type="polygon"}startDrawing(t,e){t.isDrawing=!0,t.operate={type:"polygon",data:[{point:e}],status:"pending"},t.tempPolygonPoint=e}updateDrawing(t,e){t.tempPolygonPoint=e}addPoint(t,e){if(!t.isDrawing||"polygon"!==t.operate.type)return!1;const n=t.operate.data.length>0?t.operate.data[t.operate.data.length-1]:null;return!(n&&Math.abs(n.point.x-e.x)<=5&&Math.abs(n.point.y-e.y)<=5)&&(t.operate.data.push({point:e}),!0)}finishDrawing(t){return!(!t.isDrawing||"polygon"!==t.operate.type)&&(t.operate.data.length>=3&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate={type:"polygon",data:[],status:"pending"},t.isDrawing=!1,t.tempPolygonPoint=null,!0)}cancelDrawing(t){t.isDrawing&&"polygon"===t.operate.type&&t.operate.data.length>=2&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data.pop(),0===t.operate.data.length&&(t.isDrawing=!1),!0)}hitTest(t,n){return e(n,t.data)}getHandles(t,e,n){const i=t.data,s=[];for(let t=0;t<i.length;t++){const n=i[t];s.push({x:e.offset.x+n.point.x*e.scale,y:e.offset.y+n.point.y*e.scale,index:t})}return s}move(t,e,n){t.data.forEach(t=>{t.point.x+=e,t.point.y+=n})}snapshotForResize(t){return t.data.map(t=>({point:Object.assign({},t.point)}))}resize(t,e,n,i){const s=t.data;e>=0&&e<s.length&&(s[e].point.x=n.x,s[e].point.y=n.y)}getBounds(t){const e=t.data;if(0===e.length)return{x:0,y:0,width:0,height:0};let n=1/0,i=1/0,s=-1/0,o=-1/0;return e.forEach(t=>{t.point.x<n&&(n=t.point.x),t.point.y<i&&(i=t.point.y),t.point.x>s&&(s=t.point.x),t.point.y>o&&(o=t.point.y)}),{x:n,y:i,width:s-n,height:o-i}}};const v=new class{constructor(){this.strategies=new Map}register(t){this.strategies.set(t.type,t)}get(t){const e=this.strategies.get(t);if(!e)throw new Error(`No strategy registered for shape type: ${t}`);return e}selectShapeExclusive(t,e,n){return"shape"===n.kind?(e.deselectTextAnnotation(),t.selectAnnotation(n.ref,{lock:n.locked})):(t.deselectAnnotation(),e.selectTextAnnotation(n.index))}deselectAll(t,e){t.deselectAnnotation(),e.deselectTextAnnotation()}withdrawAll(t,e){return t.withdraw()||e.withdraw()}};v.register(p),v.register(y);class M{constructor(t,e,n,i){this.viewport=t,this.container=e,this.renderCallback=n,this.changeCallback=i,this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.drawStartPoint={x:0,y:0},this.tempPolygonPoint=null,this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.annotationMoveStart={x:0,y:0},this.originalRect=null,this.originalPolygon=null,this.deleteHistory=[],this.editingTitleIndex=null,this.titleInput=null,this.strokeStyle="red",this.lineWidth=5,this.lineStyle="solid",this.vertexStyle={size:8,fillColor:"red",strokeColor:"white",strokeWidth:2,shape:"circle"},this.selectionStyle={strokeColor:"#00D9FF",fillColor:"rgba(0,217,255,0.15)",handleSize:12,handleColor:"#00D9FF"},this.colorConfig={rect:"red",polygon:"red",default:"red"},this.titleStyle={font:"12px Arial",color:"#FFFFFF",backgroundColor:"rgba(0, 0, 0, 0.7)",paddingX:6,paddingY:3,borderRadius:4,placeholder:"输入标题..."},this.titlePosition={vertical:"top",align:"center",offsetX:0,offsetY:0},this.enableTitle=!1,this.clampEnabled=!0,this.applyColorConfig()}strategyOf(t){return v.get(t)}clamp(t){return u(this.viewport,t,this.clampEnabled)}clampToImageBounds(t){return u(this.viewport,t,this.clampEnabled)}clampRecordToImageBounds(t){if(!this.clampEnabled)return;const{originalWidth:e,originalHeight:n}=this.viewport;if(!e||!n)return;if("rect"===t.type){const i=t.data[0];if(!i)return;const s=Math.min(i.start.x,i.start.x+i.width),o=Math.max(i.start.x,i.start.x+i.width),a=Math.min(i.start.y,i.start.y+i.height),r=Math.max(i.start.y,i.start.y+i.height);if(s>=0&&a>=0&&o<=e&&r<=n)return;const h=Math.min(o-s,e),l=Math.min(r-a,n);return i.start.x=Math.max(0,Math.min(s,e-h)),i.start.y=Math.max(0,Math.min(a,n-l)),i.width=h,void(i.height=l)}const i=t.data;if(!i||0===i.length)return;let s=1/0,o=1/0,a=-1/0,r=-1/0;for(const t of i)s=Math.min(s,t.point.x),a=Math.max(a,t.point.x),o=Math.min(o,t.point.y),r=Math.max(r,t.point.y);let h=0,l=0;if(a-s>e||s<0?h=-s:a>e&&(h=e-a),r-o>n||o<0?l=-o:r>n&&(l=n-r),0!==h||0!==l)for(const t of i)t.point.x+=h,t.point.y+=l}pushRecord(t){const e=Object.assign(Object.assign({},t),{id:r(),style:this.getCurrentStyle()});this.recordList.push(e),this.deleteHistory=[],this.notifyChange("create",this.recordList.length-1,e)}initTitleSupport(){this.container&&this.enableTitle&&this.createTitleInput()}setColorConfig(t){this.colorConfig="string"==typeof t?{rect:t,polygon:t,default:t}:Object.assign(Object.assign({},this.colorConfig),t),this.applyColorConfig()}getColorConfig(){return Object.assign({},this.colorConfig)}applyColorConfig(){this.strokeStyle=this.colorConfig.default||"red"}getColorForType(t){return this.colorConfig[t]||this.colorConfig.default||"red"}getCurrentStyle(){return{strokeColor:this.strokeStyle,lineWidth:this.lineWidth,lineStyle:this.lineStyle,vertexStyle:Object.assign({},this.vertexStyle)}}notifyChange(t,e,n){f(this.changeCallback,n.type,t,e,n)}notifyUpdate(t){const e=this.recordList[t];e&&this.notifyChange("update",t,e)}resolveIndex(t){return"number"==typeof t?t:this.recordList.findIndex(e=>e.id===t)}getAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return a(this.recordList[e])}updateAnnotationStyle(t){const e=this.resolveIndex(t);return!(e<0||e>=this.recordList.length)&&(this.recordList[e].style=this.getCurrentStyle(),this.notifyUpdate(e),!0)}setLineStyle(t){this.lineStyle=t}setVertexStyle(t){this.vertexStyle=Object.assign(Object.assign({},this.vertexStyle),t),t.fillColor&&(this.strokeStyle=t.fillColor)}getLineStyle(){return this.lineStyle}getVertexStyle(){return Object.assign({},this.vertexStyle)}getAnnotationStyle(t){return t.style||this.getCurrentStyle()}withdraw(){if(this.operate.data.length>0){const t="polygon"===this.operate.type?"polygon":"rect";return this.strategyOf(t).withdrawInProgress(this),!0}if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.recordList.splice(e,0,t),!0}return this.recordList.length>0&&(this.recordList.pop(),!0)}selectAnnotation(t,e){var n;const i=this.resolveIndex(t);if(i<0||i>=this.recordList.length)return this.deselectAnnotation(),!1;const s=this.recordList[i],o=void 0!==(null==e?void 0:e.lock)?!!e.lock:(null===(n=this.selectedAnnotation)||void 0===n?void 0:n.index)===i&&!0===this.selectedAnnotation.locked;return this.selectedAnnotation={index:i,type:s.type,locked:o},!0}deselectAnnotation(){this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null}deleteSelectedAnnotation(){if(!this.selectedAnnotation)return!1;const t=this.selectedAnnotation.index,e=this.recordList[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.recordList.splice(t,1),this.deselectAnnotation(),this.notifyChange("delete",t,e),!0}startMovingAnnotation(t){return!(!this.selectedAnnotation||!0===this.selectedAnnotation.locked)&&(this.isMovingAnnotation=!0,this.annotationMoveStart={x:t.clientX,y:t.clientY},!0)}updateMoveStart(t){this.annotationMoveStart=t}finishMovingAnnotation(){const t=this.isMovingAnnotation||this.isResizing;this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null,t&&this.selectedAnnotation&&this.notifyUpdate(this.selectedAnnotation.index)}clear(){this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.tempPolygonPoint=null,this.deselectAnnotation(),this.deleteHistory=[]}getAnnotations(){return this.recordList.map(t=>a(t))}getSelectedAnnotation(){if(!this.selectedAnnotation)return null;const t=this.recordList[this.selectedAnnotation.index];return t?{index:this.selectedAnnotation.index,type:this.selectedAnnotation.type,data:a(t)}:null}setTitleStyle(t){this.titleStyle=Object.assign(Object.assign({},this.titleStyle),t)}getTitleStyle(){return Object.assign({},this.titleStyle)}setTitlePosition(t){this.titlePosition=Object.assign(Object.assign({},this.titlePosition),t)}getTitlePosition(){return Object.assign({},this.titlePosition)}getEffectiveTitleStyle(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titleStyle),e.titleStyle||{})}getEffectiveTitlePosition(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titlePosition),e.titlePosition||{})}captureTitleStyleSnapshot(t){t.style||(t.style=this.getCurrentStyle()),t.style.titleStyle=Object.assign({},this.titleStyle),t.style.titlePositionExplicit||(t.style.titlePosition=Object.assign({},this.titlePosition))}autoAdjustTitlePosition(t,e){var n,i,s;if(!e||(null===(n=t.style)||void 0===n?void 0:n.titlePositionExplicit))return;const{originalWidth:o,originalHeight:a,initialScale:r,scale:h}=this.viewport;if(o<=0||a<=0)return;const l=x(t);if(!l)return;const d=r>0?r:h>0?h:1,g={x:l.x*d,y:l.y*d,width:l.width*d,height:l.height*d},u=this.getEffectiveTitleStyle(t),f=u.font||"12px Arial",p=f.match(/(\d+)px/),y=(p?parseInt(p[1]):12)+2*(null!==(i=u.paddingY)&&void 0!==i?i:3),v=this.measureTitleWidth,M=v?{minX:0,minY:0,maxX:o*d,maxY:a*d}:{minX:Number.NEGATIVE_INFINITY,minY:0,maxX:Number.POSITIVE_INFINITY,maxY:a*d},w=v?v(e,f)+2*(null!==(s=u.paddingX)&&void 0!==s?s:6):0,m=Object.assign({},this.titlePosition),A=c({anchor:g,boxWidth:w,boxHeight:y,position:m,bounds:M});t.style||(t.style=this.getCurrentStyle()),t.style.titlePosition=Object.assign(Object.assign({},m),{vertical:A.vertical,align:A.align,offsetX:A.offsetX})}adjustTitlePositions(){this.viewport.originalWidth<=0||this.viewport.originalHeight<=0||this.recordList.forEach(t=>{var e;t.title&&!(null===(e=t.style)||void 0===e?void 0:e.titlePositionExplicit)&&this.autoAdjustTitlePosition(t,t.title)})}setAnnotationTitleStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titleStyle=Object.assign(Object.assign({},i.style.titleStyle||this.titleStyle),e),this.notifyUpdate(n),!0}setAnnotationTitlePosition(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titlePosition=Object.assign(Object.assign({},i.style.titlePosition||this.titlePosition),e),i.style.titlePositionExplicit=!0,this.notifyUpdate(n),!0}createTitleInput(){this.container&&(this.titleInput=document.createElement("input"),this.titleInput.type="text",this.titleInput.style.position="absolute",this.titleInput.style.zIndex="99998",this.titleInput.style.display="none",this.titleInput.style.outline="none",this.titleInput.style.border="1px solid #00D9FF",this.titleInput.style.borderRadius="4px",this.titleInput.style.padding="4px 8px",this.titleInput.style.fontSize="13px",this.titleInput.style.fontFamily="Arial, sans-serif",this.titleInput.style.backgroundColor="#ffffff",this.titleInput.style.color="#333",this.titleInput.style.boxShadow="0 2px 8px rgba(0,0,0,0.3)",this.titleInput.style.minWidth="80px",this.titleInput.style.maxWidth="200px",this.titleInput.placeholder=this.titleStyle.placeholder||"输入标题...",this.titleInput.addEventListener("blur",()=>{this.finishTitleEditing()}),this.titleInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?this.finishTitleEditing():"Escape"===t.key&&(t.preventDefault(),this.cancelTitleEditing())}),this.container.appendChild(this.titleInput))}setTitle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.title=e||void 0,e&&(this.captureTitleStyleSnapshot(i),this.autoAdjustTitlePosition(i,e)),this.notifyUpdate(n),!0}getTitle(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return this.recordList[e].title}startTitleEditing(t){if(!this.enableTitle||!this.titleInput||t<0||t>=this.recordList.length)return!1;const e=this.recordList[t];let n,i;if(this.editingTitleIndex=t,this.deselectAnnotation(),"rect"===e.type){const t=e.data[0];n=this.viewport.offset.x+t.start.x*this.viewport.scale,i=this.viewport.offset.y+t.start.y*this.viewport.scale}else{const t=e.data[0];n=this.viewport.offset.x+t.point.x*this.viewport.scale,i=this.viewport.offset.y+t.point.y*this.viewport.scale}return this.titleInput.value=e.title||"",this.titleInput.placeholder=this.getEffectiveTitleStyle(e).placeholder||"输入标题...",this.titleInput.style.left=`${n}px`,this.titleInput.style.top=i-32+"px",this.titleInput.style.display="block",setTimeout(()=>{this.titleInput&&(this.titleInput.focus(),this.titleInput.select())},10),!0}finishTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex,e=this.titleInput.value.trim();if(t>=0&&t<this.recordList.length){const n=this.recordList[t];n.title=e||void 0,e&&(this.captureTitleStyleSnapshot(n),this.autoAdjustTitlePosition(n,e)),this.notifyUpdate(t),this.selectAnnotation(t)}return this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}cancelTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex;return t>=0&&t<this.recordList.length&&this.selectAnnotation(t),this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}resetTitleEditingState(){this.titleInput&&(this.titleInput.style.display="none"),this.editingTitleIndex=null}destroyTitleInput(){this.titleInput&&this.titleInput.parentNode&&(this.titleInput.parentNode.removeChild(this.titleInput),this.titleInput=null)}}class w extends M{startRectDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("rect").startDrawing(this,t)}updateRectDrawing(t){this.isDrawing&&"rect"===this.operate.type&&(t=this.clampToImageBounds(t),this.strategyOf("rect").updateDrawing(this,t))}finishRectDrawing(){return this.strategyOf("rect").finishDrawing(this)}startPolygonDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("polygon").startDrawing(this,t)}addPolygonPoint(t){return!(!this.isDrawing||"polygon"!==this.operate.type)&&(t=this.clampToImageBounds(t),this.strategyOf("polygon").addPoint(this,t))}updatePolygonTempPoint(t){this.strategyOf("polygon").updateDrawing(this,this.clampToImageBounds(t))}finishPolygonDrawing(){return this.strategyOf("polygon").finishDrawing(this)}cancelDrawing(){const t="polygon"===this.operate.type?"polygon":"rect";this.strategyOf(t).cancelDrawing(this)}moveSelectedAnnotation(t,e){if(!this.selectedAnnotation)return!1;const n=this.recordList[this.selectedAnnotation.index];return!!n&&(this.strategyOf(n.type).move(n,t,e),this.clampRecordToImageBounds(n),!0)}startResizing(t,e){if(!this.selectedAnnotation)return!1;this.activeHandle=t,this.isResizing=!0;const n=this.recordList[this.selectedAnnotation.index];return"rect"===n.type?this.originalRect=this.strategyOf("rect").snapshotForResize(n):"polygon"===n.type&&(this.originalPolygon=this.strategyOf("polygon").snapshotForResize(n)),!0}resizeRect(t){if(!this.selectedAnnotation||"rect"!==this.selectedAnnotation.type||!this.originalRect||!this.activeHandle)return!1;if(this.activeHandle.index<0||this.activeHandle.index>3)return!1;const e=this.recordList[this.selectedAnnotation.index],n=this.clampToImageBounds(t),i=this.strategyOf("rect").resize(e,this.activeHandle.index,n,this.originalRect);return"number"==typeof i&&(this.activeHandle.index=i),!0}resizePolygon(t){var e;if(!this.selectedAnnotation||"polygon"!==this.selectedAnnotation.type||!this.activeHandle)return!1;const n=this.recordList[this.selectedAnnotation.index],i=this.activeHandle.index,s=n.data;return!(i<0||i>=s.length)&&(this.strategyOf("polygon").resize(n,i,this.clampToImageBounds(t),null!==(e=this.originalPolygon)&&void 0!==e?e:[]),!0)}getAnnotationAtPoint(t){for(let e=this.recordList.length-1;e>=0;e--){const n=this.recordList[e],i=n.type;if(this.strategyOf(i).hitTest(n,t))return{index:e,type:i}}return null}getHandleAtPoint(t,e){if(!this.selectedAnnotation)return null;if(!0===this.selectedAnnotation.locked)return null;const n=this.recordList[this.selectedAnnotation.index],i=this.selectionStyle.handleSize,s=i/2,o=this.selectedAnnotation.type,a=this.strategyOf(o).getHandles(n,this.viewport,i);for(const n of a)if(t>=n.x-s&&t<=n.x+s&&e>=n.y-s&&e<=n.y+s)return"rect"===o?{type:"rect-corner",index:n.index}:{type:"polygon-vertex",index:n.index};return null}}class m{constructor(t,e,n,i,s){this.viewport=t,this.container=e,this.ctx=n,this.renderCallback=i,this.changeCallback=s,this.textAnnotations=[],this.editingTextIndex=null,this.currentEditingIndex=null,this.movingTextIndex=null,this.isTextMoving=!1,this.textMoveStart={x:0,y:0},this.textBeforeEditing="",this.selectedTextIndex=null,this.clampEnabled=!0,this.textInput=null,this.deleteHistory=[],this.defaultInputStyle={border:"2px solid #00D9FF",borderRadius:"6px",padding:"6px 10px",fontSize:"16px",fontFamily:"Arial, sans-serif",backgroundColor:"#ffffff",color:"#333",boxShadow:"0 4px 12px rgba(0,0,0,0.3)",minWidth:"60px",maxWidth:"200px"},this.textStyle={font:"16px Arial",color:"#FFD700",padding:6,backgroundColor:"rgba(0,0,0,0.6)",borderRadius:4,selectedBorderColor:"#00D9FF",selectedBackgroundColor:"rgba(0,217,255,0.15)",inputStyle:Object.assign({},this.defaultInputStyle)},this.createTextInput()}createTextInput(){this.textInput=document.createElement("input"),this.textInput.type="text",this.textInput.style.position="absolute",this.textInput.style.zIndex="99999",this.textInput.style.display="none",this.textInput.style.outline="none",this.textInput.style.width="fit-content",this.textInput.placeholder="输入文字...",this.applyInputStyle(),this.textInput.addEventListener("blur",()=>{this.finishEditing(),this.renderCallback&&this.renderCallback()}),this.textInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?(this.finishEditing(),this.renderCallback&&this.renderCallback()):"Escape"===t.key?(t.preventDefault(),this.cancelEditing()):"Delete"===t.key&&""===this.textInput.value&&(t.preventDefault(),this.deleteEditingAnnotation())}),this.textInput.addEventListener("input",()=>{this.adjustInputWidth()}),this.container.appendChild(this.textInput)}applyInputStyle(){if(!this.textInput)return;const t=Object.assign(Object.assign({},this.defaultInputStyle),this.textStyle.inputStyle);this.textInput.style.border=t.border,this.textInput.style.borderRadius=t.borderRadius,this.textInput.style.padding=t.padding,this.textInput.style.fontSize=t.fontSize,this.textInput.style.fontFamily=t.fontFamily,this.textInput.style.backgroundColor=t.backgroundColor,this.textInput.style.color=t.color,this.textInput.style.boxShadow=t.boxShadow,this.textInput.style.minWidth=t.minWidth,this.textInput.style.maxWidth=t.maxWidth}setTextStyle(t){this.textStyle=Object.assign(Object.assign({},this.textStyle),t),this.applyInputStyle()}setInputStyle(t){this.textStyle.inputStyle=Object.assign(Object.assign({},this.textStyle.inputStyle),t),this.applyInputStyle()}setSelectionStyle(t){void 0!==t.selectedBorderColor&&(this.textStyle.selectedBorderColor=t.selectedBorderColor),void 0!==t.selectedBackgroundColor&&(this.textStyle.selectedBackgroundColor=t.selectedBackgroundColor)}getCurrentStyle(){return{font:this.textStyle.font,color:this.textStyle.color,backgroundColor:this.textStyle.backgroundColor}}notifyChange(t,e,n){f(this.changeCallback,"text",t,e,n)}resolveIndex(t){return"number"==typeof t?t:this.textAnnotations.findIndex(e=>e.id===t)}getTextAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.textAnnotations.length))return a(this.textAnnotations[e])}updateTextAnnotationStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];return i.style=Object.assign(Object.assign({},i.style||this.getCurrentStyle()),e),this.notifyChange("update",n,this.textAnnotations[n]),!0}clampToImageBounds(t){return u(this.viewport,t,this.clampEnabled)}addTextAnnotation(t,e,n=""){var i;const s=this.clampToImageBounds({x:t,y:e});t=s.x,e=s.y,this.ctx.font=this.textStyle.font;const o=n||"输入文字...",a=this.ctx.measureText(o);let h;if(a.actualBoundingBoxAscent&&a.actualBoundingBoxDescent)h=a.actualBoundingBoxAscent+a.actualBoundingBoxDescent;else{h=1.2*parseInt((null===(i=this.textStyle.font.match(/\d+/))||void 0===i?void 0:i[0])||"16")}const l={id:r(),position:{x:t,y:e},text:n,style:this.getCurrentStyle(),width:Math.max(a.width,60),height:h};this.textAnnotations.push(l);const d=this.textAnnotations.length-1;return this.notifyChange("create",d,l),this.deleteHistory=[],this.startEditing(d),d}updateTextAnnotation(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];i.text=e,this.ctx.font=this.textStyle.font;const s=this.ctx.measureText(e);return i.width=s.width,i.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",n,this.textAnnotations[n]),!0}moveTextAnnotation(t,e,n){const i=this.resolveIndex(t);return!(i<0||i>=this.textAnnotations.length)&&(this.textAnnotations[i].position={x:e,y:n},this.notifyChange("update",i,this.textAnnotations[i]),!0)}removeTextAnnotation(t){const e=this.resolveIndex(t);if(e<0||e>=this.textAnnotations.length)return!1;const n=this.textAnnotations[e];return this.deleteHistory.push({annotation:Object.assign({},n),index:e}),this.textAnnotations.splice(e,1),this.notifyChange("delete",e,n),this.editingTextIndex===e?this.resetEditingState():null!==this.editingTextIndex&&this.editingTextIndex>e&&this.editingTextIndex--,this.movingTextIndex===e?this.endTextMoving():null!==this.movingTextIndex&&this.movingTextIndex>e&&this.movingTextIndex--,!0}clearTextAnnotations(){this.textAnnotations=[],this.selectedTextIndex=null,this.cancelEditing(),this.deleteHistory=[]}startEditing(t){if(!this.textInput||t<0||t>=this.textAnnotations.length)return!1;const e=this.textAnnotations[t];this.editingTextIndex=t,this.currentEditingIndex=t,this.textBeforeEditing=e.text;const n=this.viewport.offset.x+e.position.x*this.viewport.scale,i=this.viewport.offset.y+e.position.y*this.viewport.scale;return this.textInput.value=e.text,this.textInput.style.left=`${n}px`,this.textInput.style.top=`${i}px`,this.textInput.style.display="block",this.adjustInputWidth(),setTimeout(()=>{this.textInput&&(this.textInput.focus(),this.textInput.select())},10),!0}finishEditing(){if(!this.textInput)return!1;const t=this.currentEditingIndex,e=this.textInput.value.trim();if(null===t||t<0||t>=this.textAnnotations.length)return this.resetEditingState(),!1;if(""===e){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}else{const n=this.textAnnotations[t];n.text=e,this.ctx.font=this.textStyle.font;const i=this.ctx.measureText(n.text);n.width=i.width,n.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",t,n)}return this.resetEditingState(),!0}cancelEditing(){if(!this.textInput||null===this.editingTextIndex)return!1;this.textInput.value=this.textBeforeEditing;const t=this.editingTextIndex;if(t>=0&&t<this.textAnnotations.length){if(""===this.textAnnotations[t].text&&""===this.textBeforeEditing){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}}return this.resetEditingState(),!0}deleteEditingAnnotation(){if(null===this.editingTextIndex)return!1;const t=this.editingTextIndex;if(this.textInput&&(this.textInput.style.display="none"),t>=0&&t<this.textAnnotations.length){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}return this.resetEditingState(),!0}resetEditingState(){this.textInput&&(this.textInput.style.display="none"),this.editingTextIndex=null,this.currentEditingIndex=null,this.textBeforeEditing=""}adjustInputWidth(){if(!this.textInput||null===this.editingTextIndex)return;this.ctx.font=this.textStyle.font;const t=this.textInput.value||this.textInput.placeholder||"",e=this.ctx.measureText(t).width,n=Math.min(Math.max(e+24,60),200);this.textInput.style.width=`${n}px`}startMoving(t,e){return!(e<0||e>=this.textAnnotations.length)&&(this.movingTextIndex=e,this.isTextMoving=!0,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}moveAnnotation(t){if(!this.isTextMoving||null===this.movingTextIndex)return!1;const e=t.clientX-this.textMoveStart.x,n=t.clientY-this.textMoveStart.y,i=this.textAnnotations[this.movingTextIndex];return!!i&&(i.position.x+=e/this.viewport.scale,i.position.y+=n/this.viewport.scale,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}finishMoving(){if(this.isTextMoving=!1,null!==this.movingTextIndex){const t=this.textAnnotations[this.movingTextIndex];t&&this.notifyChange("update",this.movingTextIndex,t)}this.movingTextIndex=null}endTextMoving(){this.isTextMoving=!1,this.movingTextIndex=null}isEditingVisible(){var t;return"block"===(null===(t=this.textInput)||void 0===t?void 0:t.style.display)}checkTextClick(t,e){for(let n=this.textAnnotations.length-1;n>=0;n--){const i=this.textAnnotations[n],s=this.viewport.offset.x+i.position.x*this.viewport.scale,o=this.viewport.offset.y+i.position.y*this.viewport.scale,a=Math.max(i.width,60)+2*this.textStyle.padding,r=i.height+2*this.textStyle.padding;if(t>=s&&t<=s+a&&e>=o&&e<=o+r)return n}return null}checkTextClickForMove(t){const e=this.checkTextClick(t.offsetX,t.offsetY);return null!==e?(this.startMoving(t,e),{index:e,handled:!0}):{index:-1,handled:!1}}getTextAnnotations(){return this.textAnnotations.map(t=>a(t))}withdraw(){if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.textAnnotations.splice(e,0,t),!0}return this.textAnnotations.length>0&&(this.textAnnotations.pop(),!0)}selectTextAnnotation(t){return t<0||t>=this.textAnnotations.length?(this.deselectTextAnnotation(),!1):(this.selectedTextIndex=t,null!==this.editingTextIndex&&this.finishEditing(),!0)}deselectTextAnnotation(){this.selectedTextIndex=null}deleteSelectedTextAnnotation(){if(null===this.selectedTextIndex)return!1;const t=this.selectedTextIndex,e=this.textAnnotations[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.textAnnotations.splice(t,1),this.selectedTextIndex=null,this.notifyChange("delete",t,e),null!==this.editingTextIndex&&this.editingTextIndex>t&&this.editingTextIndex--,null!==this.movingTextIndex&&this.movingTextIndex>t&&this.movingTextIndex--,!0}getSelectedTextAnnotation(){if(null===this.selectedTextIndex)return null;const t=this.textAnnotations[this.selectedTextIndex];return t?{index:this.selectedTextIndex,data:a(t)}:null}destroy(){this.textInput&&this.textInput.parentNode&&this.textInput.parentNode.removeChild(this.textInput)}}function A(t,e){switch(e){case"dashed":t.setLineDash([10,5]);break;case"dotted":t.setLineDash([2,4]);break;default:t.setLineDash([])}}class T{draw(t,e,n,i){const s=n.data[0];t.strokeRect(e.offset.x+s.start.x*e.scale,e.offset.y+s.start.y*e.scale,s.width*e.scale,s.height*e.scale)}drawInProgress(t,e,n){const i=n.operate.data[0];t.strokeRect(e.offset.x+i.start.x*e.scale,e.offset.y+i.start.y*e.scale,i.width*e.scale,i.height*e.scale)}drawSelection(t,e,n,i,s){const o=n.data[0],a=e.offset.x+o.start.x*e.scale,r=e.offset.y+o.start.y*e.scale,h=o.width*e.scale,l=o.height*e.scale;if(t.fillStyle=i.fillColor,t.fillRect(a,r,h,l),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.strokeRect(a,r,h,l),s)return;const d=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),t.fillRect(a-d/2,r-d/2,d,d),t.fillRect(a+h-d/2,r-d/2,d,d),t.fillRect(a-d/2,r+l-d/2,d,d),t.fillRect(a+h-d/2,r+l-d/2,d,d)}drawForExport(t,e,n){const i=e.data[0];t.strokeRect(i.start.x,i.start.y,i.width,i.height)}getTitleAnchor(t,e){return x(t,e)}}class I{constructor(t){this.store=t}draw(t,e,n,i){const s=i.vertexStyle||this.store.getVertexStyle();this.drawPolygon(t,e,n.data,"fullfilled"===n.status,s)}drawInProgress(t,e,n){const i=n.operate.data,s=n.tempPolygonPoint;if(t.beginPath(),i.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),s){const n=Math.round(e.offset.x+s.x*e.scale),i=Math.round(e.offset.y+s.y*e.scale);t.lineTo(n,i)}if(t.stroke(),this.drawPolygonVertices(t,e,i,n.getVertexStyle()),s){const i=n.getVertexStyle(),o=Math.round(e.offset.x+s.x*e.scale),a=Math.round(e.offset.y+s.y*e.scale),r=i.size/2;switch(t.fillStyle=i.fillColor,t.strokeStyle=i.strokeColor,t.lineWidth=i.strokeWidth,t.beginPath(),i.shape){case"square":t.rect(o-r,a-r,2*r,2*r);break;case"diamond":t.moveTo(o,a-r),t.lineTo(o+r,a),t.lineTo(o,a+r),t.lineTo(o-r,a),t.closePath();break;default:t.arc(o,a,r,0,2*Math.PI)}t.fill(),i.strokeWidth>0&&t.stroke()}}drawSelection(t,e,n,i,s){const o=n.data;if(t.beginPath(),o.forEach((n,i)=>{const s=e.offset.x+n.point.x*e.scale,o=e.offset.y+n.point.y*e.scale;0===i?t.moveTo(s,o):t.lineTo(s,o)}),t.closePath(),t.fillStyle=i.fillColor,t.fill(),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.stroke(),s)return;const a=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),o.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),s=Math.round(e.offset.y+n.point.y*e.scale);t.fillRect(i-a/2,s-a/2,a,a)})}drawForExport(t,e,n){if("fullfilled"!==e.status)return;const i=e.data;t.beginPath(),i.forEach((e,n)=>{0===n?t.moveTo(e.point.x,e.point.y):t.lineTo(e.point.x,e.point.y)});const s=e.data[0];t.lineTo(s.point.x,s.point.y),t.stroke(),i.forEach(e=>{t.beginPath(),t.arc(e.point.x,e.point.y,4,0,2*Math.PI),t.fillStyle=n.strokeColor,t.fill()})}getTitleAnchor(t,e){return x(t,e)}drawPolygon(t,e,n,i,s){if(0!==n.length){if(t.beginPath(),n.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),i&&n.length>1){const i=n[0];t.lineTo(e.offset.x+i.point.x*e.scale,e.offset.y+i.point.y*e.scale)}t.stroke(),this.drawPolygonVertices(t,e,n,s)}}drawPolygonVertices(t,e,n,i){const s=i||this.store.getVertexStyle(),o=s.size/2;n.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),a=Math.round(e.offset.y+n.point.y*e.scale);switch(t.fillStyle=s.fillColor,t.strokeStyle=s.strokeColor,t.lineWidth=s.strokeWidth,t.beginPath(),s.shape){case"square":t.rect(i-o,a-o,2*o,2*o);break;case"diamond":t.moveTo(i,a-o),t.lineTo(i+o,a),t.lineTo(i,a+o),t.lineTo(i-o,a),t.closePath();break;default:t.arc(i,a,o,0,2*Math.PI)}t.fill(),s.strokeWidth>0&&t.stroke()})}}class S{constructor(t,e,n,i){this.ctx=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.shapeRenderers={rect:new T,polygon:new I(n)}}render(t){this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.drawBackgroundImage(t),this.drawAnnotations(),function(t,e,n){const i=n.textStyle;n.textAnnotations.forEach((s,o)=>{if(n.editingTextIndex===o&&n.isEditingVisible())return;if(!s.text)return;const a=s.style||{font:i.font,color:i.color,backgroundColor:i.backgroundColor},r=e.offset.x+s.position.x*e.scale,h=e.offset.y+s.position.y*e.scale,l=n.selectedTextIndex===o;t.font=a.font;const d=t.measureText(s.text),c=d.actualBoundingBoxAscent||.8*s.height,g=c+(d.actualBoundingBoxDescent||.2*s.height),x=i.borderRadius,u=r,f=h,p=s.width+2*i.padding,y=g+2*i.padding;t.fillStyle=a.backgroundColor,t.beginPath(),t.roundRect(u,f,p,y,x),t.fill(),l&&(t.strokeStyle=i.selectedBorderColor,t.lineWidth=2,t.setLineDash([5,5]),t.beginPath(),t.roundRect(u,f,p,y,x),t.stroke(),t.setLineDash([]));const v=r+i.padding,M=h+i.padding+c;t.fillStyle=a.color,t.fillText(s.text,v,M)})}(this.ctx,this.viewport,this.textManager)}drawBackgroundImage(t){this.ctx.drawImage(t,this.viewport.offset.x,this.viewport.offset.y,this.viewport.originalWidth*this.viewport.scale,this.viewport.originalHeight*this.viewport.scale)}drawAnnotations(){this.annotationManager.recordList.forEach(t=>{const e=this.annotationManager.getAnnotationStyle(t);this.ctx.strokeStyle=e.strokeColor,this.ctx.lineWidth=e.lineWidth,A(this.ctx,e.lineStyle||"solid"),this.ctx.fillStyle=this.ctx.strokeStyle,"rect"===t.type?this.shapeRenderers.rect.draw(this.ctx,this.viewport,t,e):"polygon"===t.type&&this.shapeRenderers.polygon.draw(this.ctx,this.viewport,t,e),this.annotationManager.enableTitle&&t.title&&this.drawAnnotationTitle(t)}),this.annotationManager.operate.data.length>0&&(this.ctx.strokeStyle=this.annotationManager.strokeStyle,this.ctx.lineWidth=this.annotationManager.lineWidth,this.ctx.fillStyle=this.ctx.strokeStyle,A(this.ctx,this.annotationManager.lineStyle),"rect"===this.annotationManager.operate.type?this.shapeRenderers.rect.drawInProgress(this.ctx,this.viewport,this.annotationManager):"polygon"===this.annotationManager.operate.type&&this.shapeRenderers.polygon.drawInProgress(this.ctx,this.viewport,this.annotationManager)),this.ctx.setLineDash([]),this.drawSelectionHighlight()}drawSelectionHighlight(){const t=this.annotationManager.selectedAnnotation;if(!t)return;const e=this.annotationManager.recordList[t.index];if(!e)return;const n=this.annotationManager.selectionStyle,i=!0===t.locked;this.ctx.save(),"rect"===e.type?this.shapeRenderers.rect.drawSelection(this.ctx,this.viewport,e,n,i):"polygon"===e.type&&this.shapeRenderers.polygon.drawSelection(this.ctx,this.viewport,e,n,i),this.ctx.restore()}drawAnnotationTitle(t){var e,n,i;if(!t.title)return;const s=this.annotationManager.getEffectiveTitleStyle(t),o=this.annotationManager.getEffectiveTitlePosition(t),a=s.font||"12px Arial",r=s.color||"#FFFFFF",h=s.backgroundColor||"rgba(0, 0, 0, 0.7)",l=null!==(e=s.paddingX)&&void 0!==e?e:6,d=null!==(n=s.paddingY)&&void 0!==n?n:3,c=null!==(i=s.borderRadius)&&void 0!==i?i:4;this.ctx.save(),this.ctx.font=a;const x=this.ctx.measureText(t.title).width,u=a.match(/(\d+)px/),f=u?parseInt(u[1]):12,p=("rect"===t.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(t,this.viewport);if(!p)return void this.ctx.restore();const y=x+2*l,v=f+2*d,{x:M,y:w}=g({anchor:p,boxWidth:y,boxHeight:v,position:o});this.ctx.fillStyle=h,this.ctx.setLineDash([]),this.ctx.beginPath(),this.ctx.roundRect(M,w,y,v,c),this.ctx.fill(),this.ctx.fillStyle=r,this.ctx.textAlign="left",this.ctx.textBaseline="top",this.ctx.fillText(t.title,M+l,w+d),this.ctx.restore()}drawForExport(t,e,n,i){t.drawImage(e,0,0,n,i),this.annotationManager.recordList.forEach(e=>{const n=this.annotationManager.getAnnotationStyle(e);t.strokeStyle=n.strokeColor,t.lineWidth=n.lineWidth,"rect"===e.type?this.shapeRenderers.rect.drawForExport(t,e,n):"polygon"===e.type&&this.shapeRenderers.polygon.drawForExport(t,e,n)}),this.textManager.textAnnotations.forEach(e=>{const n=this.textManager.textStyle,i=e.style||{font:n.font,color:n.color,backgroundColor:n.backgroundColor};t.font=i.font;const s=t.measureText(e.text),o=s.actualBoundingBoxAscent||.8*e.height,a=o+(s.actualBoundingBoxDescent||.2*e.height),r=e.position.x,h=e.position.y,l=e.width+2*n.padding,d=a+2*n.padding,c=n.borderRadius;t.fillStyle=i.backgroundColor,t.roundRect?(t.roundRect(r,h,l,d,c),t.fill()):t.fillRect(r,h,l,d),t.fillStyle=i.color,t.fillText(e.text,e.position.x+n.padding,e.position.y+n.padding+o)}),this.annotationManager.enableTitle&&this.annotationManager.recordList.forEach(e=>{var n,i,s;if(!e.title)return;const o=this.annotationManager.getEffectiveTitleStyle(e),a=this.annotationManager.getEffectiveTitlePosition(e),r=o.font||"12px Arial",h=o.color||"#FFFFFF",l=o.backgroundColor||"rgba(0, 0, 0, 0.7)",d=null!==(n=o.paddingX)&&void 0!==n?n:6,c=null!==(i=o.paddingY)&&void 0!==i?i:3,x=null!==(s=o.borderRadius)&&void 0!==s?s:4;t.font=r;const u=t.measureText(e.title).width,f=r.match(/(\d+)px/),p=f?parseInt(f[1]):12,y=("rect"===e.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(e);if(!y)return;const v=u+2*d,M=p+2*c,{x:w,y:m}=g({anchor:y,boxWidth:v,boxHeight:M,position:a});t.fillStyle=l,t.roundRect?(t.roundRect(w,m,v,M,x),t.fill()):t.fillRect(w,m,v,M),t.fillStyle=h,t.textAlign="left",t.textBaseline="top",t.fillText(e.title,w+d,m+c)})}}class b{constructor(t,e,n,i,s,o,a,r,h,l){this.canvas=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.renderer=s,this.getDrawType=o,this.getBgImage=a,this.renderCallback=r,this.setDrawTypeCallback=h,this.notifyUndo=l,this.isDragging=!1,this.dragStart={x:0,y:0},this.justFinishedMove=!1,this.justDeselected=!1}handleWheel(t){if(t.preventDefault(),!this.getBgImage())return;const e=t.deltaY>0?-.02:.02,n=this.viewport.scale,i=Math.max(this.viewport.minScale,Math.min(n+e,this.viewport.maxScale)),s=this.canvas.getBoundingClientRect(),o=t.clientX-s.left,a=t.clientY-s.top,r=(o-this.viewport.offset.x)/n,h=(a-this.viewport.offset.y)/n;this.viewport.scale=i;const l=r*i+this.viewport.offset.x,d=h*i+this.viewport.offset.y;this.viewport.offset.x+=o-l,this.viewport.offset.y+=a-d,this.viewport.calculateBoundaries(),this.viewport.constrainViewport(),this.viewport.isInitialScale=this.viewport.scale===this.viewport.initialScale,this.renderCallback()}handleMouseDown(t){var e,n;if(0!==t.button)return;const i=this.getDrawType(),s=this.getBgImage();if(this.annotationManager.selectedAnnotation&&s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),void this.renderCallback()}if("text"===i){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if("rect"===(null==n?void 0:n.type))return this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(e);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();if(this.annotationManager.selectedAnnotation)return this.annotationManager.deselectAnnotation(),void this.renderCallback()}return null!==this.textManager.selectedTextIndex?(this.textManager.deselectTextAnnotation(),void this.renderCallback()):void this.handleTextModeClick(t)}if(!s)return;const o=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if("rect"===i){if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"rect"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.startRectDrawing(o)}else if("polygon"===i){if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e&&"polygon-vertex"===e.type)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"polygon"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.isDrawing?this.checkPolygonPointValid(o)&&this.annotationManager.addPolygonPoint(o):this.annotationManager.startPolygonDrawing(o),this.annotationManager.updatePolygonTempPoint(o),this.renderCallback()}else if("drag"===i){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback()}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(this.handleRectModeClick(t,o))return;if(this.handlePolygonModeClick(t,o))return;this.isDragging=!0,this.dragStart={x:t.clientX,y:t.clientY},this.canvas.style.cursor="grabbing"}else""===i&&this.handleNoModeClick(t,o)}handleTextModeClick(t){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.startMoving(t,e),this.canvas.style.cursor="grabbing",this.renderCallback(),!0;const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return this.textManager.addTextAnnotation(n.x,n.y),!0}handleRectModeClick(t,e){var n,i;if("rect"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"rect"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"rect"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handlePolygonModeClick(t,e){var n,i;if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n&&"polygon-vertex"===n.type)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"polygon"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"polygon"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handleNoModeClick(t,e){const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();this.textManager.deselectTextAnnotation();const i=this.annotationManager.getAnnotationAtPoint(e);i?(this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback()):this.annotationManager.deselectAnnotation()}checkPolygonPointValid(t){const e=this.annotationManager.operate.data.length>0?this.annotationManager.operate.data[this.annotationManager.operate.data.length-1]:null;return!e||Math.abs(e.point.x-t.x)>5||Math.abs(e.point.y-t.y)>5}handleMouseMove(t){if(!this.getBgImage())return;const e=this.getDrawType();if(this.isDragging&&"drag"===e){const e=t.clientX-this.dragStart.x,n=t.clientY-this.dragStart.y;return this.viewport.updateOffset(e,n),this.dragStart={x:t.clientX,y:t.clientY},void this.renderCallback()}if(this.textManager.isTextMoving&&null!==this.textManager.movingTextIndex)this.textManager.moveAnnotation(t)&&this.renderCallback();else if((this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&this.annotationManager.selectedAnnotation)this.handleAnnotationMove(t);else{if(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||this.updateCursor(t),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updateRectDrawing(e),this.renderCallback()}if("polygon"===e&&this.annotationManager.isDrawing){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updatePolygonTempPoint(e),this.renderCallback()}}}handleAnnotationMove(t){var e,n;if(this.annotationManager.isResizing&&this.annotationManager.activeHandle){const i=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return"rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)?this.annotationManager.resizeRect(i):"polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)&&this.annotationManager.resizePolygon(i),void this.renderCallback()}if(!this.annotationManager.isMovingAnnotation||!this.annotationManager.selectedAnnotation)return;const i=(t.clientX-this.annotationManager.annotationMoveStart.x)/this.viewport.scale,s=(t.clientY-this.annotationManager.annotationMoveStart.y)/this.viewport.scale;this.annotationManager.moveSelectedAnnotation(i,s),this.annotationManager.updateMoveStart({x:t.clientX,y:t.clientY}),this.renderCallback()}isHoverLockedAnnotation(t){return!(!t||!this.annotationManager.selectedAnnotation)&&(!0===this.annotationManager.selectedAnnotation.locked&&t.index===this.annotationManager.selectedAnnotation.index)}updateCursor(t){const e=this.getDrawType();if("text"===e){if(this.getBgImage()){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}const n=this.annotationManager.getAnnotationAtPoint(e);if(n)return void(this.canvas.style.cursor=this.isHoverLockedAnnotation(n)?"default":"move")}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);return void(this.canvas.style.cursor=null!==e?"move":"crosshair")}"rect"!==e?"polygon"!==e?"drag"!==e?""!==e?this.canvas.style.cursor="default":this.updateNoModeCursor(t):this.updateDragModeCursor(t):this.updatePolygonModeCursor(t):this.updateRectModeCursor(t)}updateRectModeCursor(t){var e;if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void(this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updatePolygonModeCursor(t){var e;if("polygon"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){if(this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="crosshair")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updateDragModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"grab"}updateNoModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"default"}handleMouseUp(t){if(this.isDragging){this.isDragging=!1;const t=this.getDrawType();return void(this.canvas.style.cursor="drag"===t?"grab":"default")}if(this.textManager.isTextMoving){this.justFinishedMove=!0,this.textManager.finishMoving();const t=this.getDrawType();"drag"===t?this.canvas.style.cursor="grab":""===t?this.canvas.style.cursor="move":(this.textManager.endTextMoving(),this.canvas.style.cursor="default")}(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&(this.justFinishedMove=!0,this.annotationManager.finishMovingAnnotation(),this.canvas.style.cursor=this.annotationManager.selectedAnnotation?"move":"default"),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type&&(this.annotationManager.finishRectDrawing(),this.renderCallback())}handleMouseLeave(t){(this.isDragging||this.textManager.isTextMoving||this.annotationManager.isResizing||this.annotationManager.isMovingAnnotation)&&this.handleMouseUp(t)}handleDoubleClick(t){if(!this.getBgImage())return;this.justFinishedMove=!1;const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return void this.textManager.startEditing(e);if(this.annotationManager.selectedAnnotation){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if(n&&n.index===this.annotationManager.selectedAnnotation.index)return void this.annotationManager.startTitleEditing(n.index)}if("polygon"===this.getDrawType()){if(this.annotationManager.isDrawing&&this.annotationManager.operate.data.length<=2)return;this.annotationManager.finishPolygonDrawing(),this.renderCallback()}}handleClick(t){var e;const n=this.getDrawType();!this.getBgImage()||"polygon"!==n||this.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||(this.justDeselected?this.justDeselected=!1:null===(e=this.annotationManager.selectedAnnotation)||void 0===e||e.type)}handleKeyDown(t){const e=t.target;if(!e||"INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName&&"SELECT"!==e.tagName&&!e.isContentEditable){if("z"===t.key&&(t.ctrlKey||t.metaKey)){return v.withdrawAll(this.annotationManager,this.textManager)&&this.notifyUndo(),void this.renderCallback()}if(" "===t.key)return this.viewport.resetToInitial(),void this.renderCallback();if("Escape"!==t.key){if("Delete"===t.key||"Backspace"===t.key){if(null!==this.textManager.editingTextIndex)return this.textManager.removeTextAnnotation(this.textManager.editingTextIndex),void this.renderCallback();if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.renderCallback();this.annotationManager.selectedAnnotation&&(this.annotationManager.deleteSelectedAnnotation(),this.renderCallback())}}else this.annotationManager.isDrawing?(this.annotationManager.cancelDrawing(),this.renderCallback()):this.annotationManager.selectedAnnotation&&(this.annotationManager.deselectAnnotation(),this.renderCallback())}}}class C{constructor(){this.listeners=new Map}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.delete(e)}emit(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.forEach(t=>t(e))}clear(){this.listeners.clear()}}class k{constructor(t){this.canvas=document.createElement("canvas"),this.emitter=new C,this.bgImage=null,this.bgImageSrc="",this.bgImageExt="jpeg",this.drawType="";const{drawType:e,useEvents:n=!0,id:i="container",annotationColor:s,lineStyle:o,vertexStyle:a,textStyle:r,enableTitle:l=!1,clampToImageBounds:d=!0}=t,c=document.getElementById(i);if(!c)throw new Error(`Container with id "${i}" not found`);this.container=c,"absolute"!==c.style.position&&"fixed"!==c.style.position&&"relative"!==c.style.position&&(c.style.position="relative"),this.ctx=this.canvas.getContext("2d"),this.viewport=new h,this.viewport.setSize(c.clientWidth,c.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.canvas.style.cursor="default",this.canvas.style.display="block",c.appendChild(this.canvas),this.annotationManager=new w(this.viewport,this.container,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),this.annotationManager.measureTitleWidth=(t,e)=>(this.ctx.font=e,this.ctx.measureText(t).width),s&&this.annotationManager.setColorConfig(s),o&&this.annotationManager.setLineStyle(o),a&&this.annotationManager.setVertexStyle(a),this.annotationManager.enableTitle=l,l&&this.annotationManager.initTitleSupport(),this.annotationManager.clampEnabled=d,this.textManager=new m(this.viewport,this.container,this.ctx,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),r&&this.textManager.setTextStyle(r),this.textManager.clampEnabled=d,this.renderer=new S(this.ctx,this.viewport,this.annotationManager,this.textManager),this.eventHandler=new b(this.canvas,this.viewport,this.annotationManager,this.textManager,this.renderer,()=>this.drawType,()=>this.bgImage,()=>this.render(),t=>this.setDrawType(t),()=>this.emitter.emit("undo",void 0)),this.events={wheel:t=>this.eventHandler.handleWheel(t),mousedown:t=>this.eventHandler.handleMouseDown(t),mousemove:t=>this.eventHandler.handleMouseMove(t),mouseup:t=>this.eventHandler.handleMouseUp(t),mouseleave:t=>this.eventHandler.handleMouseLeave(t),dblclick:t=>this.eventHandler.handleDoubleClick(t),click:t=>this.eventHandler.handleClick(t),keydown:t=>this.eventHandler.handleKeyDown(t)},this.setDrawType(e||""),n&&this.addEventListeners()}setDrawType(t){"polygon"===this.drawType&&this.annotationManager.isDrawing&&this.annotationManager.operate.data.length>0?console.warn("Cannot switch mode while polygon is being drawn. Please complete or cancel the polygon first."):this.drawType!==t&&(this.annotationManager.operate.data=[],this.annotationManager.isDrawing=!1,this.annotationManager.tempPolygonPoint=null,""!==t&&this.deselectAnnotation(),this.annotationManager.operate.type=t,this.drawType=t,this.canvas.style.cursor="drag"===t?"grab":"text"===t?"text":"default")}drawImage(t){this.bgImageSrc=t,this.bgImageExt=n(t);const e=new Image;e.crossOrigin="anonymous",e.src=t,e.onload=()=>{this.bgImage=e,this.viewport.setOriginalSize(e.width,e.height),this.viewport.calculateInitialView(),this.annotationManager.adjustTitlePositions(),this.render()}}render(){this.renderer.render(this.bgImage)}clear(t=""){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.setDrawType(t),this.render(),this.emitter.emit("clear",void 0)}withdraw(){const t=this.annotationManager.withdraw(),e=this.textManager.withdraw();(t||e)&&(this.render(),this.emitter.emit("undo",void 0))}resize(){const t=this.canvas.parentElement;t&&(this.viewport.setSize(t.clientWidth,t.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.render())}addEventListeners(){this.canvas.addEventListener("mousedown",this.events.mousedown),this.canvas.addEventListener("mousemove",this.events.mousemove),this.canvas.addEventListener("mouseup",this.events.mouseup),this.canvas.addEventListener("mouseleave",this.events.mouseleave),this.canvas.addEventListener("wheel",this.events.wheel),this.canvas.addEventListener("contextmenu",t=>t.preventDefault()),document.addEventListener("keydown",this.events.keydown),this.handleClickEventListener()}handleClickEventListener(){let t=null,e=0;this.canvas.addEventListener("click",n=>{if(this.eventHandler.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving)return;const i=this.eventHandler.justFinishedMove;i&&(this.eventHandler.justFinishedMove=!1),e++,1===e?t=window.setTimeout(()=>{1!==e||i||this.events.click(n),e=0,t=null},300):2===e&&(this.eventHandler.justFinishedMove=!1,this.events.dblclick(n),e=0,null!==t&&(clearTimeout(t),t=null))})}changeScale(t){if(!this.bgImage)return;const e=o(this.viewport.scale,t),n=this.viewport.width/2,i=this.viewport.height/2,s=this.viewport.scale+e;this.viewport.updateScale(s,n,i),this.render()}clearCanvas(t=!1,e=!0){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.textManager.deselectTextAnnotation(),this.emitter.emit("clear",void 0),!t&&e&&(this.bgImage=null,this.bgImageSrc="",this.viewport.setOriginalSize(0,0),this.viewport.reset()),this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.bgImage&&this.render(),"drag"===this.drawType&&(this.canvas.style.cursor="default")}clearAnnotations(){this.clearCanvas(!0,!1)}getAnnotations(){return this.annotationManager.getAnnotations()}getAnnotation(t){return this.annotationManager.getAnnotation(t)}getTextAnnotation(t){return this.textManager.getTextAnnotation(t)}on(t,e){this.emitter.on(t,e)}off(t,e){this.emitter.off(t,e)}setAnnotationTitle(t,e){const n=this.annotationManager.setTitle(t,e);return n&&this.render(),n}getAnnotationTitle(t){return this.annotationManager.getTitle(t)}setTitleStyle(t){this.annotationManager.setTitleStyle(t),this.render()}getTitleStyle(){return this.annotationManager.getTitleStyle()}setTitlePosition(t){this.annotationManager.setTitlePosition(t),this.render()}getTitlePosition(){return this.annotationManager.getTitlePosition()}setAnnotationTitleStyle(t,e){const n=this.annotationManager.setAnnotationTitleStyle(t,e);return n&&this.render(),n}setAnnotationTitlePosition(t,e){const n=this.annotationManager.setAnnotationTitlePosition(t,e);return n&&this.render(),n}getTextAnnotations(){return this.textManager.getTextAnnotations()}exportAnnotationImage(){return new Promise((t,e)=>{if(!this.bgImage)return void e(new Error("No background image loaded"));const n=document.createElement("canvas");n.width=this.viewport.originalWidth,n.height=this.viewport.originalHeight;const i=n.getContext("2d");if(!i)return void e(new Error("Could not create offscreen canvas context"));const s=new Image;s.src=this.bgImageSrc,s.crossOrigin="anonymous",s.onload=()=>{try{this.renderer.drawForExport(i,s,this.viewport.originalWidth,this.viewport.originalHeight);const e=n.toDataURL(`image/${this.bgImageExt}`,.7);t(e)}catch(n){this.exportCurrentViewImage().then(t).catch(t=>e(new Error(`Both methods failed: ${t.message}`)))}},s.onerror=()=>{e(new Error("Failed to load image for export"))}})}exportCurrentViewImage(){return new Promise((t,e)=>{try{t(this.canvas.toDataURL(`image/${this.bgImageExt}`))}catch(t){e(new Error(`Failed to export current view: ${t.message}`))}})}base64ToFile(t,e){return i(t,e)}static base64ToBlob(t){return s(t)}addTextAnnotation(t,e,n=""){this.textManager.addTextAnnotation(t,e,n),this.render()}updateTextAnnotation(t,e){this.textManager.updateTextAnnotation(t,e)&&this.render()}moveTextAnnotation(t,e,n){this.textManager.moveTextAnnotation(t,e,n)&&this.render()}removeTextAnnotation(t){this.textManager.removeTextAnnotation(t)&&this.render()}clearTextAnnotations(){this.textManager.clearTextAnnotations(),this.render()}selectAnnotation(t,e){this.annotationManager.selectAnnotation(t,e)&&this.render()}deselectAnnotation(){this.annotationManager.deselectAnnotation(),this.textManager.deselectTextAnnotation(),this.textManager.editingTextIndex=null,this.render()}getSelectedAnnotation(){const t=this.annotationManager.getSelectedAnnotation();if(t)return t;const e=this.textManager.getSelectedTextAnnotation();return e?{index:e.index,type:"text",data:e.data}:null}deleteSelectedAnnotation(){if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.render();this.annotationManager.deleteSelectedAnnotation()&&this.render()}moveSelectedAnnotation(t,e){if(this.annotationManager.moveSelectedAnnotation(t,e)){const t=this.annotationManager.selectedAnnotation;t&&this.annotationManager.notifyUpdate(t.index),this.render()}}setAnnotationColor(t){this.annotationManager.setColorConfig(t),this.render()}getAnnotationColor(){return this.annotationManager.getColorConfig()}updateSelectedAnnotationStyle(t){if(void 0!==t){const e=this.annotationManager.updateAnnotationStyle(t);return e&&this.render(),e}const e=this.annotationManager.selectedAnnotation;if(!e)return!1;const n=this.annotationManager.recordList[e.index];return!!n&&(n.style=this.annotationManager.getCurrentStyle(),this.annotationManager.notifyUpdate(e.index),this.render(),!0)}setLineStyle(t){this.annotationManager.setLineStyle(t),this.render()}getLineStyle(){return this.annotationManager.getLineStyle()}setVertexStyle(t){this.annotationManager.setVertexStyle(t),this.render()}getVertexStyle(){return this.annotationManager.getVertexStyle()}setTextStyle(t){this.textManager.setTextStyle(t),this.render()}updateTextAnnotationStyle(t,e){const n=this.textManager.updateTextAnnotationStyle(t,e);return n&&this.render(),n}setTextInputStyle(t){this.textManager.setInputStyle(t)}setTextSelectionStyle(t){this.textManager.setSelectionStyle(t),this.render()}destroy(){this.emitter.clear(),document.removeEventListener("keydown",this.events.keydown),this.textManager.destroy(),this.annotationManager.destroyTitleInput(),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}export{w as AnnotationManager,k as Drawer,C as Emitter,b as EventHandler,S as Renderer,m as TextAnnotationManager,h as ViewportManager,s as base64ToBlob,i as base64ToFile,k as default,n as getImageTypeFromUrl,o as getZoomDelta,e as isPointInPolygon,t as isPointInRect};
|
|
1
|
+
function t(t,e){const n=e.width>=0?e.start.x:e.start.x+e.width,i=e.height>=0?e.start.y:e.start.y+e.height,s=Math.abs(e.width),o=Math.abs(e.height);return t.x>=n&&t.x<=n+s&&t.y>=i&&t.y<=i+o}function e(t,e){if(e.length<3)return!1;let n=!1;for(let i=0,s=e.length-1;i<e.length;s=i++){const o=e[i].point.x,a=e[i].point.y,r=e[s].point.x,h=e[s].point.y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n}function n(t){try{const e=new URL(t).pathname.toLowerCase();return e.endsWith(".png")?"png":e.endsWith(".jpg")?"jpg":e.endsWith(".jpeg")?"jpeg":e.endsWith(".webp")?"webp":e.endsWith(".gif")?"gif":e.endsWith(".bmp")?"bmp":e.endsWith(".svg")?"svg":"jpeg"}catch(t){return"jpeg"}}function i(t,e){const n=t.split(";base64,"),i=n[0].split(":")[1],s=window.atob(n[1]),o=s.length,a=new Uint8Array(o);for(let t=0;t<o;++t)a[t]=s.charCodeAt(t);const r=new Blob([a],{type:i});return new File([r],e,{type:i})}function s(t){return new Promise((e,n)=>{const i=t.split(";base64,");if(i.length<2)return void n(new Error("Invalid base64 string"));const s=i[0].split(":")[1],o=atob(i[1]),a=new ArrayBuffer(o.length),r=new Uint8Array(a);for(let t=0;t<o.length;t++)r[t]=o.charCodeAt(t);e(new Blob([a],{type:s}))})}function o(t,e){return t<2?e?.1:-.1:t<5?e?.05:-.05:e?.02:-.02}function a(t){return"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t))}function r(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():`id-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}class h{constructor(){this.width=0,this.height=0,this.originalWidth=0,this.originalHeight=0,this.scale=1,this.minScale=1,this.maxScale=10,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}setSize(t,e){this.width=t,this.height=e}setOriginalSize(t,e){this.originalWidth=t,this.originalHeight=e}calculateInitialView(){if(0===this.originalWidth||0===this.originalHeight)return;const t=this.width/this.originalWidth,e=this.height/this.originalHeight;this.scale=Math.min(t,e),this.initialScale=this.scale,this.minScale=this.initialScale,this.offset={x:(this.width-this.originalWidth*this.scale)/2,y:(this.height-this.originalHeight*this.scale)/2},this.initialOffset=Object.assign({},this.offset),this.calculateBoundaries(),this.isInitialScale=!0}calculateBoundaries(){const t=this.originalWidth*this.scale,e=this.originalHeight*this.scale;this.maxOffsetX=0,this.maxOffsetY=0,this.minOffsetX=this.width-t,this.minOffsetY=this.height-e,this.minOffsetX>this.maxOffsetX&&([this.minOffsetX,this.maxOffsetX]=[this.maxOffsetX,this.minOffsetX]),this.minOffsetY>this.maxOffsetY&&([this.minOffsetY,this.maxOffsetY]=[this.maxOffsetY,this.minOffsetY])}constrainViewport(){this.offset.x>this.maxOffsetX?this.offset.x=this.maxOffsetX:this.offset.x<this.minOffsetX&&(this.offset.x=this.minOffsetX),this.offset.y>this.maxOffsetY?this.offset.y=this.maxOffsetY:this.offset.y<this.minOffsetY&&(this.offset.y=this.minOffsetY)}toImageCoordinates(t,e){return{x:(t-this.offset.x)/this.scale,y:(e-this.offset.y)/this.scale}}toCanvasCoordinates(t,e){return{x:this.offset.x+t*this.scale,y:this.offset.y+e*this.scale}}updateScale(t,e,n){const i=this.scale,s=(e-this.offset.x)/i,o=(n-this.offset.y)/i;this.scale=Math.max(this.minScale,Math.min(t,this.maxScale));const a=s*this.scale+this.offset.x,r=o*this.scale+this.offset.y;this.offset.x+=e-a,this.offset.y+=n-r,this.calculateBoundaries(),this.constrainViewport(),this.isInitialScale=this.scale===this.initialScale}resetToInitial(){this.scale=this.initialScale,this.offset=Object.assign({},this.initialOffset),this.calculateBoundaries(),this.isInitialScale=!0}updateOffset(t,e){this.offset.x+=t,this.offset.y+=e,this.constrainViewport()}reset(){this.scale=1,this.minScale=1,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}}const l={minX:Number.NEGATIVE_INFINITY,minY:Number.NEGATIVE_INFINITY,maxX:Number.POSITIVE_INFINITY,maxY:Number.POSITIVE_INFINITY};function d(t,e,n){return Math.min(Math.max(t,e),n)}function c(t){var e,n,i,s;const{anchor:o,boxWidth:a,boxHeight:r,position:h}=t,c=null!==(e=t.bounds)&&void 0!==e?e:l,g=null!==(n=t.gap)&&void 0!==n?n:4,x=null!==(i=h.offsetX)&&void 0!==i?i:0,u=null!==(s=h.offsetY)&&void 0!==s?s:0,f=h.align||"center";let p;switch(f){case"left":p=o.x+x;break;case"right":p=o.x+o.width-a+x;break;default:p=o.x+o.width/2-a/2+x}const y=d(p,c.minX,Math.max(c.minX,c.maxX-a)),v=x+(y-p),M=h.vertical||"top";let w,m=M;return"inside-top"===M?w=o.y+g+u:"bottom"===M?(w=o.y+o.height+g+u,w+r>c.maxY&&(m="top",w=o.y-r-g+u)):(w=o.y-r-g+u,w<c.minY&&(m="bottom",w=o.y+o.height+g+u)),w=d(w,c.minY,Math.max(c.minY,c.maxY-r)),{x:y,y:w,vertical:m,align:f,offsetX:v}}function g(t){const{x:e,y:n}=c(t);return{x:e,y:n}}function x(t,e){if("polygon"===t.type){const n=t.data;if(0===n.length)return null;let i=1/0,s=1/0,o=-1/0,a=-1/0;return n.forEach(t=>{const n=e?e.offset.x+t.point.x*e.scale:t.point.x,r=e?e.offset.y+t.point.y*e.scale:t.point.y;n<i&&(i=n),r<s&&(s=r),n>o&&(o=n),r>a&&(a=r)}),{x:i,y:s,width:o-i,height:a-s}}const n=t.data[0];return e?{x:e.offset.x+n.start.x*e.scale,y:e.offset.y+n.start.y*e.scale,width:n.width*e.scale,height:n.height*e.scale}:{x:n.start.x,y:n.start.y,width:n.width,height:n.height}}function u(t,e,n){if(!n)return e;const{originalWidth:i,originalHeight:s}=t;return i&&s?{x:Math.max(0,Math.min(e.x,i)),y:Math.max(0,Math.min(e.y,s))}:e}function f(t,e,n,i,s){t&&s.id&&t(n,{id:s.id,type:e,index:i,data:a(s)})}const p=new class{constructor(){this.type="rect"}startDrawing(t,e){t.isDrawing=!0,t.drawStartPoint=e,t.operate={type:"rect",data:[{start:Object.assign({},e),width:0,height:0}],status:"pending"}}updateDrawing(t,e){if(!t.isDrawing||"rect"!==t.operate.type)return;const n=t.operate.data[0];n.width=e.x-t.drawStartPoint.x,n.height=e.y-t.drawStartPoint.y}addPoint(t,e){return!1}finishDrawing(t){if(!t.isDrawing||"rect"!==t.operate.type)return!1;const e=t.operate.data[0];return Math.abs(e.width)>5&&Math.abs(e.height)>5&&t.pushRecord(Object.assign({},t.operate)),t.operate.data=[],t.isDrawing=!1,!0}cancelDrawing(t){t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data=[],t.isDrawing=!1,!0)}hitTest(e,n){return t(n,e.data[0])}getHandles(t,e,n){const i=t.data[0],s=e.offset.x+i.start.x*e.scale,o=e.offset.y+i.start.y*e.scale,a=i.width*e.scale,r=i.height*e.scale;return[{x:s,y:o,index:0},{x:s+a,y:o,index:1},{x:s,y:o+r,index:2},{x:s+a,y:o+r,index:3}]}move(t,e,n){const i=t.data[0];i.start.x+=e,i.start.y+=n}snapshotForResize(t){const e=t.data[0];return{start:Object.assign({},e.start),width:e.width,height:e.height}}resize(t,e,n,i){const s=t.data[0],o=i,a=o.start.x,r=o.start.x+o.width,h=o.start.y,l=o.start.y+o.height;let d,c;switch(e){case 0:d=r,c=l;break;case 1:d=a,c=l;break;case 2:d=r,c=h;break;case 3:d=a,c=h;break;default:return}const g=Math.min(n.x,d),x=Math.max(n.x,d),u=Math.min(n.y,c),f=Math.max(n.y,c);s.start.x=g,s.start.y=u,s.width=x-g,s.height=f-u;const p=n.x<d,y=n.y<c;let v;return 0===e?p||y?!p&&y?v=1:p&&!y&&(v=2):v=3:1===e?p&&!y?v=2:p&&y?v=0:p||y||(v=3):2===e?!p&&y?v=1:p&&y?v=0:p||y||(v=3):3===e&&(p&&y?v=0:!p&&y?v=1:p&&!y&&(v=2)),o.start.x=s.start.x,o.start.y=s.start.y,o.width=s.width,o.height=s.height,v}getBounds(t){const e=t.data[0];return{x:e.start.x,y:e.start.y,width:e.width,height:e.height}}};const y=new class{constructor(){this.type="polygon"}startDrawing(t,e){t.isDrawing=!0,t.operate={type:"polygon",data:[{point:e}],status:"pending"},t.tempPolygonPoint=e}updateDrawing(t,e){t.tempPolygonPoint=e}addPoint(t,e){if(!t.isDrawing||"polygon"!==t.operate.type)return!1;const n=t.operate.data.length>0?t.operate.data[t.operate.data.length-1]:null;return!(n&&Math.abs(n.point.x-e.x)<=5&&Math.abs(n.point.y-e.y)<=5)&&(t.operate.data.push({point:e}),!0)}finishDrawing(t){return!(!t.isDrawing||"polygon"!==t.operate.type)&&(t.operate.data.length>=3&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate={type:"polygon",data:[],status:"pending"},t.isDrawing=!1,t.tempPolygonPoint=null,!0)}cancelDrawing(t){t.isDrawing&&"polygon"===t.operate.type&&t.operate.data.length>=2&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data.pop(),0===t.operate.data.length&&(t.isDrawing=!1),!0)}hitTest(t,n){return e(n,t.data)}getHandles(t,e,n){const i=t.data,s=[];for(let t=0;t<i.length;t++){const n=i[t];s.push({x:e.offset.x+n.point.x*e.scale,y:e.offset.y+n.point.y*e.scale,index:t})}return s}move(t,e,n){t.data.forEach(t=>{t.point.x+=e,t.point.y+=n})}snapshotForResize(t){return t.data.map(t=>({point:Object.assign({},t.point)}))}resize(t,e,n,i){const s=t.data;e>=0&&e<s.length&&(s[e].point.x=n.x,s[e].point.y=n.y)}getBounds(t){const e=t.data;if(0===e.length)return{x:0,y:0,width:0,height:0};let n=1/0,i=1/0,s=-1/0,o=-1/0;return e.forEach(t=>{t.point.x<n&&(n=t.point.x),t.point.y<i&&(i=t.point.y),t.point.x>s&&(s=t.point.x),t.point.y>o&&(o=t.point.y)}),{x:n,y:i,width:s-n,height:o-i}}};const v=new class{constructor(){this.strategies=new Map}register(t){this.strategies.set(t.type,t)}get(t){const e=this.strategies.get(t);if(!e)throw new Error(`No strategy registered for shape type: ${t}`);return e}selectShapeExclusive(t,e,n){return"shape"===n.kind?(e.deselectTextAnnotation(),t.selectAnnotation(n.ref,{lock:n.locked})):(t.deselectAnnotation(),e.selectTextAnnotation(n.index))}deselectAll(t,e){t.deselectAnnotation(),e.deselectTextAnnotation()}withdrawAll(t,e){return t.withdraw()||e.withdraw()}};v.register(p),v.register(y);class M{constructor(t,e,n,i){this.viewport=t,this.container=e,this.renderCallback=n,this.changeCallback=i,this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.drawStartPoint={x:0,y:0},this.tempPolygonPoint=null,this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.annotationMoveStart={x:0,y:0},this.originalRect=null,this.originalPolygon=null,this.deleteHistory=[],this.editingTitleIndex=null,this.titleInput=null,this.strokeStyle="red",this.lineWidth=5,this.lineStyle="solid",this.vertexStyle={size:8,fillColor:"red",strokeColor:"white",strokeWidth:2,shape:"circle"},this.selectionStyle={strokeColor:"#00D9FF",fillColor:"rgba(0,217,255,0.15)",handleSize:12,handleColor:"#00D9FF"},this.colorConfig={rect:"red",polygon:"red",default:"red"},this.titleStyle={font:"12px Arial",color:"#FFFFFF",backgroundColor:"rgba(0, 0, 0, 0.7)",paddingX:6,paddingY:3,borderRadius:4,placeholder:"输入标题..."},this.titlePosition={vertical:"top",align:"center",offsetX:0,offsetY:0},this.enableTitle=!1,this.clampEnabled=!0,this.applyColorConfig()}strategyOf(t){return v.get(t)}clamp(t){return u(this.viewport,t,this.clampEnabled)}clampToImageBounds(t){return u(this.viewport,t,this.clampEnabled)}clampRecordToImageBounds(t){if(!this.clampEnabled)return;const{originalWidth:e,originalHeight:n}=this.viewport;if(!e||!n)return;if("rect"===t.type){const i=t.data[0];if(!i)return;const s=Math.min(i.start.x,i.start.x+i.width),o=Math.max(i.start.x,i.start.x+i.width),a=Math.min(i.start.y,i.start.y+i.height),r=Math.max(i.start.y,i.start.y+i.height);if(s>=0&&a>=0&&o<=e&&r<=n)return;const h=Math.min(o-s,e),l=Math.min(r-a,n);return i.start.x=Math.max(0,Math.min(s,e-h)),i.start.y=Math.max(0,Math.min(a,n-l)),i.width=h,void(i.height=l)}const i=t.data;if(!i||0===i.length)return;let s=1/0,o=1/0,a=-1/0,r=-1/0;for(const t of i)s=Math.min(s,t.point.x),a=Math.max(a,t.point.x),o=Math.min(o,t.point.y),r=Math.max(r,t.point.y);let h=0,l=0;if(a-s>e||s<0?h=-s:a>e&&(h=e-a),r-o>n||o<0?l=-o:r>n&&(l=n-r),0!==h||0!==l)for(const t of i)t.point.x+=h,t.point.y+=l}pushRecord(t){const e=Object.assign(Object.assign({},t),{id:r(),style:this.getCurrentStyle()});this.recordList.push(e),this.deleteHistory=[],this.notifyChange("create",this.recordList.length-1,e)}initTitleSupport(){this.container&&this.enableTitle&&this.createTitleInput()}setColorConfig(t){this.colorConfig="string"==typeof t?{rect:t,polygon:t,default:t}:Object.assign(Object.assign({},this.colorConfig),t),this.applyColorConfig()}getColorConfig(){return Object.assign({},this.colorConfig)}applyColorConfig(){this.strokeStyle=this.colorConfig.default||"red"}getColorForType(t){return this.colorConfig[t]||this.colorConfig.default||"red"}getCurrentStyle(){return{strokeColor:this.strokeStyle,lineWidth:this.lineWidth,lineStyle:this.lineStyle,vertexStyle:Object.assign({},this.vertexStyle)}}notifyChange(t,e,n){f(this.changeCallback,n.type,t,e,n)}notifyUpdate(t){const e=this.recordList[t];e&&this.notifyChange("update",t,e)}resolveIndex(t){return"number"==typeof t?t:this.recordList.findIndex(e=>e.id===t)}getAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return a(this.recordList[e])}updateAnnotationStyle(t){const e=this.resolveIndex(t);return!(e<0||e>=this.recordList.length)&&(this.recordList[e].style=this.getCurrentStyle(),this.notifyUpdate(e),!0)}setLineStyle(t){this.lineStyle=t}setVertexStyle(t){this.vertexStyle=Object.assign(Object.assign({},this.vertexStyle),t),t.fillColor&&(this.strokeStyle=t.fillColor)}getLineStyle(){return this.lineStyle}getVertexStyle(){return Object.assign({},this.vertexStyle)}getAnnotationStyle(t){return t.style||this.getCurrentStyle()}withdraw(){if(this.operate.data.length>0){const t="polygon"===this.operate.type?"polygon":"rect";return this.strategyOf(t).withdrawInProgress(this),!0}if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.recordList.splice(e,0,t),!0}return this.recordList.length>0&&(this.recordList.pop(),!0)}selectAnnotation(t,e){var n;const i=this.resolveIndex(t);if(i<0||i>=this.recordList.length)return this.deselectAnnotation(),!1;const s=this.recordList[i],o=void 0!==(null==e?void 0:e.lock)?!!e.lock:(null===(n=this.selectedAnnotation)||void 0===n?void 0:n.index)===i&&!0===this.selectedAnnotation.locked;return this.selectedAnnotation={index:i,type:s.type,locked:o},!0}deselectAnnotation(){this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null}deleteSelectedAnnotation(){if(!this.selectedAnnotation)return!1;const t=this.selectedAnnotation.index,e=this.recordList[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.recordList.splice(t,1),this.deselectAnnotation(),this.notifyChange("delete",t,e),!0}startMovingAnnotation(t){return!(!this.selectedAnnotation||!0===this.selectedAnnotation.locked)&&(this.isMovingAnnotation=!0,this.annotationMoveStart={x:t.clientX,y:t.clientY},!0)}updateMoveStart(t){this.annotationMoveStart=t}finishMovingAnnotation(){var t;const e=this.isMovingAnnotation||this.isResizing;if(this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null,e&&this.selectedAnnotation){const e=this.recordList[this.selectedAnnotation.index];(null==e?void 0:e.title)&&this.autoAdjustTitlePosition(e,e.title),this.notifyUpdate(this.selectedAnnotation.index),null===(t=this.renderCallback)||void 0===t||t.call(this)}}clear(){this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.tempPolygonPoint=null,this.deselectAnnotation(),this.deleteHistory=[]}getAnnotations(){return this.recordList.map(t=>a(t))}getSelectedAnnotation(){if(!this.selectedAnnotation)return null;const t=this.recordList[this.selectedAnnotation.index];return t?{index:this.selectedAnnotation.index,type:this.selectedAnnotation.type,data:a(t)}:null}setTitleStyle(t){this.titleStyle=Object.assign(Object.assign({},this.titleStyle),t)}getTitleStyle(){return Object.assign({},this.titleStyle)}setTitlePosition(t){this.titlePosition=Object.assign(Object.assign({},this.titlePosition),t)}getTitlePosition(){return Object.assign({},this.titlePosition)}getEffectiveTitleStyle(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titleStyle),e.titleStyle||{})}getEffectiveTitlePosition(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titlePosition),e.titlePosition||{})}captureTitleStyleSnapshot(t){t.style||(t.style=this.getCurrentStyle()),t.style.titleStyle=Object.assign({},this.titleStyle),t.style.titlePositionExplicit||(t.style.titlePosition=Object.assign({},this.titlePosition))}autoAdjustTitlePosition(t,e){var n,i,s;if(!e||(null===(n=t.style)||void 0===n?void 0:n.titlePositionExplicit))return;const{originalWidth:o,originalHeight:a,initialScale:r,scale:h}=this.viewport;if(o<=0||a<=0)return;const l=x(t);if(!l)return;const d=r>0?r:h>0?h:1,g={x:l.x*d,y:l.y*d,width:l.width*d,height:l.height*d},u=this.getEffectiveTitleStyle(t),f=u.font||"12px Arial",p=f.match(/(\d+)px/),y=(p?parseInt(p[1]):12)+2*(null!==(i=u.paddingY)&&void 0!==i?i:3),v=this.measureTitleWidth,M=v?{minX:0,minY:0,maxX:o*d,maxY:a*d}:{minX:Number.NEGATIVE_INFINITY,minY:0,maxX:Number.POSITIVE_INFINITY,maxY:a*d},w=v?v(e,f)+2*(null!==(s=u.paddingX)&&void 0!==s?s:6):0,m=Object.assign({},this.titlePosition),A=c({anchor:g,boxWidth:w,boxHeight:y,position:m,bounds:M});t.style||(t.style=this.getCurrentStyle()),t.style.titlePosition=Object.assign(Object.assign({},m),{vertical:A.vertical,align:A.align,offsetX:A.offsetX})}adjustTitlePositions(){this.viewport.originalWidth<=0||this.viewport.originalHeight<=0||this.recordList.forEach(t=>{var e;t.title&&!(null===(e=t.style)||void 0===e?void 0:e.titlePositionExplicit)&&this.autoAdjustTitlePosition(t,t.title)})}setAnnotationTitleStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titleStyle=Object.assign(Object.assign({},i.style.titleStyle||this.titleStyle),e),this.notifyUpdate(n),!0}setAnnotationTitlePosition(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titlePosition=Object.assign(Object.assign({},i.style.titlePosition||this.titlePosition),e),i.style.titlePositionExplicit=!0,this.notifyUpdate(n),!0}createTitleInput(){this.container&&(this.titleInput=document.createElement("input"),this.titleInput.type="text",this.titleInput.style.position="absolute",this.titleInput.style.zIndex="99998",this.titleInput.style.display="none",this.titleInput.style.outline="none",this.titleInput.style.border="1px solid #00D9FF",this.titleInput.style.borderRadius="4px",this.titleInput.style.padding="4px 8px",this.titleInput.style.fontSize="13px",this.titleInput.style.fontFamily="Arial, sans-serif",this.titleInput.style.backgroundColor="#ffffff",this.titleInput.style.color="#333",this.titleInput.style.boxShadow="0 2px 8px rgba(0,0,0,0.3)",this.titleInput.style.minWidth="80px",this.titleInput.style.maxWidth="200px",this.titleInput.placeholder=this.titleStyle.placeholder||"输入标题...",this.titleInput.addEventListener("blur",()=>{this.finishTitleEditing()}),this.titleInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?this.finishTitleEditing():"Escape"===t.key&&(t.preventDefault(),this.cancelTitleEditing())}),this.container.appendChild(this.titleInput))}setTitle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.title=e||void 0,e&&(this.captureTitleStyleSnapshot(i),this.autoAdjustTitlePosition(i,e)),this.notifyUpdate(n),!0}getTitle(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return this.recordList[e].title}startTitleEditing(t){if(!this.enableTitle||!this.titleInput||t<0||t>=this.recordList.length)return!1;const e=this.recordList[t];let n,i;if(this.editingTitleIndex=t,this.deselectAnnotation(),"rect"===e.type){const t=e.data[0];n=this.viewport.offset.x+t.start.x*this.viewport.scale,i=this.viewport.offset.y+t.start.y*this.viewport.scale}else{const t=e.data[0];n=this.viewport.offset.x+t.point.x*this.viewport.scale,i=this.viewport.offset.y+t.point.y*this.viewport.scale}return this.titleInput.value=e.title||"",this.titleInput.placeholder=this.getEffectiveTitleStyle(e).placeholder||"输入标题...",this.titleInput.style.left=`${n}px`,this.titleInput.style.top=i-32+"px",this.titleInput.style.display="block",setTimeout(()=>{this.titleInput&&(this.titleInput.focus(),this.titleInput.select())},10),!0}finishTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex,e=this.titleInput.value.trim();if(t>=0&&t<this.recordList.length){const n=this.recordList[t];n.title=e||void 0,e&&(this.captureTitleStyleSnapshot(n),this.autoAdjustTitlePosition(n,e)),this.notifyUpdate(t),this.selectAnnotation(t)}return this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}cancelTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex;return t>=0&&t<this.recordList.length&&this.selectAnnotation(t),this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}resetTitleEditingState(){this.titleInput&&(this.titleInput.style.display="none"),this.editingTitleIndex=null}destroyTitleInput(){this.titleInput&&this.titleInput.parentNode&&(this.titleInput.parentNode.removeChild(this.titleInput),this.titleInput=null)}}class w extends M{startRectDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("rect").startDrawing(this,t)}updateRectDrawing(t){this.isDrawing&&"rect"===this.operate.type&&(t=this.clampToImageBounds(t),this.strategyOf("rect").updateDrawing(this,t))}finishRectDrawing(){return this.strategyOf("rect").finishDrawing(this)}startPolygonDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("polygon").startDrawing(this,t)}addPolygonPoint(t){return!(!this.isDrawing||"polygon"!==this.operate.type)&&(t=this.clampToImageBounds(t),this.strategyOf("polygon").addPoint(this,t))}updatePolygonTempPoint(t){this.strategyOf("polygon").updateDrawing(this,this.clampToImageBounds(t))}finishPolygonDrawing(){return this.strategyOf("polygon").finishDrawing(this)}cancelDrawing(){const t="polygon"===this.operate.type?"polygon":"rect";this.strategyOf(t).cancelDrawing(this)}moveSelectedAnnotation(t,e){if(!this.selectedAnnotation)return!1;const n=this.recordList[this.selectedAnnotation.index];return!!n&&(this.strategyOf(n.type).move(n,t,e),this.clampRecordToImageBounds(n),!0)}startResizing(t,e){if(!this.selectedAnnotation)return!1;this.activeHandle=t,this.isResizing=!0;const n=this.recordList[this.selectedAnnotation.index];return"rect"===n.type?this.originalRect=this.strategyOf("rect").snapshotForResize(n):"polygon"===n.type&&(this.originalPolygon=this.strategyOf("polygon").snapshotForResize(n)),!0}resizeRect(t){if(!this.selectedAnnotation||"rect"!==this.selectedAnnotation.type||!this.originalRect||!this.activeHandle)return!1;if(this.activeHandle.index<0||this.activeHandle.index>3)return!1;const e=this.recordList[this.selectedAnnotation.index],n=this.clampToImageBounds(t),i=this.strategyOf("rect").resize(e,this.activeHandle.index,n,this.originalRect);return"number"==typeof i&&(this.activeHandle.index=i),!0}resizePolygon(t){var e;if(!this.selectedAnnotation||"polygon"!==this.selectedAnnotation.type||!this.activeHandle)return!1;const n=this.recordList[this.selectedAnnotation.index],i=this.activeHandle.index,s=n.data;return!(i<0||i>=s.length)&&(this.strategyOf("polygon").resize(n,i,this.clampToImageBounds(t),null!==(e=this.originalPolygon)&&void 0!==e?e:[]),!0)}getAnnotationAtPoint(t){for(let e=this.recordList.length-1;e>=0;e--){const n=this.recordList[e],i=n.type;if(this.strategyOf(i).hitTest(n,t))return{index:e,type:i}}return null}getHandleAtPoint(t,e){if(!this.selectedAnnotation)return null;if(!0===this.selectedAnnotation.locked)return null;const n=this.recordList[this.selectedAnnotation.index],i=this.selectionStyle.handleSize,s=i/2,o=this.selectedAnnotation.type,a=this.strategyOf(o).getHandles(n,this.viewport,i);for(const n of a)if(t>=n.x-s&&t<=n.x+s&&e>=n.y-s&&e<=n.y+s)return"rect"===o?{type:"rect-corner",index:n.index}:{type:"polygon-vertex",index:n.index};return null}}class m{constructor(t,e,n,i,s){this.viewport=t,this.container=e,this.ctx=n,this.renderCallback=i,this.changeCallback=s,this.textAnnotations=[],this.editingTextIndex=null,this.currentEditingIndex=null,this.movingTextIndex=null,this.isTextMoving=!1,this.textMoveStart={x:0,y:0},this.textBeforeEditing="",this.selectedTextIndex=null,this.clampEnabled=!0,this.textInput=null,this.deleteHistory=[],this.defaultInputStyle={border:"2px solid #00D9FF",borderRadius:"6px",padding:"6px 10px",fontSize:"16px",fontFamily:"Arial, sans-serif",backgroundColor:"#ffffff",color:"#333",boxShadow:"0 4px 12px rgba(0,0,0,0.3)",minWidth:"60px",maxWidth:"200px"},this.textStyle={font:"16px Arial",color:"#FFD700",padding:6,backgroundColor:"rgba(0,0,0,0.6)",borderRadius:4,selectedBorderColor:"#00D9FF",selectedBackgroundColor:"rgba(0,217,255,0.15)",inputStyle:Object.assign({},this.defaultInputStyle)},this.createTextInput()}createTextInput(){this.textInput=document.createElement("input"),this.textInput.type="text",this.textInput.style.position="absolute",this.textInput.style.zIndex="99999",this.textInput.style.display="none",this.textInput.style.outline="none",this.textInput.style.width="fit-content",this.textInput.placeholder="输入文字...",this.applyInputStyle(),this.textInput.addEventListener("blur",()=>{this.finishEditing(),this.renderCallback&&this.renderCallback()}),this.textInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?(this.finishEditing(),this.renderCallback&&this.renderCallback()):"Escape"===t.key?(t.preventDefault(),this.cancelEditing()):"Delete"===t.key&&""===this.textInput.value&&(t.preventDefault(),this.deleteEditingAnnotation())}),this.textInput.addEventListener("input",()=>{this.adjustInputWidth()}),this.container.appendChild(this.textInput)}applyInputStyle(){if(!this.textInput)return;const t=Object.assign(Object.assign({},this.defaultInputStyle),this.textStyle.inputStyle);this.textInput.style.border=t.border,this.textInput.style.borderRadius=t.borderRadius,this.textInput.style.padding=t.padding,this.textInput.style.fontSize=t.fontSize,this.textInput.style.fontFamily=t.fontFamily,this.textInput.style.backgroundColor=t.backgroundColor,this.textInput.style.color=t.color,this.textInput.style.boxShadow=t.boxShadow,this.textInput.style.minWidth=t.minWidth,this.textInput.style.maxWidth=t.maxWidth}setTextStyle(t){this.textStyle=Object.assign(Object.assign({},this.textStyle),t),this.applyInputStyle()}setInputStyle(t){this.textStyle.inputStyle=Object.assign(Object.assign({},this.textStyle.inputStyle),t),this.applyInputStyle()}setSelectionStyle(t){void 0!==t.selectedBorderColor&&(this.textStyle.selectedBorderColor=t.selectedBorderColor),void 0!==t.selectedBackgroundColor&&(this.textStyle.selectedBackgroundColor=t.selectedBackgroundColor)}getCurrentStyle(){return{font:this.textStyle.font,color:this.textStyle.color,backgroundColor:this.textStyle.backgroundColor}}notifyChange(t,e,n){f(this.changeCallback,"text",t,e,n)}resolveIndex(t){return"number"==typeof t?t:this.textAnnotations.findIndex(e=>e.id===t)}getTextAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.textAnnotations.length))return a(this.textAnnotations[e])}updateTextAnnotationStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];return i.style=Object.assign(Object.assign({},i.style||this.getCurrentStyle()),e),this.notifyChange("update",n,this.textAnnotations[n]),!0}clampToImageBounds(t){return u(this.viewport,t,this.clampEnabled)}addTextAnnotation(t,e,n=""){var i;const s=this.clampToImageBounds({x:t,y:e});t=s.x,e=s.y,this.ctx.font=this.textStyle.font;const o=n||"输入文字...",a=this.ctx.measureText(o);let h;if(a.actualBoundingBoxAscent&&a.actualBoundingBoxDescent)h=a.actualBoundingBoxAscent+a.actualBoundingBoxDescent;else{h=1.2*parseInt((null===(i=this.textStyle.font.match(/\d+/))||void 0===i?void 0:i[0])||"16")}const l={id:r(),position:{x:t,y:e},text:n,style:this.getCurrentStyle(),width:Math.max(a.width,60),height:h};this.textAnnotations.push(l);const d=this.textAnnotations.length-1;return this.notifyChange("create",d,l),this.deleteHistory=[],this.startEditing(d),d}updateTextAnnotation(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];i.text=e,this.ctx.font=this.textStyle.font;const s=this.ctx.measureText(e);return i.width=s.width,i.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",n,this.textAnnotations[n]),!0}moveTextAnnotation(t,e,n){const i=this.resolveIndex(t);return!(i<0||i>=this.textAnnotations.length)&&(this.textAnnotations[i].position={x:e,y:n},this.notifyChange("update",i,this.textAnnotations[i]),!0)}removeTextAnnotation(t){const e=this.resolveIndex(t);if(e<0||e>=this.textAnnotations.length)return!1;const n=this.textAnnotations[e];return this.deleteHistory.push({annotation:Object.assign({},n),index:e}),this.textAnnotations.splice(e,1),this.notifyChange("delete",e,n),this.editingTextIndex===e?this.resetEditingState():null!==this.editingTextIndex&&this.editingTextIndex>e&&this.editingTextIndex--,this.movingTextIndex===e?this.endTextMoving():null!==this.movingTextIndex&&this.movingTextIndex>e&&this.movingTextIndex--,!0}clearTextAnnotations(){this.textAnnotations=[],this.selectedTextIndex=null,this.cancelEditing(),this.deleteHistory=[]}startEditing(t){if(!this.textInput||t<0||t>=this.textAnnotations.length)return!1;const e=this.textAnnotations[t];this.editingTextIndex=t,this.currentEditingIndex=t,this.textBeforeEditing=e.text;const n=this.viewport.offset.x+e.position.x*this.viewport.scale,i=this.viewport.offset.y+e.position.y*this.viewport.scale;return this.textInput.value=e.text,this.textInput.style.left=`${n}px`,this.textInput.style.top=`${i}px`,this.textInput.style.display="block",this.adjustInputWidth(),setTimeout(()=>{this.textInput&&(this.textInput.focus(),this.textInput.select())},10),!0}finishEditing(){if(!this.textInput)return!1;const t=this.currentEditingIndex,e=this.textInput.value.trim();if(null===t||t<0||t>=this.textAnnotations.length)return this.resetEditingState(),!1;if(""===e){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}else{const n=this.textAnnotations[t];n.text=e,this.ctx.font=this.textStyle.font;const i=this.ctx.measureText(n.text);n.width=i.width,n.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",t,n)}return this.resetEditingState(),!0}cancelEditing(){if(!this.textInput||null===this.editingTextIndex)return!1;this.textInput.value=this.textBeforeEditing;const t=this.editingTextIndex;if(t>=0&&t<this.textAnnotations.length){if(""===this.textAnnotations[t].text&&""===this.textBeforeEditing){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}}return this.resetEditingState(),!0}deleteEditingAnnotation(){if(null===this.editingTextIndex)return!1;const t=this.editingTextIndex;if(this.textInput&&(this.textInput.style.display="none"),t>=0&&t<this.textAnnotations.length){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}return this.resetEditingState(),!0}resetEditingState(){this.textInput&&(this.textInput.style.display="none"),this.editingTextIndex=null,this.currentEditingIndex=null,this.textBeforeEditing=""}adjustInputWidth(){if(!this.textInput||null===this.editingTextIndex)return;this.ctx.font=this.textStyle.font;const t=this.textInput.value||this.textInput.placeholder||"",e=this.ctx.measureText(t).width,n=Math.min(Math.max(e+24,60),200);this.textInput.style.width=`${n}px`}startMoving(t,e){return!(e<0||e>=this.textAnnotations.length)&&(this.movingTextIndex=e,this.isTextMoving=!0,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}moveAnnotation(t){if(!this.isTextMoving||null===this.movingTextIndex)return!1;const e=t.clientX-this.textMoveStart.x,n=t.clientY-this.textMoveStart.y,i=this.textAnnotations[this.movingTextIndex];return!!i&&(i.position.x+=e/this.viewport.scale,i.position.y+=n/this.viewport.scale,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}finishMoving(){if(this.isTextMoving=!1,null!==this.movingTextIndex){const t=this.textAnnotations[this.movingTextIndex];t&&this.notifyChange("update",this.movingTextIndex,t)}this.movingTextIndex=null}endTextMoving(){this.isTextMoving=!1,this.movingTextIndex=null}isEditingVisible(){var t;return"block"===(null===(t=this.textInput)||void 0===t?void 0:t.style.display)}checkTextClick(t,e){for(let n=this.textAnnotations.length-1;n>=0;n--){const i=this.textAnnotations[n],s=this.viewport.offset.x+i.position.x*this.viewport.scale,o=this.viewport.offset.y+i.position.y*this.viewport.scale,a=Math.max(i.width,60)+2*this.textStyle.padding,r=i.height+2*this.textStyle.padding;if(t>=s&&t<=s+a&&e>=o&&e<=o+r)return n}return null}checkTextClickForMove(t){const e=this.checkTextClick(t.offsetX,t.offsetY);return null!==e?(this.startMoving(t,e),{index:e,handled:!0}):{index:-1,handled:!1}}getTextAnnotations(){return this.textAnnotations.map(t=>a(t))}withdraw(){if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.textAnnotations.splice(e,0,t),!0}return this.textAnnotations.length>0&&(this.textAnnotations.pop(),!0)}selectTextAnnotation(t){return t<0||t>=this.textAnnotations.length?(this.deselectTextAnnotation(),!1):(this.selectedTextIndex=t,null!==this.editingTextIndex&&this.finishEditing(),!0)}deselectTextAnnotation(){this.selectedTextIndex=null}deleteSelectedTextAnnotation(){if(null===this.selectedTextIndex)return!1;const t=this.selectedTextIndex,e=this.textAnnotations[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.textAnnotations.splice(t,1),this.selectedTextIndex=null,this.notifyChange("delete",t,e),null!==this.editingTextIndex&&this.editingTextIndex>t&&this.editingTextIndex--,null!==this.movingTextIndex&&this.movingTextIndex>t&&this.movingTextIndex--,!0}getSelectedTextAnnotation(){if(null===this.selectedTextIndex)return null;const t=this.textAnnotations[this.selectedTextIndex];return t?{index:this.selectedTextIndex,data:a(t)}:null}destroy(){this.textInput&&this.textInput.parentNode&&this.textInput.parentNode.removeChild(this.textInput)}}function A(t,e){switch(e){case"dashed":t.setLineDash([10,5]);break;case"dotted":t.setLineDash([2,4]);break;default:t.setLineDash([])}}class T{draw(t,e,n,i){const s=n.data[0];t.strokeRect(e.offset.x+s.start.x*e.scale,e.offset.y+s.start.y*e.scale,s.width*e.scale,s.height*e.scale)}drawInProgress(t,e,n){const i=n.operate.data[0];t.strokeRect(e.offset.x+i.start.x*e.scale,e.offset.y+i.start.y*e.scale,i.width*e.scale,i.height*e.scale)}drawSelection(t,e,n,i,s){const o=n.data[0],a=e.offset.x+o.start.x*e.scale,r=e.offset.y+o.start.y*e.scale,h=o.width*e.scale,l=o.height*e.scale;if(t.fillStyle=i.fillColor,t.fillRect(a,r,h,l),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.strokeRect(a,r,h,l),s)return;const d=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),t.fillRect(a-d/2,r-d/2,d,d),t.fillRect(a+h-d/2,r-d/2,d,d),t.fillRect(a-d/2,r+l-d/2,d,d),t.fillRect(a+h-d/2,r+l-d/2,d,d)}drawForExport(t,e,n){const i=e.data[0];t.strokeRect(i.start.x,i.start.y,i.width,i.height)}getTitleAnchor(t,e){return x(t,e)}}class I{constructor(t){this.store=t}draw(t,e,n,i){const s=i.vertexStyle||this.store.getVertexStyle();this.drawPolygon(t,e,n.data,"fullfilled"===n.status,s)}drawInProgress(t,e,n){const i=n.operate.data,s=n.tempPolygonPoint;if(t.beginPath(),i.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),s){const n=Math.round(e.offset.x+s.x*e.scale),i=Math.round(e.offset.y+s.y*e.scale);t.lineTo(n,i)}if(t.stroke(),this.drawPolygonVertices(t,e,i,n.getVertexStyle()),s){const i=n.getVertexStyle(),o=Math.round(e.offset.x+s.x*e.scale),a=Math.round(e.offset.y+s.y*e.scale),r=i.size/2;switch(t.fillStyle=i.fillColor,t.strokeStyle=i.strokeColor,t.lineWidth=i.strokeWidth,t.beginPath(),i.shape){case"square":t.rect(o-r,a-r,2*r,2*r);break;case"diamond":t.moveTo(o,a-r),t.lineTo(o+r,a),t.lineTo(o,a+r),t.lineTo(o-r,a),t.closePath();break;default:t.arc(o,a,r,0,2*Math.PI)}t.fill(),i.strokeWidth>0&&t.stroke()}}drawSelection(t,e,n,i,s){const o=n.data;if(t.beginPath(),o.forEach((n,i)=>{const s=e.offset.x+n.point.x*e.scale,o=e.offset.y+n.point.y*e.scale;0===i?t.moveTo(s,o):t.lineTo(s,o)}),t.closePath(),t.fillStyle=i.fillColor,t.fill(),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.stroke(),s)return;const a=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),o.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),s=Math.round(e.offset.y+n.point.y*e.scale);t.fillRect(i-a/2,s-a/2,a,a)})}drawForExport(t,e,n){if("fullfilled"!==e.status)return;const i=e.data;t.beginPath(),i.forEach((e,n)=>{0===n?t.moveTo(e.point.x,e.point.y):t.lineTo(e.point.x,e.point.y)});const s=e.data[0];t.lineTo(s.point.x,s.point.y),t.stroke(),i.forEach(e=>{t.beginPath(),t.arc(e.point.x,e.point.y,4,0,2*Math.PI),t.fillStyle=n.strokeColor,t.fill()})}getTitleAnchor(t,e){return x(t,e)}drawPolygon(t,e,n,i,s){if(0!==n.length){if(t.beginPath(),n.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),i&&n.length>1){const i=n[0];t.lineTo(e.offset.x+i.point.x*e.scale,e.offset.y+i.point.y*e.scale)}t.stroke(),this.drawPolygonVertices(t,e,n,s)}}drawPolygonVertices(t,e,n,i){const s=i||this.store.getVertexStyle(),o=s.size/2;n.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),a=Math.round(e.offset.y+n.point.y*e.scale);switch(t.fillStyle=s.fillColor,t.strokeStyle=s.strokeColor,t.lineWidth=s.strokeWidth,t.beginPath(),s.shape){case"square":t.rect(i-o,a-o,2*o,2*o);break;case"diamond":t.moveTo(i,a-o),t.lineTo(i+o,a),t.lineTo(i,a+o),t.lineTo(i-o,a),t.closePath();break;default:t.arc(i,a,o,0,2*Math.PI)}t.fill(),s.strokeWidth>0&&t.stroke()})}}class S{constructor(t,e,n,i){this.ctx=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.shapeRenderers={rect:new T,polygon:new I(n)}}render(t){this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.drawBackgroundImage(t),this.drawAnnotations(),function(t,e,n){const i=n.textStyle;n.textAnnotations.forEach((s,o)=>{if(n.editingTextIndex===o&&n.isEditingVisible())return;if(!s.text)return;const a=s.style||{font:i.font,color:i.color,backgroundColor:i.backgroundColor},r=e.offset.x+s.position.x*e.scale,h=e.offset.y+s.position.y*e.scale,l=n.selectedTextIndex===o;t.font=a.font;const d=t.measureText(s.text),c=d.actualBoundingBoxAscent||.8*s.height,g=c+(d.actualBoundingBoxDescent||.2*s.height),x=i.borderRadius,u=r,f=h,p=s.width+2*i.padding,y=g+2*i.padding;t.fillStyle=a.backgroundColor,t.beginPath(),t.roundRect(u,f,p,y,x),t.fill(),l&&(t.strokeStyle=i.selectedBorderColor,t.lineWidth=2,t.setLineDash([5,5]),t.beginPath(),t.roundRect(u,f,p,y,x),t.stroke(),t.setLineDash([]));const v=r+i.padding,M=h+i.padding+c;t.fillStyle=a.color,t.fillText(s.text,v,M)})}(this.ctx,this.viewport,this.textManager)}drawBackgroundImage(t){this.ctx.drawImage(t,this.viewport.offset.x,this.viewport.offset.y,this.viewport.originalWidth*this.viewport.scale,this.viewport.originalHeight*this.viewport.scale)}drawAnnotations(){this.annotationManager.recordList.forEach(t=>{const e=this.annotationManager.getAnnotationStyle(t);this.ctx.strokeStyle=e.strokeColor,this.ctx.lineWidth=e.lineWidth,A(this.ctx,e.lineStyle||"solid"),this.ctx.fillStyle=this.ctx.strokeStyle,"rect"===t.type?this.shapeRenderers.rect.draw(this.ctx,this.viewport,t,e):"polygon"===t.type&&this.shapeRenderers.polygon.draw(this.ctx,this.viewport,t,e),this.annotationManager.enableTitle&&t.title&&this.drawAnnotationTitle(t)}),this.annotationManager.operate.data.length>0&&(this.ctx.strokeStyle=this.annotationManager.strokeStyle,this.ctx.lineWidth=this.annotationManager.lineWidth,this.ctx.fillStyle=this.ctx.strokeStyle,A(this.ctx,this.annotationManager.lineStyle),"rect"===this.annotationManager.operate.type?this.shapeRenderers.rect.drawInProgress(this.ctx,this.viewport,this.annotationManager):"polygon"===this.annotationManager.operate.type&&this.shapeRenderers.polygon.drawInProgress(this.ctx,this.viewport,this.annotationManager)),this.ctx.setLineDash([]),this.drawSelectionHighlight()}drawSelectionHighlight(){const t=this.annotationManager.selectedAnnotation;if(!t)return;const e=this.annotationManager.recordList[t.index];if(!e)return;const n=this.annotationManager.selectionStyle,i=!0===t.locked;this.ctx.save(),"rect"===e.type?this.shapeRenderers.rect.drawSelection(this.ctx,this.viewport,e,n,i):"polygon"===e.type&&this.shapeRenderers.polygon.drawSelection(this.ctx,this.viewport,e,n,i),this.ctx.restore()}drawAnnotationTitle(t){var e,n,i;if(!t.title)return;const s=this.annotationManager.getEffectiveTitleStyle(t),o=this.annotationManager.getEffectiveTitlePosition(t),a=s.font||"12px Arial",r=s.color||"#FFFFFF",h=s.backgroundColor||"rgba(0, 0, 0, 0.7)",l=null!==(e=s.paddingX)&&void 0!==e?e:6,d=null!==(n=s.paddingY)&&void 0!==n?n:3,c=null!==(i=s.borderRadius)&&void 0!==i?i:4;this.ctx.save(),this.ctx.font=a;const x=this.ctx.measureText(t.title).width,u=a.match(/(\d+)px/),f=u?parseInt(u[1]):12,p=("rect"===t.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(t,this.viewport);if(!p)return void this.ctx.restore();const y=x+2*l,v=f+2*d,{x:M,y:w}=g({anchor:p,boxWidth:y,boxHeight:v,position:o});this.ctx.fillStyle=h,this.ctx.setLineDash([]),this.ctx.beginPath(),this.ctx.roundRect(M,w,y,v,c),this.ctx.fill(),this.ctx.fillStyle=r,this.ctx.textAlign="left",this.ctx.textBaseline="top",this.ctx.fillText(t.title,M+l,w+d),this.ctx.restore()}drawForExport(t,e,n,i){t.drawImage(e,0,0,n,i),this.annotationManager.recordList.forEach(e=>{const n=this.annotationManager.getAnnotationStyle(e);t.strokeStyle=n.strokeColor,t.lineWidth=n.lineWidth,"rect"===e.type?this.shapeRenderers.rect.drawForExport(t,e,n):"polygon"===e.type&&this.shapeRenderers.polygon.drawForExport(t,e,n)}),this.textManager.textAnnotations.forEach(e=>{const n=this.textManager.textStyle,i=e.style||{font:n.font,color:n.color,backgroundColor:n.backgroundColor};t.font=i.font;const s=t.measureText(e.text),o=s.actualBoundingBoxAscent||.8*e.height,a=o+(s.actualBoundingBoxDescent||.2*e.height),r=e.position.x,h=e.position.y,l=e.width+2*n.padding,d=a+2*n.padding,c=n.borderRadius;t.fillStyle=i.backgroundColor,t.roundRect?(t.roundRect(r,h,l,d,c),t.fill()):t.fillRect(r,h,l,d),t.fillStyle=i.color,t.fillText(e.text,e.position.x+n.padding,e.position.y+n.padding+o)}),this.annotationManager.enableTitle&&this.annotationManager.recordList.forEach(e=>{var n,i,s;if(!e.title)return;const o=this.annotationManager.getEffectiveTitleStyle(e),a=this.annotationManager.getEffectiveTitlePosition(e),r=o.font||"12px Arial",h=o.color||"#FFFFFF",l=o.backgroundColor||"rgba(0, 0, 0, 0.7)",d=null!==(n=o.paddingX)&&void 0!==n?n:6,c=null!==(i=o.paddingY)&&void 0!==i?i:3,x=null!==(s=o.borderRadius)&&void 0!==s?s:4;t.font=r;const u=t.measureText(e.title).width,f=r.match(/(\d+)px/),p=f?parseInt(f[1]):12,y=("rect"===e.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(e);if(!y)return;const v=u+2*d,M=p+2*c,{x:w,y:m}=g({anchor:y,boxWidth:v,boxHeight:M,position:a});t.fillStyle=l,t.roundRect?(t.roundRect(w,m,v,M,x),t.fill()):t.fillRect(w,m,v,M),t.fillStyle=h,t.textAlign="left",t.textBaseline="top",t.fillText(e.title,w+d,m+c)})}}class b{constructor(t,e,n,i,s,o,a,r,h,l){this.canvas=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.renderer=s,this.getDrawType=o,this.getBgImage=a,this.renderCallback=r,this.setDrawTypeCallback=h,this.notifyUndo=l,this.isDragging=!1,this.dragStart={x:0,y:0},this.justFinishedMove=!1,this.justDeselected=!1}handleWheel(t){if(t.preventDefault(),!this.getBgImage())return;const e=t.deltaY>0?-.02:.02,n=this.viewport.scale,i=Math.max(this.viewport.minScale,Math.min(n+e,this.viewport.maxScale)),s=this.canvas.getBoundingClientRect(),o=t.clientX-s.left,a=t.clientY-s.top,r=(o-this.viewport.offset.x)/n,h=(a-this.viewport.offset.y)/n;this.viewport.scale=i;const l=r*i+this.viewport.offset.x,d=h*i+this.viewport.offset.y;this.viewport.offset.x+=o-l,this.viewport.offset.y+=a-d,this.viewport.calculateBoundaries(),this.viewport.constrainViewport(),this.viewport.isInitialScale=this.viewport.scale===this.viewport.initialScale,this.renderCallback()}handleMouseDown(t){var e,n;if(0!==t.button)return;const i=this.getDrawType(),s=this.getBgImage();if(this.annotationManager.selectedAnnotation&&s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),void this.renderCallback()}if("text"===i){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if("rect"===(null==n?void 0:n.type))return this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(e);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();if(this.annotationManager.selectedAnnotation)return this.annotationManager.deselectAnnotation(),void this.renderCallback()}return null!==this.textManager.selectedTextIndex?(this.textManager.deselectTextAnnotation(),void this.renderCallback()):void this.handleTextModeClick(t)}if(!s)return;const o=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if("rect"===i){if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"rect"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.startRectDrawing(o)}else if("polygon"===i){if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e&&"polygon-vertex"===e.type)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"polygon"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.isDrawing?this.checkPolygonPointValid(o)&&this.annotationManager.addPolygonPoint(o):this.annotationManager.startPolygonDrawing(o),this.annotationManager.updatePolygonTempPoint(o),this.renderCallback()}else if("drag"===i){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback()}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(this.handleRectModeClick(t,o))return;if(this.handlePolygonModeClick(t,o))return;this.isDragging=!0,this.dragStart={x:t.clientX,y:t.clientY},this.canvas.style.cursor="grabbing"}else""===i&&this.handleNoModeClick(t,o)}handleTextModeClick(t){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.startMoving(t,e),this.canvas.style.cursor="grabbing",this.renderCallback(),!0;const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return this.textManager.addTextAnnotation(n.x,n.y),!0}handleRectModeClick(t,e){var n,i;if("rect"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"rect"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"rect"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handlePolygonModeClick(t,e){var n,i;if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n&&"polygon-vertex"===n.type)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"polygon"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"polygon"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handleNoModeClick(t,e){const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):v.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();this.textManager.deselectTextAnnotation();const i=this.annotationManager.getAnnotationAtPoint(e);i?(this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback()):this.annotationManager.deselectAnnotation()}checkPolygonPointValid(t){const e=this.annotationManager.operate.data.length>0?this.annotationManager.operate.data[this.annotationManager.operate.data.length-1]:null;return!e||Math.abs(e.point.x-t.x)>5||Math.abs(e.point.y-t.y)>5}handleMouseMove(t){if(!this.getBgImage())return;const e=this.getDrawType();if(this.isDragging&&"drag"===e){const e=t.clientX-this.dragStart.x,n=t.clientY-this.dragStart.y;return this.viewport.updateOffset(e,n),this.dragStart={x:t.clientX,y:t.clientY},void this.renderCallback()}if(this.textManager.isTextMoving&&null!==this.textManager.movingTextIndex)this.textManager.moveAnnotation(t)&&this.renderCallback();else if((this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&this.annotationManager.selectedAnnotation)this.handleAnnotationMove(t);else{if(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||this.updateCursor(t),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updateRectDrawing(e),this.renderCallback()}if("polygon"===e&&this.annotationManager.isDrawing){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updatePolygonTempPoint(e),this.renderCallback()}}}handleAnnotationMove(t){var e,n;if(this.annotationManager.isResizing&&this.annotationManager.activeHandle){const i=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return"rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)?this.annotationManager.resizeRect(i):"polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)&&this.annotationManager.resizePolygon(i),void this.renderCallback()}if(!this.annotationManager.isMovingAnnotation||!this.annotationManager.selectedAnnotation)return;const i=(t.clientX-this.annotationManager.annotationMoveStart.x)/this.viewport.scale,s=(t.clientY-this.annotationManager.annotationMoveStart.y)/this.viewport.scale;this.annotationManager.moveSelectedAnnotation(i,s),this.annotationManager.updateMoveStart({x:t.clientX,y:t.clientY}),this.renderCallback()}isHoverLockedAnnotation(t){return!(!t||!this.annotationManager.selectedAnnotation)&&(!0===this.annotationManager.selectedAnnotation.locked&&t.index===this.annotationManager.selectedAnnotation.index)}updateCursor(t){const e=this.getDrawType();if("text"===e){if(this.getBgImage()){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}const n=this.annotationManager.getAnnotationAtPoint(e);if(n)return void(this.canvas.style.cursor=this.isHoverLockedAnnotation(n)?"default":"move")}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);return void(this.canvas.style.cursor=null!==e?"move":"crosshair")}"rect"!==e?"polygon"!==e?"drag"!==e?""!==e?this.canvas.style.cursor="default":this.updateNoModeCursor(t):this.updateDragModeCursor(t):this.updatePolygonModeCursor(t):this.updateRectModeCursor(t)}updateRectModeCursor(t){var e;if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void(this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updatePolygonModeCursor(t){var e;if("polygon"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){if(this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="crosshair")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updateDragModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"grab"}updateNoModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"default"}handleMouseUp(t){if(this.isDragging){this.isDragging=!1;const t=this.getDrawType();return void(this.canvas.style.cursor="drag"===t?"grab":"default")}if(this.textManager.isTextMoving){this.justFinishedMove=!0,this.textManager.finishMoving();const t=this.getDrawType();"drag"===t?this.canvas.style.cursor="grab":""===t?this.canvas.style.cursor="move":(this.textManager.endTextMoving(),this.canvas.style.cursor="default")}(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&(this.justFinishedMove=!0,this.annotationManager.finishMovingAnnotation(),this.canvas.style.cursor=this.annotationManager.selectedAnnotation?"move":"default"),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type&&(this.annotationManager.finishRectDrawing(),this.renderCallback())}handleMouseLeave(t){(this.isDragging||this.textManager.isTextMoving||this.annotationManager.isResizing||this.annotationManager.isMovingAnnotation)&&this.handleMouseUp(t)}handleDoubleClick(t){if(!this.getBgImage())return;this.justFinishedMove=!1;const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return void this.textManager.startEditing(e);if(this.annotationManager.selectedAnnotation){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if(n&&n.index===this.annotationManager.selectedAnnotation.index)return void this.annotationManager.startTitleEditing(n.index)}if("polygon"===this.getDrawType()){if(this.annotationManager.isDrawing&&this.annotationManager.operate.data.length<=2)return;this.annotationManager.finishPolygonDrawing(),this.renderCallback()}}handleClick(t){var e;const n=this.getDrawType();!this.getBgImage()||"polygon"!==n||this.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||(this.justDeselected?this.justDeselected=!1:null===(e=this.annotationManager.selectedAnnotation)||void 0===e||e.type)}handleKeyDown(t){const e=t.target;if(!e||"INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName&&"SELECT"!==e.tagName&&!e.isContentEditable){if("z"===t.key&&(t.ctrlKey||t.metaKey)){return v.withdrawAll(this.annotationManager,this.textManager)&&this.notifyUndo(),void this.renderCallback()}if(" "===t.key)return this.viewport.resetToInitial(),void this.renderCallback();if("Escape"!==t.key){if("Delete"===t.key||"Backspace"===t.key){if(null!==this.textManager.editingTextIndex)return this.textManager.removeTextAnnotation(this.textManager.editingTextIndex),void this.renderCallback();if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.renderCallback();this.annotationManager.selectedAnnotation&&(this.annotationManager.deleteSelectedAnnotation(),this.renderCallback())}}else this.annotationManager.isDrawing?(this.annotationManager.cancelDrawing(),this.renderCallback()):this.annotationManager.selectedAnnotation&&(this.annotationManager.deselectAnnotation(),this.renderCallback())}}}class C{constructor(){this.listeners=new Map}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.delete(e)}emit(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.forEach(t=>t(e))}clear(){this.listeners.clear()}}class k{constructor(t){this.canvas=document.createElement("canvas"),this.emitter=new C,this.bgImage=null,this.bgImageSrc="",this.bgImageExt="jpeg",this.drawType="";const{drawType:e,useEvents:n=!0,id:i="container",annotationColor:s,lineStyle:o,vertexStyle:a,textStyle:r,enableTitle:l=!1,clampToImageBounds:d=!0}=t,c=document.getElementById(i);if(!c)throw new Error(`Container with id "${i}" not found`);this.container=c,"absolute"!==c.style.position&&"fixed"!==c.style.position&&"relative"!==c.style.position&&(c.style.position="relative"),this.ctx=this.canvas.getContext("2d"),this.viewport=new h,this.viewport.setSize(c.clientWidth,c.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.canvas.style.cursor="default",this.canvas.style.display="block",c.appendChild(this.canvas),this.annotationManager=new w(this.viewport,this.container,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),this.annotationManager.measureTitleWidth=(t,e)=>(this.ctx.font=e,this.ctx.measureText(t).width),s&&this.annotationManager.setColorConfig(s),o&&this.annotationManager.setLineStyle(o),a&&this.annotationManager.setVertexStyle(a),this.annotationManager.enableTitle=l,l&&this.annotationManager.initTitleSupport(),this.annotationManager.clampEnabled=d,this.textManager=new m(this.viewport,this.container,this.ctx,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),r&&this.textManager.setTextStyle(r),this.textManager.clampEnabled=d,this.renderer=new S(this.ctx,this.viewport,this.annotationManager,this.textManager),this.eventHandler=new b(this.canvas,this.viewport,this.annotationManager,this.textManager,this.renderer,()=>this.drawType,()=>this.bgImage,()=>this.render(),t=>this.setDrawType(t),()=>this.emitter.emit("undo",void 0)),this.events={wheel:t=>this.eventHandler.handleWheel(t),mousedown:t=>this.eventHandler.handleMouseDown(t),mousemove:t=>this.eventHandler.handleMouseMove(t),mouseup:t=>this.eventHandler.handleMouseUp(t),mouseleave:t=>this.eventHandler.handleMouseLeave(t),dblclick:t=>this.eventHandler.handleDoubleClick(t),click:t=>this.eventHandler.handleClick(t),keydown:t=>this.eventHandler.handleKeyDown(t)},this.setDrawType(e||""),n&&this.addEventListeners()}setDrawType(t){"polygon"===this.drawType&&this.annotationManager.isDrawing&&this.annotationManager.operate.data.length>0?console.warn("Cannot switch mode while polygon is being drawn. Please complete or cancel the polygon first."):this.drawType!==t&&(this.annotationManager.operate.data=[],this.annotationManager.isDrawing=!1,this.annotationManager.tempPolygonPoint=null,""!==t&&this.deselectAnnotation(),this.annotationManager.operate.type=t,this.drawType=t,this.canvas.style.cursor="drag"===t?"grab":"text"===t?"text":"default")}drawImage(t){this.bgImageSrc=t,this.bgImageExt=n(t);const e=new Image;e.crossOrigin="anonymous",e.src=t,e.onload=()=>{this.bgImage=e,this.viewport.setOriginalSize(e.width,e.height),this.viewport.calculateInitialView(),this.annotationManager.adjustTitlePositions(),this.render()}}render(){this.renderer.render(this.bgImage)}clear(t=""){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.setDrawType(t),this.render(),this.emitter.emit("clear",void 0)}withdraw(){const t=this.annotationManager.withdraw(),e=this.textManager.withdraw();(t||e)&&(this.render(),this.emitter.emit("undo",void 0))}resize(){const t=this.canvas.parentElement;t&&(this.viewport.setSize(t.clientWidth,t.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.render())}addEventListeners(){this.canvas.addEventListener("mousedown",this.events.mousedown),this.canvas.addEventListener("mousemove",this.events.mousemove),this.canvas.addEventListener("mouseup",this.events.mouseup),this.canvas.addEventListener("mouseleave",this.events.mouseleave),this.canvas.addEventListener("wheel",this.events.wheel),this.canvas.addEventListener("contextmenu",t=>t.preventDefault()),document.addEventListener("keydown",this.events.keydown),this.handleClickEventListener()}handleClickEventListener(){let t=null,e=0;this.canvas.addEventListener("click",n=>{if(this.eventHandler.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving)return;const i=this.eventHandler.justFinishedMove;i&&(this.eventHandler.justFinishedMove=!1),e++,1===e?t=window.setTimeout(()=>{1!==e||i||this.events.click(n),e=0,t=null},300):2===e&&(this.eventHandler.justFinishedMove=!1,this.events.dblclick(n),e=0,null!==t&&(clearTimeout(t),t=null))})}changeScale(t){if(!this.bgImage)return;const e=o(this.viewport.scale,t),n=this.viewport.width/2,i=this.viewport.height/2,s=this.viewport.scale+e;this.viewport.updateScale(s,n,i),this.render()}clearCanvas(t=!1,e=!0){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.textManager.deselectTextAnnotation(),this.emitter.emit("clear",void 0),!t&&e&&(this.bgImage=null,this.bgImageSrc="",this.viewport.setOriginalSize(0,0),this.viewport.reset()),this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.bgImage&&this.render(),"drag"===this.drawType&&(this.canvas.style.cursor="default")}clearAnnotations(){this.clearCanvas(!0,!1)}getAnnotations(){return this.annotationManager.getAnnotations()}getAnnotation(t){return this.annotationManager.getAnnotation(t)}getTextAnnotation(t){return this.textManager.getTextAnnotation(t)}on(t,e){this.emitter.on(t,e)}off(t,e){this.emitter.off(t,e)}setAnnotationTitle(t,e){const n=this.annotationManager.setTitle(t,e);return n&&this.render(),n}getAnnotationTitle(t){return this.annotationManager.getTitle(t)}setTitleStyle(t){this.annotationManager.setTitleStyle(t),this.render()}getTitleStyle(){return this.annotationManager.getTitleStyle()}setTitlePosition(t){this.annotationManager.setTitlePosition(t),this.render()}getTitlePosition(){return this.annotationManager.getTitlePosition()}setAnnotationTitleStyle(t,e){const n=this.annotationManager.setAnnotationTitleStyle(t,e);return n&&this.render(),n}setAnnotationTitlePosition(t,e){const n=this.annotationManager.setAnnotationTitlePosition(t,e);return n&&this.render(),n}getTextAnnotations(){return this.textManager.getTextAnnotations()}exportAnnotationImage(){return new Promise((t,e)=>{if(!this.bgImage)return void e(new Error("No background image loaded"));const n=document.createElement("canvas");n.width=this.viewport.originalWidth,n.height=this.viewport.originalHeight;const i=n.getContext("2d");if(!i)return void e(new Error("Could not create offscreen canvas context"));const s=new Image;s.src=this.bgImageSrc,s.crossOrigin="anonymous",s.onload=()=>{try{this.renderer.drawForExport(i,s,this.viewport.originalWidth,this.viewport.originalHeight);const e=n.toDataURL(`image/${this.bgImageExt}`,.7);t(e)}catch(n){this.exportCurrentViewImage().then(t).catch(t=>e(new Error(`Both methods failed: ${t.message}`)))}},s.onerror=()=>{e(new Error("Failed to load image for export"))}})}exportCurrentViewImage(){return new Promise((t,e)=>{try{t(this.canvas.toDataURL(`image/${this.bgImageExt}`))}catch(t){e(new Error(`Failed to export current view: ${t.message}`))}})}base64ToFile(t,e){return i(t,e)}static base64ToBlob(t){return s(t)}addTextAnnotation(t,e,n=""){this.textManager.addTextAnnotation(t,e,n),this.render()}updateTextAnnotation(t,e){this.textManager.updateTextAnnotation(t,e)&&this.render()}moveTextAnnotation(t,e,n){this.textManager.moveTextAnnotation(t,e,n)&&this.render()}removeTextAnnotation(t){this.textManager.removeTextAnnotation(t)&&this.render()}clearTextAnnotations(){this.textManager.clearTextAnnotations(),this.render()}selectAnnotation(t,e){this.annotationManager.selectAnnotation(t,e)&&this.render()}deselectAnnotation(){this.annotationManager.deselectAnnotation(),this.textManager.deselectTextAnnotation(),this.textManager.editingTextIndex=null,this.render()}getSelectedAnnotation(){const t=this.annotationManager.getSelectedAnnotation();if(t)return t;const e=this.textManager.getSelectedTextAnnotation();return e?{index:e.index,type:"text",data:e.data}:null}deleteSelectedAnnotation(){if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.render();this.annotationManager.deleteSelectedAnnotation()&&this.render()}moveSelectedAnnotation(t,e){if(this.annotationManager.moveSelectedAnnotation(t,e)){const t=this.annotationManager.selectedAnnotation;t&&this.annotationManager.notifyUpdate(t.index),this.render()}}setAnnotationColor(t){this.annotationManager.setColorConfig(t),this.render()}getAnnotationColor(){return this.annotationManager.getColorConfig()}updateSelectedAnnotationStyle(t){if(void 0!==t){const e=this.annotationManager.updateAnnotationStyle(t);return e&&this.render(),e}const e=this.annotationManager.selectedAnnotation;if(!e)return!1;const n=this.annotationManager.recordList[e.index];return!!n&&(n.style=this.annotationManager.getCurrentStyle(),this.annotationManager.notifyUpdate(e.index),this.render(),!0)}setLineStyle(t){this.annotationManager.setLineStyle(t),this.render()}getLineStyle(){return this.annotationManager.getLineStyle()}setVertexStyle(t){this.annotationManager.setVertexStyle(t),this.render()}getVertexStyle(){return this.annotationManager.getVertexStyle()}setTextStyle(t){this.textManager.setTextStyle(t),this.render()}updateTextAnnotationStyle(t,e){const n=this.textManager.updateTextAnnotationStyle(t,e);return n&&this.render(),n}setTextInputStyle(t){this.textManager.setInputStyle(t)}setTextSelectionStyle(t){this.textManager.setSelectionStyle(t),this.render()}destroy(){this.emitter.clear(),document.removeEventListener("keydown",this.events.keydown),this.textManager.destroy(),this.annotationManager.destroyTitleInput(),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}export{w as AnnotationManager,k as Drawer,C as Emitter,b as EventHandler,S as Renderer,m as TextAnnotationManager,h as ViewportManager,s as base64ToBlob,i as base64ToFile,k as default,n as getImageTypeFromUrl,o as getZoomDelta,e as isPointInPolygon,t as isPointInRect};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ImageAnnotationDrawer=t.ImageAnnotationDrawer||{})}(this,function(t){"use strict";function e(t,e){const n=e.width>=0?e.start.x:e.start.x+e.width,i=e.height>=0?e.start.y:e.start.y+e.height,s=Math.abs(e.width),o=Math.abs(e.height);return t.x>=n&&t.x<=n+s&&t.y>=i&&t.y<=i+o}function n(t,e){if(e.length<3)return!1;let n=!1;for(let i=0,s=e.length-1;i<e.length;s=i++){const o=e[i].point.x,a=e[i].point.y,r=e[s].point.x,h=e[s].point.y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n}function i(t){try{const e=new URL(t).pathname.toLowerCase();return e.endsWith(".png")?"png":e.endsWith(".jpg")?"jpg":e.endsWith(".jpeg")?"jpeg":e.endsWith(".webp")?"webp":e.endsWith(".gif")?"gif":e.endsWith(".bmp")?"bmp":e.endsWith(".svg")?"svg":"jpeg"}catch(t){return"jpeg"}}function s(t,e){const n=t.split(";base64,"),i=n[0].split(":")[1],s=window.atob(n[1]),o=s.length,a=new Uint8Array(o);for(let t=0;t<o;++t)a[t]=s.charCodeAt(t);const r=new Blob([a],{type:i});return new File([r],e,{type:i})}function o(t){return new Promise((e,n)=>{const i=t.split(";base64,");if(i.length<2)return void n(new Error("Invalid base64 string"));const s=i[0].split(":")[1],o=atob(i[1]),a=new ArrayBuffer(o.length),r=new Uint8Array(a);for(let t=0;t<o.length;t++)r[t]=o.charCodeAt(t);e(new Blob([a],{type:s}))})}function a(t,e){return t<2?e?.1:-.1:t<5?e?.05:-.05:e?.02:-.02}function r(t){return"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t))}function h(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():`id-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}class l{constructor(){this.width=0,this.height=0,this.originalWidth=0,this.originalHeight=0,this.scale=1,this.minScale=1,this.maxScale=10,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}setSize(t,e){this.width=t,this.height=e}setOriginalSize(t,e){this.originalWidth=t,this.originalHeight=e}calculateInitialView(){if(0===this.originalWidth||0===this.originalHeight)return;const t=this.width/this.originalWidth,e=this.height/this.originalHeight;this.scale=Math.min(t,e),this.initialScale=this.scale,this.minScale=this.initialScale,this.offset={x:(this.width-this.originalWidth*this.scale)/2,y:(this.height-this.originalHeight*this.scale)/2},this.initialOffset=Object.assign({},this.offset),this.calculateBoundaries(),this.isInitialScale=!0}calculateBoundaries(){const t=this.originalWidth*this.scale,e=this.originalHeight*this.scale;this.maxOffsetX=0,this.maxOffsetY=0,this.minOffsetX=this.width-t,this.minOffsetY=this.height-e,this.minOffsetX>this.maxOffsetX&&([this.minOffsetX,this.maxOffsetX]=[this.maxOffsetX,this.minOffsetX]),this.minOffsetY>this.maxOffsetY&&([this.minOffsetY,this.maxOffsetY]=[this.maxOffsetY,this.minOffsetY])}constrainViewport(){this.offset.x>this.maxOffsetX?this.offset.x=this.maxOffsetX:this.offset.x<this.minOffsetX&&(this.offset.x=this.minOffsetX),this.offset.y>this.maxOffsetY?this.offset.y=this.maxOffsetY:this.offset.y<this.minOffsetY&&(this.offset.y=this.minOffsetY)}toImageCoordinates(t,e){return{x:(t-this.offset.x)/this.scale,y:(e-this.offset.y)/this.scale}}toCanvasCoordinates(t,e){return{x:this.offset.x+t*this.scale,y:this.offset.y+e*this.scale}}updateScale(t,e,n){const i=this.scale,s=(e-this.offset.x)/i,o=(n-this.offset.y)/i;this.scale=Math.max(this.minScale,Math.min(t,this.maxScale));const a=s*this.scale+this.offset.x,r=o*this.scale+this.offset.y;this.offset.x+=e-a,this.offset.y+=n-r,this.calculateBoundaries(),this.constrainViewport(),this.isInitialScale=this.scale===this.initialScale}resetToInitial(){this.scale=this.initialScale,this.offset=Object.assign({},this.initialOffset),this.calculateBoundaries(),this.isInitialScale=!0}updateOffset(t,e){this.offset.x+=t,this.offset.y+=e,this.constrainViewport()}reset(){this.scale=1,this.minScale=1,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}}const d={minX:Number.NEGATIVE_INFINITY,minY:Number.NEGATIVE_INFINITY,maxX:Number.POSITIVE_INFINITY,maxY:Number.POSITIVE_INFINITY};function c(t,e,n){return Math.min(Math.max(t,e),n)}function g(t){var e,n,i,s;const{anchor:o,boxWidth:a,boxHeight:r,position:h}=t,l=null!==(e=t.bounds)&&void 0!==e?e:d,g=null!==(n=t.gap)&&void 0!==n?n:4,x=null!==(i=h.offsetX)&&void 0!==i?i:0,u=null!==(s=h.offsetY)&&void 0!==s?s:0,f=h.align||"center";let p;switch(f){case"left":p=o.x+x;break;case"right":p=o.x+o.width-a+x;break;default:p=o.x+o.width/2-a/2+x}const y=c(p,l.minX,Math.max(l.minX,l.maxX-a)),v=x+(y-p),M=h.vertical||"top";let w,m=M;return"inside-top"===M?w=o.y+g+u:"bottom"===M?(w=o.y+o.height+g+u,w+r>l.maxY&&(m="top",w=o.y-r-g+u)):(w=o.y-r-g+u,w<l.minY&&(m="bottom",w=o.y+o.height+g+u)),w=c(w,l.minY,Math.max(l.minY,l.maxY-r)),{x:y,y:w,vertical:m,align:f,offsetX:v}}function x(t){const{x:e,y:n}=g(t);return{x:e,y:n}}function u(t,e){if("polygon"===t.type){const n=t.data;if(0===n.length)return null;let i=1/0,s=1/0,o=-1/0,a=-1/0;return n.forEach(t=>{const n=e?e.offset.x+t.point.x*e.scale:t.point.x,r=e?e.offset.y+t.point.y*e.scale:t.point.y;n<i&&(i=n),r<s&&(s=r),n>o&&(o=n),r>a&&(a=r)}),{x:i,y:s,width:o-i,height:a-s}}const n=t.data[0];return e?{x:e.offset.x+n.start.x*e.scale,y:e.offset.y+n.start.y*e.scale,width:n.width*e.scale,height:n.height*e.scale}:{x:n.start.x,y:n.start.y,width:n.width,height:n.height}}function f(t,e,n){if(!n)return e;const{originalWidth:i,originalHeight:s}=t;return i&&s?{x:Math.max(0,Math.min(e.x,i)),y:Math.max(0,Math.min(e.y,s))}:e}function p(t,e,n,i,s){t&&s.id&&t(n,{id:s.id,type:e,index:i,data:r(s)})}const y=new class{constructor(){this.type="rect"}startDrawing(t,e){t.isDrawing=!0,t.drawStartPoint=e,t.operate={type:"rect",data:[{start:Object.assign({},e),width:0,height:0}],status:"pending"}}updateDrawing(t,e){if(!t.isDrawing||"rect"!==t.operate.type)return;const n=t.operate.data[0];n.width=e.x-t.drawStartPoint.x,n.height=e.y-t.drawStartPoint.y}addPoint(t,e){return!1}finishDrawing(t){if(!t.isDrawing||"rect"!==t.operate.type)return!1;const e=t.operate.data[0];return Math.abs(e.width)>5&&Math.abs(e.height)>5&&t.pushRecord(Object.assign({},t.operate)),t.operate.data=[],t.isDrawing=!1,!0}cancelDrawing(t){t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data=[],t.isDrawing=!1,!0)}hitTest(t,n){return e(n,t.data[0])}getHandles(t,e,n){const i=t.data[0],s=e.offset.x+i.start.x*e.scale,o=e.offset.y+i.start.y*e.scale,a=i.width*e.scale,r=i.height*e.scale;return[{x:s,y:o,index:0},{x:s+a,y:o,index:1},{x:s,y:o+r,index:2},{x:s+a,y:o+r,index:3}]}move(t,e,n){const i=t.data[0];i.start.x+=e,i.start.y+=n}snapshotForResize(t){const e=t.data[0];return{start:Object.assign({},e.start),width:e.width,height:e.height}}resize(t,e,n,i){const s=t.data[0],o=i,a=o.start.x,r=o.start.x+o.width,h=o.start.y,l=o.start.y+o.height;let d,c;switch(e){case 0:d=r,c=l;break;case 1:d=a,c=l;break;case 2:d=r,c=h;break;case 3:d=a,c=h;break;default:return}const g=Math.min(n.x,d),x=Math.max(n.x,d),u=Math.min(n.y,c),f=Math.max(n.y,c);s.start.x=g,s.start.y=u,s.width=x-g,s.height=f-u;const p=n.x<d,y=n.y<c;let v;return 0===e?p||y?!p&&y?v=1:p&&!y&&(v=2):v=3:1===e?p&&!y?v=2:p&&y?v=0:p||y||(v=3):2===e?!p&&y?v=1:p&&y?v=0:p||y||(v=3):3===e&&(p&&y?v=0:!p&&y?v=1:p&&!y&&(v=2)),o.start.x=s.start.x,o.start.y=s.start.y,o.width=s.width,o.height=s.height,v}getBounds(t){const e=t.data[0];return{x:e.start.x,y:e.start.y,width:e.width,height:e.height}}};const v=new class{constructor(){this.type="polygon"}startDrawing(t,e){t.isDrawing=!0,t.operate={type:"polygon",data:[{point:e}],status:"pending"},t.tempPolygonPoint=e}updateDrawing(t,e){t.tempPolygonPoint=e}addPoint(t,e){if(!t.isDrawing||"polygon"!==t.operate.type)return!1;const n=t.operate.data.length>0?t.operate.data[t.operate.data.length-1]:null;return!(n&&Math.abs(n.point.x-e.x)<=5&&Math.abs(n.point.y-e.y)<=5)&&(t.operate.data.push({point:e}),!0)}finishDrawing(t){return!(!t.isDrawing||"polygon"!==t.operate.type)&&(t.operate.data.length>=3&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate={type:"polygon",data:[],status:"pending"},t.isDrawing=!1,t.tempPolygonPoint=null,!0)}cancelDrawing(t){t.isDrawing&&"polygon"===t.operate.type&&t.operate.data.length>=2&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data.pop(),0===t.operate.data.length&&(t.isDrawing=!1),!0)}hitTest(t,e){return n(e,t.data)}getHandles(t,e,n){const i=t.data,s=[];for(let t=0;t<i.length;t++){const n=i[t];s.push({x:e.offset.x+n.point.x*e.scale,y:e.offset.y+n.point.y*e.scale,index:t})}return s}move(t,e,n){t.data.forEach(t=>{t.point.x+=e,t.point.y+=n})}snapshotForResize(t){return t.data.map(t=>({point:Object.assign({},t.point)}))}resize(t,e,n,i){const s=t.data;e>=0&&e<s.length&&(s[e].point.x=n.x,s[e].point.y=n.y)}getBounds(t){const e=t.data;if(0===e.length)return{x:0,y:0,width:0,height:0};let n=1/0,i=1/0,s=-1/0,o=-1/0;return e.forEach(t=>{t.point.x<n&&(n=t.point.x),t.point.y<i&&(i=t.point.y),t.point.x>s&&(s=t.point.x),t.point.y>o&&(o=t.point.y)}),{x:n,y:i,width:s-n,height:o-i}}};const M=new class{constructor(){this.strategies=new Map}register(t){this.strategies.set(t.type,t)}get(t){const e=this.strategies.get(t);if(!e)throw new Error(`No strategy registered for shape type: ${t}`);return e}selectShapeExclusive(t,e,n){return"shape"===n.kind?(e.deselectTextAnnotation(),t.selectAnnotation(n.ref,{lock:n.locked})):(t.deselectAnnotation(),e.selectTextAnnotation(n.index))}deselectAll(t,e){t.deselectAnnotation(),e.deselectTextAnnotation()}withdrawAll(t,e){return t.withdraw()||e.withdraw()}};M.register(y),M.register(v);class w{constructor(t,e,n,i){this.viewport=t,this.container=e,this.renderCallback=n,this.changeCallback=i,this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.drawStartPoint={x:0,y:0},this.tempPolygonPoint=null,this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.annotationMoveStart={x:0,y:0},this.originalRect=null,this.originalPolygon=null,this.deleteHistory=[],this.editingTitleIndex=null,this.titleInput=null,this.strokeStyle="red",this.lineWidth=5,this.lineStyle="solid",this.vertexStyle={size:8,fillColor:"red",strokeColor:"white",strokeWidth:2,shape:"circle"},this.selectionStyle={strokeColor:"#00D9FF",fillColor:"rgba(0,217,255,0.15)",handleSize:12,handleColor:"#00D9FF"},this.colorConfig={rect:"red",polygon:"red",default:"red"},this.titleStyle={font:"12px Arial",color:"#FFFFFF",backgroundColor:"rgba(0, 0, 0, 0.7)",paddingX:6,paddingY:3,borderRadius:4,placeholder:"输入标题..."},this.titlePosition={vertical:"top",align:"center",offsetX:0,offsetY:0},this.enableTitle=!1,this.clampEnabled=!0,this.applyColorConfig()}strategyOf(t){return M.get(t)}clamp(t){return f(this.viewport,t,this.clampEnabled)}clampToImageBounds(t){return f(this.viewport,t,this.clampEnabled)}clampRecordToImageBounds(t){if(!this.clampEnabled)return;const{originalWidth:e,originalHeight:n}=this.viewport;if(!e||!n)return;if("rect"===t.type){const i=t.data[0];if(!i)return;const s=Math.min(i.start.x,i.start.x+i.width),o=Math.max(i.start.x,i.start.x+i.width),a=Math.min(i.start.y,i.start.y+i.height),r=Math.max(i.start.y,i.start.y+i.height);if(s>=0&&a>=0&&o<=e&&r<=n)return;const h=Math.min(o-s,e),l=Math.min(r-a,n);return i.start.x=Math.max(0,Math.min(s,e-h)),i.start.y=Math.max(0,Math.min(a,n-l)),i.width=h,void(i.height=l)}const i=t.data;if(!i||0===i.length)return;let s=1/0,o=1/0,a=-1/0,r=-1/0;for(const t of i)s=Math.min(s,t.point.x),a=Math.max(a,t.point.x),o=Math.min(o,t.point.y),r=Math.max(r,t.point.y);let h=0,l=0;if(a-s>e||s<0?h=-s:a>e&&(h=e-a),r-o>n||o<0?l=-o:r>n&&(l=n-r),0!==h||0!==l)for(const t of i)t.point.x+=h,t.point.y+=l}pushRecord(t){const e=Object.assign(Object.assign({},t),{id:h(),style:this.getCurrentStyle()});this.recordList.push(e),this.deleteHistory=[],this.notifyChange("create",this.recordList.length-1,e)}initTitleSupport(){this.container&&this.enableTitle&&this.createTitleInput()}setColorConfig(t){this.colorConfig="string"==typeof t?{rect:t,polygon:t,default:t}:Object.assign(Object.assign({},this.colorConfig),t),this.applyColorConfig()}getColorConfig(){return Object.assign({},this.colorConfig)}applyColorConfig(){this.strokeStyle=this.colorConfig.default||"red"}getColorForType(t){return this.colorConfig[t]||this.colorConfig.default||"red"}getCurrentStyle(){return{strokeColor:this.strokeStyle,lineWidth:this.lineWidth,lineStyle:this.lineStyle,vertexStyle:Object.assign({},this.vertexStyle)}}notifyChange(t,e,n){p(this.changeCallback,n.type,t,e,n)}notifyUpdate(t){const e=this.recordList[t];e&&this.notifyChange("update",t,e)}resolveIndex(t){return"number"==typeof t?t:this.recordList.findIndex(e=>e.id===t)}getAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return r(this.recordList[e])}updateAnnotationStyle(t){const e=this.resolveIndex(t);return!(e<0||e>=this.recordList.length)&&(this.recordList[e].style=this.getCurrentStyle(),this.notifyUpdate(e),!0)}setLineStyle(t){this.lineStyle=t}setVertexStyle(t){this.vertexStyle=Object.assign(Object.assign({},this.vertexStyle),t),t.fillColor&&(this.strokeStyle=t.fillColor)}getLineStyle(){return this.lineStyle}getVertexStyle(){return Object.assign({},this.vertexStyle)}getAnnotationStyle(t){return t.style||this.getCurrentStyle()}withdraw(){if(this.operate.data.length>0){const t="polygon"===this.operate.type?"polygon":"rect";return this.strategyOf(t).withdrawInProgress(this),!0}if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.recordList.splice(e,0,t),!0}return this.recordList.length>0&&(this.recordList.pop(),!0)}selectAnnotation(t,e){var n;const i=this.resolveIndex(t);if(i<0||i>=this.recordList.length)return this.deselectAnnotation(),!1;const s=this.recordList[i],o=void 0!==(null==e?void 0:e.lock)?!!e.lock:(null===(n=this.selectedAnnotation)||void 0===n?void 0:n.index)===i&&!0===this.selectedAnnotation.locked;return this.selectedAnnotation={index:i,type:s.type,locked:o},!0}deselectAnnotation(){this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null}deleteSelectedAnnotation(){if(!this.selectedAnnotation)return!1;const t=this.selectedAnnotation.index,e=this.recordList[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.recordList.splice(t,1),this.deselectAnnotation(),this.notifyChange("delete",t,e),!0}startMovingAnnotation(t){return!(!this.selectedAnnotation||!0===this.selectedAnnotation.locked)&&(this.isMovingAnnotation=!0,this.annotationMoveStart={x:t.clientX,y:t.clientY},!0)}updateMoveStart(t){this.annotationMoveStart=t}finishMovingAnnotation(){const t=this.isMovingAnnotation||this.isResizing;this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null,t&&this.selectedAnnotation&&this.notifyUpdate(this.selectedAnnotation.index)}clear(){this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.tempPolygonPoint=null,this.deselectAnnotation(),this.deleteHistory=[]}getAnnotations(){return this.recordList.map(t=>r(t))}getSelectedAnnotation(){if(!this.selectedAnnotation)return null;const t=this.recordList[this.selectedAnnotation.index];return t?{index:this.selectedAnnotation.index,type:this.selectedAnnotation.type,data:r(t)}:null}setTitleStyle(t){this.titleStyle=Object.assign(Object.assign({},this.titleStyle),t)}getTitleStyle(){return Object.assign({},this.titleStyle)}setTitlePosition(t){this.titlePosition=Object.assign(Object.assign({},this.titlePosition),t)}getTitlePosition(){return Object.assign({},this.titlePosition)}getEffectiveTitleStyle(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titleStyle),e.titleStyle||{})}getEffectiveTitlePosition(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titlePosition),e.titlePosition||{})}captureTitleStyleSnapshot(t){t.style||(t.style=this.getCurrentStyle()),t.style.titleStyle=Object.assign({},this.titleStyle),t.style.titlePositionExplicit||(t.style.titlePosition=Object.assign({},this.titlePosition))}autoAdjustTitlePosition(t,e){var n,i,s;if(!e||(null===(n=t.style)||void 0===n?void 0:n.titlePositionExplicit))return;const{originalWidth:o,originalHeight:a,initialScale:r,scale:h}=this.viewport;if(o<=0||a<=0)return;const l=u(t);if(!l)return;const d=r>0?r:h>0?h:1,c={x:l.x*d,y:l.y*d,width:l.width*d,height:l.height*d},x=this.getEffectiveTitleStyle(t),f=x.font||"12px Arial",p=f.match(/(\d+)px/),y=(p?parseInt(p[1]):12)+2*(null!==(i=x.paddingY)&&void 0!==i?i:3),v=this.measureTitleWidth,M=v?{minX:0,minY:0,maxX:o*d,maxY:a*d}:{minX:Number.NEGATIVE_INFINITY,minY:0,maxX:Number.POSITIVE_INFINITY,maxY:a*d},w=v?v(e,f)+2*(null!==(s=x.paddingX)&&void 0!==s?s:6):0,m=Object.assign({},this.titlePosition),A=g({anchor:c,boxWidth:w,boxHeight:y,position:m,bounds:M});t.style||(t.style=this.getCurrentStyle()),t.style.titlePosition=Object.assign(Object.assign({},m),{vertical:A.vertical,align:A.align,offsetX:A.offsetX})}adjustTitlePositions(){this.viewport.originalWidth<=0||this.viewport.originalHeight<=0||this.recordList.forEach(t=>{var e;t.title&&!(null===(e=t.style)||void 0===e?void 0:e.titlePositionExplicit)&&this.autoAdjustTitlePosition(t,t.title)})}setAnnotationTitleStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titleStyle=Object.assign(Object.assign({},i.style.titleStyle||this.titleStyle),e),this.notifyUpdate(n),!0}setAnnotationTitlePosition(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titlePosition=Object.assign(Object.assign({},i.style.titlePosition||this.titlePosition),e),i.style.titlePositionExplicit=!0,this.notifyUpdate(n),!0}createTitleInput(){this.container&&(this.titleInput=document.createElement("input"),this.titleInput.type="text",this.titleInput.style.position="absolute",this.titleInput.style.zIndex="99998",this.titleInput.style.display="none",this.titleInput.style.outline="none",this.titleInput.style.border="1px solid #00D9FF",this.titleInput.style.borderRadius="4px",this.titleInput.style.padding="4px 8px",this.titleInput.style.fontSize="13px",this.titleInput.style.fontFamily="Arial, sans-serif",this.titleInput.style.backgroundColor="#ffffff",this.titleInput.style.color="#333",this.titleInput.style.boxShadow="0 2px 8px rgba(0,0,0,0.3)",this.titleInput.style.minWidth="80px",this.titleInput.style.maxWidth="200px",this.titleInput.placeholder=this.titleStyle.placeholder||"输入标题...",this.titleInput.addEventListener("blur",()=>{this.finishTitleEditing()}),this.titleInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?this.finishTitleEditing():"Escape"===t.key&&(t.preventDefault(),this.cancelTitleEditing())}),this.container.appendChild(this.titleInput))}setTitle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.title=e||void 0,e&&(this.captureTitleStyleSnapshot(i),this.autoAdjustTitlePosition(i,e)),this.notifyUpdate(n),!0}getTitle(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return this.recordList[e].title}startTitleEditing(t){if(!this.enableTitle||!this.titleInput||t<0||t>=this.recordList.length)return!1;const e=this.recordList[t];let n,i;if(this.editingTitleIndex=t,this.deselectAnnotation(),"rect"===e.type){const t=e.data[0];n=this.viewport.offset.x+t.start.x*this.viewport.scale,i=this.viewport.offset.y+t.start.y*this.viewport.scale}else{const t=e.data[0];n=this.viewport.offset.x+t.point.x*this.viewport.scale,i=this.viewport.offset.y+t.point.y*this.viewport.scale}return this.titleInput.value=e.title||"",this.titleInput.placeholder=this.getEffectiveTitleStyle(e).placeholder||"输入标题...",this.titleInput.style.left=`${n}px`,this.titleInput.style.top=i-32+"px",this.titleInput.style.display="block",setTimeout(()=>{this.titleInput&&(this.titleInput.focus(),this.titleInput.select())},10),!0}finishTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex,e=this.titleInput.value.trim();if(t>=0&&t<this.recordList.length){const n=this.recordList[t];n.title=e||void 0,e&&(this.captureTitleStyleSnapshot(n),this.autoAdjustTitlePosition(n,e)),this.notifyUpdate(t),this.selectAnnotation(t)}return this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}cancelTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex;return t>=0&&t<this.recordList.length&&this.selectAnnotation(t),this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}resetTitleEditingState(){this.titleInput&&(this.titleInput.style.display="none"),this.editingTitleIndex=null}destroyTitleInput(){this.titleInput&&this.titleInput.parentNode&&(this.titleInput.parentNode.removeChild(this.titleInput),this.titleInput=null)}}class m extends w{startRectDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("rect").startDrawing(this,t)}updateRectDrawing(t){this.isDrawing&&"rect"===this.operate.type&&(t=this.clampToImageBounds(t),this.strategyOf("rect").updateDrawing(this,t))}finishRectDrawing(){return this.strategyOf("rect").finishDrawing(this)}startPolygonDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("polygon").startDrawing(this,t)}addPolygonPoint(t){return!(!this.isDrawing||"polygon"!==this.operate.type)&&(t=this.clampToImageBounds(t),this.strategyOf("polygon").addPoint(this,t))}updatePolygonTempPoint(t){this.strategyOf("polygon").updateDrawing(this,this.clampToImageBounds(t))}finishPolygonDrawing(){return this.strategyOf("polygon").finishDrawing(this)}cancelDrawing(){const t="polygon"===this.operate.type?"polygon":"rect";this.strategyOf(t).cancelDrawing(this)}moveSelectedAnnotation(t,e){if(!this.selectedAnnotation)return!1;const n=this.recordList[this.selectedAnnotation.index];return!!n&&(this.strategyOf(n.type).move(n,t,e),this.clampRecordToImageBounds(n),!0)}startResizing(t,e){if(!this.selectedAnnotation)return!1;this.activeHandle=t,this.isResizing=!0;const n=this.recordList[this.selectedAnnotation.index];return"rect"===n.type?this.originalRect=this.strategyOf("rect").snapshotForResize(n):"polygon"===n.type&&(this.originalPolygon=this.strategyOf("polygon").snapshotForResize(n)),!0}resizeRect(t){if(!this.selectedAnnotation||"rect"!==this.selectedAnnotation.type||!this.originalRect||!this.activeHandle)return!1;if(this.activeHandle.index<0||this.activeHandle.index>3)return!1;const e=this.recordList[this.selectedAnnotation.index],n=this.clampToImageBounds(t),i=this.strategyOf("rect").resize(e,this.activeHandle.index,n,this.originalRect);return"number"==typeof i&&(this.activeHandle.index=i),!0}resizePolygon(t){var e;if(!this.selectedAnnotation||"polygon"!==this.selectedAnnotation.type||!this.activeHandle)return!1;const n=this.recordList[this.selectedAnnotation.index],i=this.activeHandle.index,s=n.data;return!(i<0||i>=s.length)&&(this.strategyOf("polygon").resize(n,i,this.clampToImageBounds(t),null!==(e=this.originalPolygon)&&void 0!==e?e:[]),!0)}getAnnotationAtPoint(t){for(let e=this.recordList.length-1;e>=0;e--){const n=this.recordList[e],i=n.type;if(this.strategyOf(i).hitTest(n,t))return{index:e,type:i}}return null}getHandleAtPoint(t,e){if(!this.selectedAnnotation)return null;if(!0===this.selectedAnnotation.locked)return null;const n=this.recordList[this.selectedAnnotation.index],i=this.selectionStyle.handleSize,s=i/2,o=this.selectedAnnotation.type,a=this.strategyOf(o).getHandles(n,this.viewport,i);for(const n of a)if(t>=n.x-s&&t<=n.x+s&&e>=n.y-s&&e<=n.y+s)return"rect"===o?{type:"rect-corner",index:n.index}:{type:"polygon-vertex",index:n.index};return null}}class A{constructor(t,e,n,i,s){this.viewport=t,this.container=e,this.ctx=n,this.renderCallback=i,this.changeCallback=s,this.textAnnotations=[],this.editingTextIndex=null,this.currentEditingIndex=null,this.movingTextIndex=null,this.isTextMoving=!1,this.textMoveStart={x:0,y:0},this.textBeforeEditing="",this.selectedTextIndex=null,this.clampEnabled=!0,this.textInput=null,this.deleteHistory=[],this.defaultInputStyle={border:"2px solid #00D9FF",borderRadius:"6px",padding:"6px 10px",fontSize:"16px",fontFamily:"Arial, sans-serif",backgroundColor:"#ffffff",color:"#333",boxShadow:"0 4px 12px rgba(0,0,0,0.3)",minWidth:"60px",maxWidth:"200px"},this.textStyle={font:"16px Arial",color:"#FFD700",padding:6,backgroundColor:"rgba(0,0,0,0.6)",borderRadius:4,selectedBorderColor:"#00D9FF",selectedBackgroundColor:"rgba(0,217,255,0.15)",inputStyle:Object.assign({},this.defaultInputStyle)},this.createTextInput()}createTextInput(){this.textInput=document.createElement("input"),this.textInput.type="text",this.textInput.style.position="absolute",this.textInput.style.zIndex="99999",this.textInput.style.display="none",this.textInput.style.outline="none",this.textInput.style.width="fit-content",this.textInput.placeholder="输入文字...",this.applyInputStyle(),this.textInput.addEventListener("blur",()=>{this.finishEditing(),this.renderCallback&&this.renderCallback()}),this.textInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?(this.finishEditing(),this.renderCallback&&this.renderCallback()):"Escape"===t.key?(t.preventDefault(),this.cancelEditing()):"Delete"===t.key&&""===this.textInput.value&&(t.preventDefault(),this.deleteEditingAnnotation())}),this.textInput.addEventListener("input",()=>{this.adjustInputWidth()}),this.container.appendChild(this.textInput)}applyInputStyle(){if(!this.textInput)return;const t=Object.assign(Object.assign({},this.defaultInputStyle),this.textStyle.inputStyle);this.textInput.style.border=t.border,this.textInput.style.borderRadius=t.borderRadius,this.textInput.style.padding=t.padding,this.textInput.style.fontSize=t.fontSize,this.textInput.style.fontFamily=t.fontFamily,this.textInput.style.backgroundColor=t.backgroundColor,this.textInput.style.color=t.color,this.textInput.style.boxShadow=t.boxShadow,this.textInput.style.minWidth=t.minWidth,this.textInput.style.maxWidth=t.maxWidth}setTextStyle(t){this.textStyle=Object.assign(Object.assign({},this.textStyle),t),this.applyInputStyle()}setInputStyle(t){this.textStyle.inputStyle=Object.assign(Object.assign({},this.textStyle.inputStyle),t),this.applyInputStyle()}setSelectionStyle(t){void 0!==t.selectedBorderColor&&(this.textStyle.selectedBorderColor=t.selectedBorderColor),void 0!==t.selectedBackgroundColor&&(this.textStyle.selectedBackgroundColor=t.selectedBackgroundColor)}getCurrentStyle(){return{font:this.textStyle.font,color:this.textStyle.color,backgroundColor:this.textStyle.backgroundColor}}notifyChange(t,e,n){p(this.changeCallback,"text",t,e,n)}resolveIndex(t){return"number"==typeof t?t:this.textAnnotations.findIndex(e=>e.id===t)}getTextAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.textAnnotations.length))return r(this.textAnnotations[e])}updateTextAnnotationStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];return i.style=Object.assign(Object.assign({},i.style||this.getCurrentStyle()),e),this.notifyChange("update",n,this.textAnnotations[n]),!0}clampToImageBounds(t){return f(this.viewport,t,this.clampEnabled)}addTextAnnotation(t,e,n=""){var i;const s=this.clampToImageBounds({x:t,y:e});t=s.x,e=s.y,this.ctx.font=this.textStyle.font;const o=n||"输入文字...",a=this.ctx.measureText(o);let r;if(a.actualBoundingBoxAscent&&a.actualBoundingBoxDescent)r=a.actualBoundingBoxAscent+a.actualBoundingBoxDescent;else{r=1.2*parseInt((null===(i=this.textStyle.font.match(/\d+/))||void 0===i?void 0:i[0])||"16")}const l={id:h(),position:{x:t,y:e},text:n,style:this.getCurrentStyle(),width:Math.max(a.width,60),height:r};this.textAnnotations.push(l);const d=this.textAnnotations.length-1;return this.notifyChange("create",d,l),this.deleteHistory=[],this.startEditing(d),d}updateTextAnnotation(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];i.text=e,this.ctx.font=this.textStyle.font;const s=this.ctx.measureText(e);return i.width=s.width,i.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",n,this.textAnnotations[n]),!0}moveTextAnnotation(t,e,n){const i=this.resolveIndex(t);return!(i<0||i>=this.textAnnotations.length)&&(this.textAnnotations[i].position={x:e,y:n},this.notifyChange("update",i,this.textAnnotations[i]),!0)}removeTextAnnotation(t){const e=this.resolveIndex(t);if(e<0||e>=this.textAnnotations.length)return!1;const n=this.textAnnotations[e];return this.deleteHistory.push({annotation:Object.assign({},n),index:e}),this.textAnnotations.splice(e,1),this.notifyChange("delete",e,n),this.editingTextIndex===e?this.resetEditingState():null!==this.editingTextIndex&&this.editingTextIndex>e&&this.editingTextIndex--,this.movingTextIndex===e?this.endTextMoving():null!==this.movingTextIndex&&this.movingTextIndex>e&&this.movingTextIndex--,!0}clearTextAnnotations(){this.textAnnotations=[],this.selectedTextIndex=null,this.cancelEditing(),this.deleteHistory=[]}startEditing(t){if(!this.textInput||t<0||t>=this.textAnnotations.length)return!1;const e=this.textAnnotations[t];this.editingTextIndex=t,this.currentEditingIndex=t,this.textBeforeEditing=e.text;const n=this.viewport.offset.x+e.position.x*this.viewport.scale,i=this.viewport.offset.y+e.position.y*this.viewport.scale;return this.textInput.value=e.text,this.textInput.style.left=`${n}px`,this.textInput.style.top=`${i}px`,this.textInput.style.display="block",this.adjustInputWidth(),setTimeout(()=>{this.textInput&&(this.textInput.focus(),this.textInput.select())},10),!0}finishEditing(){if(!this.textInput)return!1;const t=this.currentEditingIndex,e=this.textInput.value.trim();if(null===t||t<0||t>=this.textAnnotations.length)return this.resetEditingState(),!1;if(""===e){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}else{const n=this.textAnnotations[t];n.text=e,this.ctx.font=this.textStyle.font;const i=this.ctx.measureText(n.text);n.width=i.width,n.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",t,n)}return this.resetEditingState(),!0}cancelEditing(){if(!this.textInput||null===this.editingTextIndex)return!1;this.textInput.value=this.textBeforeEditing;const t=this.editingTextIndex;if(t>=0&&t<this.textAnnotations.length){if(""===this.textAnnotations[t].text&&""===this.textBeforeEditing){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}}return this.resetEditingState(),!0}deleteEditingAnnotation(){if(null===this.editingTextIndex)return!1;const t=this.editingTextIndex;if(this.textInput&&(this.textInput.style.display="none"),t>=0&&t<this.textAnnotations.length){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}return this.resetEditingState(),!0}resetEditingState(){this.textInput&&(this.textInput.style.display="none"),this.editingTextIndex=null,this.currentEditingIndex=null,this.textBeforeEditing=""}adjustInputWidth(){if(!this.textInput||null===this.editingTextIndex)return;this.ctx.font=this.textStyle.font;const t=this.textInput.value||this.textInput.placeholder||"",e=this.ctx.measureText(t).width,n=Math.min(Math.max(e+24,60),200);this.textInput.style.width=`${n}px`}startMoving(t,e){return!(e<0||e>=this.textAnnotations.length)&&(this.movingTextIndex=e,this.isTextMoving=!0,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}moveAnnotation(t){if(!this.isTextMoving||null===this.movingTextIndex)return!1;const e=t.clientX-this.textMoveStart.x,n=t.clientY-this.textMoveStart.y,i=this.textAnnotations[this.movingTextIndex];return!!i&&(i.position.x+=e/this.viewport.scale,i.position.y+=n/this.viewport.scale,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}finishMoving(){if(this.isTextMoving=!1,null!==this.movingTextIndex){const t=this.textAnnotations[this.movingTextIndex];t&&this.notifyChange("update",this.movingTextIndex,t)}this.movingTextIndex=null}endTextMoving(){this.isTextMoving=!1,this.movingTextIndex=null}isEditingVisible(){var t;return"block"===(null===(t=this.textInput)||void 0===t?void 0:t.style.display)}checkTextClick(t,e){for(let n=this.textAnnotations.length-1;n>=0;n--){const i=this.textAnnotations[n],s=this.viewport.offset.x+i.position.x*this.viewport.scale,o=this.viewport.offset.y+i.position.y*this.viewport.scale,a=Math.max(i.width,60)+2*this.textStyle.padding,r=i.height+2*this.textStyle.padding;if(t>=s&&t<=s+a&&e>=o&&e<=o+r)return n}return null}checkTextClickForMove(t){const e=this.checkTextClick(t.offsetX,t.offsetY);return null!==e?(this.startMoving(t,e),{index:e,handled:!0}):{index:-1,handled:!1}}getTextAnnotations(){return this.textAnnotations.map(t=>r(t))}withdraw(){if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.textAnnotations.splice(e,0,t),!0}return this.textAnnotations.length>0&&(this.textAnnotations.pop(),!0)}selectTextAnnotation(t){return t<0||t>=this.textAnnotations.length?(this.deselectTextAnnotation(),!1):(this.selectedTextIndex=t,null!==this.editingTextIndex&&this.finishEditing(),!0)}deselectTextAnnotation(){this.selectedTextIndex=null}deleteSelectedTextAnnotation(){if(null===this.selectedTextIndex)return!1;const t=this.selectedTextIndex,e=this.textAnnotations[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.textAnnotations.splice(t,1),this.selectedTextIndex=null,this.notifyChange("delete",t,e),null!==this.editingTextIndex&&this.editingTextIndex>t&&this.editingTextIndex--,null!==this.movingTextIndex&&this.movingTextIndex>t&&this.movingTextIndex--,!0}getSelectedTextAnnotation(){if(null===this.selectedTextIndex)return null;const t=this.textAnnotations[this.selectedTextIndex];return t?{index:this.selectedTextIndex,data:r(t)}:null}destroy(){this.textInput&&this.textInput.parentNode&&this.textInput.parentNode.removeChild(this.textInput)}}function I(t,e){switch(e){case"dashed":t.setLineDash([10,5]);break;case"dotted":t.setLineDash([2,4]);break;default:t.setLineDash([])}}class T{draw(t,e,n,i){const s=n.data[0];t.strokeRect(e.offset.x+s.start.x*e.scale,e.offset.y+s.start.y*e.scale,s.width*e.scale,s.height*e.scale)}drawInProgress(t,e,n){const i=n.operate.data[0];t.strokeRect(e.offset.x+i.start.x*e.scale,e.offset.y+i.start.y*e.scale,i.width*e.scale,i.height*e.scale)}drawSelection(t,e,n,i,s){const o=n.data[0],a=e.offset.x+o.start.x*e.scale,r=e.offset.y+o.start.y*e.scale,h=o.width*e.scale,l=o.height*e.scale;if(t.fillStyle=i.fillColor,t.fillRect(a,r,h,l),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.strokeRect(a,r,h,l),s)return;const d=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),t.fillRect(a-d/2,r-d/2,d,d),t.fillRect(a+h-d/2,r-d/2,d,d),t.fillRect(a-d/2,r+l-d/2,d,d),t.fillRect(a+h-d/2,r+l-d/2,d,d)}drawForExport(t,e,n){const i=e.data[0];t.strokeRect(i.start.x,i.start.y,i.width,i.height)}getTitleAnchor(t,e){return u(t,e)}}class S{constructor(t){this.store=t}draw(t,e,n,i){const s=i.vertexStyle||this.store.getVertexStyle();this.drawPolygon(t,e,n.data,"fullfilled"===n.status,s)}drawInProgress(t,e,n){const i=n.operate.data,s=n.tempPolygonPoint;if(t.beginPath(),i.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),s){const n=Math.round(e.offset.x+s.x*e.scale),i=Math.round(e.offset.y+s.y*e.scale);t.lineTo(n,i)}if(t.stroke(),this.drawPolygonVertices(t,e,i,n.getVertexStyle()),s){const i=n.getVertexStyle(),o=Math.round(e.offset.x+s.x*e.scale),a=Math.round(e.offset.y+s.y*e.scale),r=i.size/2;switch(t.fillStyle=i.fillColor,t.strokeStyle=i.strokeColor,t.lineWidth=i.strokeWidth,t.beginPath(),i.shape){case"square":t.rect(o-r,a-r,2*r,2*r);break;case"diamond":t.moveTo(o,a-r),t.lineTo(o+r,a),t.lineTo(o,a+r),t.lineTo(o-r,a),t.closePath();break;default:t.arc(o,a,r,0,2*Math.PI)}t.fill(),i.strokeWidth>0&&t.stroke()}}drawSelection(t,e,n,i,s){const o=n.data;if(t.beginPath(),o.forEach((n,i)=>{const s=e.offset.x+n.point.x*e.scale,o=e.offset.y+n.point.y*e.scale;0===i?t.moveTo(s,o):t.lineTo(s,o)}),t.closePath(),t.fillStyle=i.fillColor,t.fill(),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.stroke(),s)return;const a=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),o.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),s=Math.round(e.offset.y+n.point.y*e.scale);t.fillRect(i-a/2,s-a/2,a,a)})}drawForExport(t,e,n){if("fullfilled"!==e.status)return;const i=e.data;t.beginPath(),i.forEach((e,n)=>{0===n?t.moveTo(e.point.x,e.point.y):t.lineTo(e.point.x,e.point.y)});const s=e.data[0];t.lineTo(s.point.x,s.point.y),t.stroke(),i.forEach(e=>{t.beginPath(),t.arc(e.point.x,e.point.y,4,0,2*Math.PI),t.fillStyle=n.strokeColor,t.fill()})}getTitleAnchor(t,e){return u(t,e)}drawPolygon(t,e,n,i,s){if(0!==n.length){if(t.beginPath(),n.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),i&&n.length>1){const i=n[0];t.lineTo(e.offset.x+i.point.x*e.scale,e.offset.y+i.point.y*e.scale)}t.stroke(),this.drawPolygonVertices(t,e,n,s)}}drawPolygonVertices(t,e,n,i){const s=i||this.store.getVertexStyle(),o=s.size/2;n.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),a=Math.round(e.offset.y+n.point.y*e.scale);switch(t.fillStyle=s.fillColor,t.strokeStyle=s.strokeColor,t.lineWidth=s.strokeWidth,t.beginPath(),s.shape){case"square":t.rect(i-o,a-o,2*o,2*o);break;case"diamond":t.moveTo(i,a-o),t.lineTo(i+o,a),t.lineTo(i,a+o),t.lineTo(i-o,a),t.closePath();break;default:t.arc(i,a,o,0,2*Math.PI)}t.fill(),s.strokeWidth>0&&t.stroke()})}}class b{constructor(t,e,n,i){this.ctx=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.shapeRenderers={rect:new T,polygon:new S(n)}}render(t){this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.drawBackgroundImage(t),this.drawAnnotations(),function(t,e,n){const i=n.textStyle;n.textAnnotations.forEach((s,o)=>{if(n.editingTextIndex===o&&n.isEditingVisible())return;if(!s.text)return;const a=s.style||{font:i.font,color:i.color,backgroundColor:i.backgroundColor},r=e.offset.x+s.position.x*e.scale,h=e.offset.y+s.position.y*e.scale,l=n.selectedTextIndex===o;t.font=a.font;const d=t.measureText(s.text),c=d.actualBoundingBoxAscent||.8*s.height,g=c+(d.actualBoundingBoxDescent||.2*s.height),x=i.borderRadius,u=r,f=h,p=s.width+2*i.padding,y=g+2*i.padding;t.fillStyle=a.backgroundColor,t.beginPath(),t.roundRect(u,f,p,y,x),t.fill(),l&&(t.strokeStyle=i.selectedBorderColor,t.lineWidth=2,t.setLineDash([5,5]),t.beginPath(),t.roundRect(u,f,p,y,x),t.stroke(),t.setLineDash([]));const v=r+i.padding,M=h+i.padding+c;t.fillStyle=a.color,t.fillText(s.text,v,M)})}(this.ctx,this.viewport,this.textManager)}drawBackgroundImage(t){this.ctx.drawImage(t,this.viewport.offset.x,this.viewport.offset.y,this.viewport.originalWidth*this.viewport.scale,this.viewport.originalHeight*this.viewport.scale)}drawAnnotations(){this.annotationManager.recordList.forEach(t=>{const e=this.annotationManager.getAnnotationStyle(t);this.ctx.strokeStyle=e.strokeColor,this.ctx.lineWidth=e.lineWidth,I(this.ctx,e.lineStyle||"solid"),this.ctx.fillStyle=this.ctx.strokeStyle,"rect"===t.type?this.shapeRenderers.rect.draw(this.ctx,this.viewport,t,e):"polygon"===t.type&&this.shapeRenderers.polygon.draw(this.ctx,this.viewport,t,e),this.annotationManager.enableTitle&&t.title&&this.drawAnnotationTitle(t)}),this.annotationManager.operate.data.length>0&&(this.ctx.strokeStyle=this.annotationManager.strokeStyle,this.ctx.lineWidth=this.annotationManager.lineWidth,this.ctx.fillStyle=this.ctx.strokeStyle,I(this.ctx,this.annotationManager.lineStyle),"rect"===this.annotationManager.operate.type?this.shapeRenderers.rect.drawInProgress(this.ctx,this.viewport,this.annotationManager):"polygon"===this.annotationManager.operate.type&&this.shapeRenderers.polygon.drawInProgress(this.ctx,this.viewport,this.annotationManager)),this.ctx.setLineDash([]),this.drawSelectionHighlight()}drawSelectionHighlight(){const t=this.annotationManager.selectedAnnotation;if(!t)return;const e=this.annotationManager.recordList[t.index];if(!e)return;const n=this.annotationManager.selectionStyle,i=!0===t.locked;this.ctx.save(),"rect"===e.type?this.shapeRenderers.rect.drawSelection(this.ctx,this.viewport,e,n,i):"polygon"===e.type&&this.shapeRenderers.polygon.drawSelection(this.ctx,this.viewport,e,n,i),this.ctx.restore()}drawAnnotationTitle(t){var e,n,i;if(!t.title)return;const s=this.annotationManager.getEffectiveTitleStyle(t),o=this.annotationManager.getEffectiveTitlePosition(t),a=s.font||"12px Arial",r=s.color||"#FFFFFF",h=s.backgroundColor||"rgba(0, 0, 0, 0.7)",l=null!==(e=s.paddingX)&&void 0!==e?e:6,d=null!==(n=s.paddingY)&&void 0!==n?n:3,c=null!==(i=s.borderRadius)&&void 0!==i?i:4;this.ctx.save(),this.ctx.font=a;const g=this.ctx.measureText(t.title).width,u=a.match(/(\d+)px/),f=u?parseInt(u[1]):12,p=("rect"===t.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(t,this.viewport);if(!p)return void this.ctx.restore();const y=g+2*l,v=f+2*d,{x:M,y:w}=x({anchor:p,boxWidth:y,boxHeight:v,position:o});this.ctx.fillStyle=h,this.ctx.setLineDash([]),this.ctx.beginPath(),this.ctx.roundRect(M,w,y,v,c),this.ctx.fill(),this.ctx.fillStyle=r,this.ctx.textAlign="left",this.ctx.textBaseline="top",this.ctx.fillText(t.title,M+l,w+d),this.ctx.restore()}drawForExport(t,e,n,i){t.drawImage(e,0,0,n,i),this.annotationManager.recordList.forEach(e=>{const n=this.annotationManager.getAnnotationStyle(e);t.strokeStyle=n.strokeColor,t.lineWidth=n.lineWidth,"rect"===e.type?this.shapeRenderers.rect.drawForExport(t,e,n):"polygon"===e.type&&this.shapeRenderers.polygon.drawForExport(t,e,n)}),this.textManager.textAnnotations.forEach(e=>{const n=this.textManager.textStyle,i=e.style||{font:n.font,color:n.color,backgroundColor:n.backgroundColor};t.font=i.font;const s=t.measureText(e.text),o=s.actualBoundingBoxAscent||.8*e.height,a=o+(s.actualBoundingBoxDescent||.2*e.height),r=e.position.x,h=e.position.y,l=e.width+2*n.padding,d=a+2*n.padding,c=n.borderRadius;t.fillStyle=i.backgroundColor,t.roundRect?(t.roundRect(r,h,l,d,c),t.fill()):t.fillRect(r,h,l,d),t.fillStyle=i.color,t.fillText(e.text,e.position.x+n.padding,e.position.y+n.padding+o)}),this.annotationManager.enableTitle&&this.annotationManager.recordList.forEach(e=>{var n,i,s;if(!e.title)return;const o=this.annotationManager.getEffectiveTitleStyle(e),a=this.annotationManager.getEffectiveTitlePosition(e),r=o.font||"12px Arial",h=o.color||"#FFFFFF",l=o.backgroundColor||"rgba(0, 0, 0, 0.7)",d=null!==(n=o.paddingX)&&void 0!==n?n:6,c=null!==(i=o.paddingY)&&void 0!==i?i:3,g=null!==(s=o.borderRadius)&&void 0!==s?s:4;t.font=r;const u=t.measureText(e.title).width,f=r.match(/(\d+)px/),p=f?parseInt(f[1]):12,y=("rect"===e.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(e);if(!y)return;const v=u+2*d,M=p+2*c,{x:w,y:m}=x({anchor:y,boxWidth:v,boxHeight:M,position:a});t.fillStyle=l,t.roundRect?(t.roundRect(w,m,v,M,g),t.fill()):t.fillRect(w,m,v,M),t.fillStyle=h,t.textAlign="left",t.textBaseline="top",t.fillText(e.title,w+d,m+c)})}}class C{constructor(t,e,n,i,s,o,a,r,h,l){this.canvas=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.renderer=s,this.getDrawType=o,this.getBgImage=a,this.renderCallback=r,this.setDrawTypeCallback=h,this.notifyUndo=l,this.isDragging=!1,this.dragStart={x:0,y:0},this.justFinishedMove=!1,this.justDeselected=!1}handleWheel(t){if(t.preventDefault(),!this.getBgImage())return;const e=t.deltaY>0?-.02:.02,n=this.viewport.scale,i=Math.max(this.viewport.minScale,Math.min(n+e,this.viewport.maxScale)),s=this.canvas.getBoundingClientRect(),o=t.clientX-s.left,a=t.clientY-s.top,r=(o-this.viewport.offset.x)/n,h=(a-this.viewport.offset.y)/n;this.viewport.scale=i;const l=r*i+this.viewport.offset.x,d=h*i+this.viewport.offset.y;this.viewport.offset.x+=o-l,this.viewport.offset.y+=a-d,this.viewport.calculateBoundaries(),this.viewport.constrainViewport(),this.viewport.isInitialScale=this.viewport.scale===this.viewport.initialScale,this.renderCallback()}handleMouseDown(t){var e,n;if(0!==t.button)return;const i=this.getDrawType(),s=this.getBgImage();if(this.annotationManager.selectedAnnotation&&s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),void this.renderCallback()}if("text"===i){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if("rect"===(null==n?void 0:n.type))return this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(e);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();if(this.annotationManager.selectedAnnotation)return this.annotationManager.deselectAnnotation(),void this.renderCallback()}return null!==this.textManager.selectedTextIndex?(this.textManager.deselectTextAnnotation(),void this.renderCallback()):void this.handleTextModeClick(t)}if(!s)return;const o=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if("rect"===i){if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"rect"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.startRectDrawing(o)}else if("polygon"===i){if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e&&"polygon-vertex"===e.type)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"polygon"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.isDrawing?this.checkPolygonPointValid(o)&&this.annotationManager.addPolygonPoint(o):this.annotationManager.startPolygonDrawing(o),this.annotationManager.updatePolygonTempPoint(o),this.renderCallback()}else if("drag"===i){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback()}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(this.handleRectModeClick(t,o))return;if(this.handlePolygonModeClick(t,o))return;this.isDragging=!0,this.dragStart={x:t.clientX,y:t.clientY},this.canvas.style.cursor="grabbing"}else""===i&&this.handleNoModeClick(t,o)}handleTextModeClick(t){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.startMoving(t,e),this.canvas.style.cursor="grabbing",this.renderCallback(),!0;const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return this.textManager.addTextAnnotation(n.x,n.y),!0}handleRectModeClick(t,e){var n,i;if("rect"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"rect"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"rect"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handlePolygonModeClick(t,e){var n,i;if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n&&"polygon-vertex"===n.type)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"polygon"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"polygon"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handleNoModeClick(t,e){const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();this.textManager.deselectTextAnnotation();const i=this.annotationManager.getAnnotationAtPoint(e);i?(this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback()):this.annotationManager.deselectAnnotation()}checkPolygonPointValid(t){const e=this.annotationManager.operate.data.length>0?this.annotationManager.operate.data[this.annotationManager.operate.data.length-1]:null;return!e||Math.abs(e.point.x-t.x)>5||Math.abs(e.point.y-t.y)>5}handleMouseMove(t){if(!this.getBgImage())return;const e=this.getDrawType();if(this.isDragging&&"drag"===e){const e=t.clientX-this.dragStart.x,n=t.clientY-this.dragStart.y;return this.viewport.updateOffset(e,n),this.dragStart={x:t.clientX,y:t.clientY},void this.renderCallback()}if(this.textManager.isTextMoving&&null!==this.textManager.movingTextIndex)this.textManager.moveAnnotation(t)&&this.renderCallback();else if((this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&this.annotationManager.selectedAnnotation)this.handleAnnotationMove(t);else{if(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||this.updateCursor(t),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updateRectDrawing(e),this.renderCallback()}if("polygon"===e&&this.annotationManager.isDrawing){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updatePolygonTempPoint(e),this.renderCallback()}}}handleAnnotationMove(t){var e,n;if(this.annotationManager.isResizing&&this.annotationManager.activeHandle){const i=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return"rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)?this.annotationManager.resizeRect(i):"polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)&&this.annotationManager.resizePolygon(i),void this.renderCallback()}if(!this.annotationManager.isMovingAnnotation||!this.annotationManager.selectedAnnotation)return;const i=(t.clientX-this.annotationManager.annotationMoveStart.x)/this.viewport.scale,s=(t.clientY-this.annotationManager.annotationMoveStart.y)/this.viewport.scale;this.annotationManager.moveSelectedAnnotation(i,s),this.annotationManager.updateMoveStart({x:t.clientX,y:t.clientY}),this.renderCallback()}isHoverLockedAnnotation(t){return!(!t||!this.annotationManager.selectedAnnotation)&&(!0===this.annotationManager.selectedAnnotation.locked&&t.index===this.annotationManager.selectedAnnotation.index)}updateCursor(t){const e=this.getDrawType();if("text"===e){if(this.getBgImage()){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}const n=this.annotationManager.getAnnotationAtPoint(e);if(n)return void(this.canvas.style.cursor=this.isHoverLockedAnnotation(n)?"default":"move")}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);return void(this.canvas.style.cursor=null!==e?"move":"crosshair")}"rect"!==e?"polygon"!==e?"drag"!==e?""!==e?this.canvas.style.cursor="default":this.updateNoModeCursor(t):this.updateDragModeCursor(t):this.updatePolygonModeCursor(t):this.updateRectModeCursor(t)}updateRectModeCursor(t){var e;if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void(this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updatePolygonModeCursor(t){var e;if("polygon"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){if(this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="crosshair")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updateDragModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"grab"}updateNoModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"default"}handleMouseUp(t){if(this.isDragging){this.isDragging=!1;const t=this.getDrawType();return void(this.canvas.style.cursor="drag"===t?"grab":"default")}if(this.textManager.isTextMoving){this.justFinishedMove=!0,this.textManager.finishMoving();const t=this.getDrawType();"drag"===t?this.canvas.style.cursor="grab":""===t?this.canvas.style.cursor="move":(this.textManager.endTextMoving(),this.canvas.style.cursor="default")}(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&(this.justFinishedMove=!0,this.annotationManager.finishMovingAnnotation(),this.canvas.style.cursor=this.annotationManager.selectedAnnotation?"move":"default"),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type&&(this.annotationManager.finishRectDrawing(),this.renderCallback())}handleMouseLeave(t){(this.isDragging||this.textManager.isTextMoving||this.annotationManager.isResizing||this.annotationManager.isMovingAnnotation)&&this.handleMouseUp(t)}handleDoubleClick(t){if(!this.getBgImage())return;this.justFinishedMove=!1;const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return void this.textManager.startEditing(e);if(this.annotationManager.selectedAnnotation){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if(n&&n.index===this.annotationManager.selectedAnnotation.index)return void this.annotationManager.startTitleEditing(n.index)}if("polygon"===this.getDrawType()){if(this.annotationManager.isDrawing&&this.annotationManager.operate.data.length<=2)return;this.annotationManager.finishPolygonDrawing(),this.renderCallback()}}handleClick(t){var e;const n=this.getDrawType();!this.getBgImage()||"polygon"!==n||this.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||(this.justDeselected?this.justDeselected=!1:null===(e=this.annotationManager.selectedAnnotation)||void 0===e||e.type)}handleKeyDown(t){const e=t.target;if(!e||"INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName&&"SELECT"!==e.tagName&&!e.isContentEditable){if("z"===t.key&&(t.ctrlKey||t.metaKey)){return M.withdrawAll(this.annotationManager,this.textManager)&&this.notifyUndo(),void this.renderCallback()}if(" "===t.key)return this.viewport.resetToInitial(),void this.renderCallback();if("Escape"!==t.key){if("Delete"===t.key||"Backspace"===t.key){if(null!==this.textManager.editingTextIndex)return this.textManager.removeTextAnnotation(this.textManager.editingTextIndex),void this.renderCallback();if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.renderCallback();this.annotationManager.selectedAnnotation&&(this.annotationManager.deleteSelectedAnnotation(),this.renderCallback())}}else this.annotationManager.isDrawing?(this.annotationManager.cancelDrawing(),this.renderCallback()):this.annotationManager.selectedAnnotation&&(this.annotationManager.deselectAnnotation(),this.renderCallback())}}}class k{constructor(){this.listeners=new Map}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.delete(e)}emit(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.forEach(t=>t(e))}clear(){this.listeners.clear()}}class P{constructor(t){this.canvas=document.createElement("canvas"),this.emitter=new k,this.bgImage=null,this.bgImageSrc="",this.bgImageExt="jpeg",this.drawType="";const{drawType:e,useEvents:n=!0,id:i="container",annotationColor:s,lineStyle:o,vertexStyle:a,textStyle:r,enableTitle:h=!1,clampToImageBounds:d=!0}=t,c=document.getElementById(i);if(!c)throw new Error(`Container with id "${i}" not found`);this.container=c,"absolute"!==c.style.position&&"fixed"!==c.style.position&&"relative"!==c.style.position&&(c.style.position="relative"),this.ctx=this.canvas.getContext("2d"),this.viewport=new l,this.viewport.setSize(c.clientWidth,c.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.canvas.style.cursor="default",this.canvas.style.display="block",c.appendChild(this.canvas),this.annotationManager=new m(this.viewport,this.container,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),this.annotationManager.measureTitleWidth=(t,e)=>(this.ctx.font=e,this.ctx.measureText(t).width),s&&this.annotationManager.setColorConfig(s),o&&this.annotationManager.setLineStyle(o),a&&this.annotationManager.setVertexStyle(a),this.annotationManager.enableTitle=h,h&&this.annotationManager.initTitleSupport(),this.annotationManager.clampEnabled=d,this.textManager=new A(this.viewport,this.container,this.ctx,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),r&&this.textManager.setTextStyle(r),this.textManager.clampEnabled=d,this.renderer=new b(this.ctx,this.viewport,this.annotationManager,this.textManager),this.eventHandler=new C(this.canvas,this.viewport,this.annotationManager,this.textManager,this.renderer,()=>this.drawType,()=>this.bgImage,()=>this.render(),t=>this.setDrawType(t),()=>this.emitter.emit("undo",void 0)),this.events={wheel:t=>this.eventHandler.handleWheel(t),mousedown:t=>this.eventHandler.handleMouseDown(t),mousemove:t=>this.eventHandler.handleMouseMove(t),mouseup:t=>this.eventHandler.handleMouseUp(t),mouseleave:t=>this.eventHandler.handleMouseLeave(t),dblclick:t=>this.eventHandler.handleDoubleClick(t),click:t=>this.eventHandler.handleClick(t),keydown:t=>this.eventHandler.handleKeyDown(t)},this.setDrawType(e||""),n&&this.addEventListeners()}setDrawType(t){"polygon"===this.drawType&&this.annotationManager.isDrawing&&this.annotationManager.operate.data.length>0?console.warn("Cannot switch mode while polygon is being drawn. Please complete or cancel the polygon first."):this.drawType!==t&&(this.annotationManager.operate.data=[],this.annotationManager.isDrawing=!1,this.annotationManager.tempPolygonPoint=null,""!==t&&this.deselectAnnotation(),this.annotationManager.operate.type=t,this.drawType=t,this.canvas.style.cursor="drag"===t?"grab":"text"===t?"text":"default")}drawImage(t){this.bgImageSrc=t,this.bgImageExt=i(t);const e=new Image;e.crossOrigin="anonymous",e.src=t,e.onload=()=>{this.bgImage=e,this.viewport.setOriginalSize(e.width,e.height),this.viewport.calculateInitialView(),this.annotationManager.adjustTitlePositions(),this.render()}}render(){this.renderer.render(this.bgImage)}clear(t=""){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.setDrawType(t),this.render(),this.emitter.emit("clear",void 0)}withdraw(){const t=this.annotationManager.withdraw(),e=this.textManager.withdraw();(t||e)&&(this.render(),this.emitter.emit("undo",void 0))}resize(){const t=this.canvas.parentElement;t&&(this.viewport.setSize(t.clientWidth,t.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.render())}addEventListeners(){this.canvas.addEventListener("mousedown",this.events.mousedown),this.canvas.addEventListener("mousemove",this.events.mousemove),this.canvas.addEventListener("mouseup",this.events.mouseup),this.canvas.addEventListener("mouseleave",this.events.mouseleave),this.canvas.addEventListener("wheel",this.events.wheel),this.canvas.addEventListener("contextmenu",t=>t.preventDefault()),document.addEventListener("keydown",this.events.keydown),this.handleClickEventListener()}handleClickEventListener(){let t=null,e=0;this.canvas.addEventListener("click",n=>{if(this.eventHandler.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving)return;const i=this.eventHandler.justFinishedMove;i&&(this.eventHandler.justFinishedMove=!1),e++,1===e?t=window.setTimeout(()=>{1!==e||i||this.events.click(n),e=0,t=null},300):2===e&&(this.eventHandler.justFinishedMove=!1,this.events.dblclick(n),e=0,null!==t&&(clearTimeout(t),t=null))})}changeScale(t){if(!this.bgImage)return;const e=a(this.viewport.scale,t),n=this.viewport.width/2,i=this.viewport.height/2,s=this.viewport.scale+e;this.viewport.updateScale(s,n,i),this.render()}clearCanvas(t=!1,e=!0){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.textManager.deselectTextAnnotation(),this.emitter.emit("clear",void 0),!t&&e&&(this.bgImage=null,this.bgImageSrc="",this.viewport.setOriginalSize(0,0),this.viewport.reset()),this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.bgImage&&this.render(),"drag"===this.drawType&&(this.canvas.style.cursor="default")}clearAnnotations(){this.clearCanvas(!0,!1)}getAnnotations(){return this.annotationManager.getAnnotations()}getAnnotation(t){return this.annotationManager.getAnnotation(t)}getTextAnnotation(t){return this.textManager.getTextAnnotation(t)}on(t,e){this.emitter.on(t,e)}off(t,e){this.emitter.off(t,e)}setAnnotationTitle(t,e){const n=this.annotationManager.setTitle(t,e);return n&&this.render(),n}getAnnotationTitle(t){return this.annotationManager.getTitle(t)}setTitleStyle(t){this.annotationManager.setTitleStyle(t),this.render()}getTitleStyle(){return this.annotationManager.getTitleStyle()}setTitlePosition(t){this.annotationManager.setTitlePosition(t),this.render()}getTitlePosition(){return this.annotationManager.getTitlePosition()}setAnnotationTitleStyle(t,e){const n=this.annotationManager.setAnnotationTitleStyle(t,e);return n&&this.render(),n}setAnnotationTitlePosition(t,e){const n=this.annotationManager.setAnnotationTitlePosition(t,e);return n&&this.render(),n}getTextAnnotations(){return this.textManager.getTextAnnotations()}exportAnnotationImage(){return new Promise((t,e)=>{if(!this.bgImage)return void e(new Error("No background image loaded"));const n=document.createElement("canvas");n.width=this.viewport.originalWidth,n.height=this.viewport.originalHeight;const i=n.getContext("2d");if(!i)return void e(new Error("Could not create offscreen canvas context"));const s=new Image;s.src=this.bgImageSrc,s.crossOrigin="anonymous",s.onload=()=>{try{this.renderer.drawForExport(i,s,this.viewport.originalWidth,this.viewport.originalHeight);const e=n.toDataURL(`image/${this.bgImageExt}`,.7);t(e)}catch(n){this.exportCurrentViewImage().then(t).catch(t=>e(new Error(`Both methods failed: ${t.message}`)))}},s.onerror=()=>{e(new Error("Failed to load image for export"))}})}exportCurrentViewImage(){return new Promise((t,e)=>{try{t(this.canvas.toDataURL(`image/${this.bgImageExt}`))}catch(t){e(new Error(`Failed to export current view: ${t.message}`))}})}base64ToFile(t,e){return s(t,e)}static base64ToBlob(t){return o(t)}addTextAnnotation(t,e,n=""){this.textManager.addTextAnnotation(t,e,n),this.render()}updateTextAnnotation(t,e){this.textManager.updateTextAnnotation(t,e)&&this.render()}moveTextAnnotation(t,e,n){this.textManager.moveTextAnnotation(t,e,n)&&this.render()}removeTextAnnotation(t){this.textManager.removeTextAnnotation(t)&&this.render()}clearTextAnnotations(){this.textManager.clearTextAnnotations(),this.render()}selectAnnotation(t,e){this.annotationManager.selectAnnotation(t,e)&&this.render()}deselectAnnotation(){this.annotationManager.deselectAnnotation(),this.textManager.deselectTextAnnotation(),this.textManager.editingTextIndex=null,this.render()}getSelectedAnnotation(){const t=this.annotationManager.getSelectedAnnotation();if(t)return t;const e=this.textManager.getSelectedTextAnnotation();return e?{index:e.index,type:"text",data:e.data}:null}deleteSelectedAnnotation(){if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.render();this.annotationManager.deleteSelectedAnnotation()&&this.render()}moveSelectedAnnotation(t,e){if(this.annotationManager.moveSelectedAnnotation(t,e)){const t=this.annotationManager.selectedAnnotation;t&&this.annotationManager.notifyUpdate(t.index),this.render()}}setAnnotationColor(t){this.annotationManager.setColorConfig(t),this.render()}getAnnotationColor(){return this.annotationManager.getColorConfig()}updateSelectedAnnotationStyle(t){if(void 0!==t){const e=this.annotationManager.updateAnnotationStyle(t);return e&&this.render(),e}const e=this.annotationManager.selectedAnnotation;if(!e)return!1;const n=this.annotationManager.recordList[e.index];return!!n&&(n.style=this.annotationManager.getCurrentStyle(),this.annotationManager.notifyUpdate(e.index),this.render(),!0)}setLineStyle(t){this.annotationManager.setLineStyle(t),this.render()}getLineStyle(){return this.annotationManager.getLineStyle()}setVertexStyle(t){this.annotationManager.setVertexStyle(t),this.render()}getVertexStyle(){return this.annotationManager.getVertexStyle()}setTextStyle(t){this.textManager.setTextStyle(t),this.render()}updateTextAnnotationStyle(t,e){const n=this.textManager.updateTextAnnotationStyle(t,e);return n&&this.render(),n}setTextInputStyle(t){this.textManager.setInputStyle(t)}setTextSelectionStyle(t){this.textManager.setSelectionStyle(t),this.render()}destroy(){this.emitter.clear(),document.removeEventListener("keydown",this.events.keydown),this.textManager.destroy(),this.annotationManager.destroyTitleInput(),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}t.AnnotationManager=m,t.Drawer=P,t.Emitter=k,t.EventHandler=C,t.Renderer=b,t.TextAnnotationManager=A,t.ViewportManager=l,t.base64ToBlob=o,t.base64ToFile=s,t.default=P,t.getImageTypeFromUrl=i,t.getZoomDelta=a,t.isPointInPolygon=n,t.isPointInRect=e,Object.defineProperty(t,"__esModule",{value:!0})}),"undefined"!=typeof ImageAnnotationDrawer&&ImageAnnotationDrawer.default&&(ImageAnnotationDrawer=ImageAnnotationDrawer.default);
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ImageAnnotationDrawer=t.ImageAnnotationDrawer||{})}(this,function(t){"use strict";function e(t,e){const n=e.width>=0?e.start.x:e.start.x+e.width,i=e.height>=0?e.start.y:e.start.y+e.height,s=Math.abs(e.width),o=Math.abs(e.height);return t.x>=n&&t.x<=n+s&&t.y>=i&&t.y<=i+o}function n(t,e){if(e.length<3)return!1;let n=!1;for(let i=0,s=e.length-1;i<e.length;s=i++){const o=e[i].point.x,a=e[i].point.y,r=e[s].point.x,h=e[s].point.y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n}function i(t){try{const e=new URL(t).pathname.toLowerCase();return e.endsWith(".png")?"png":e.endsWith(".jpg")?"jpg":e.endsWith(".jpeg")?"jpeg":e.endsWith(".webp")?"webp":e.endsWith(".gif")?"gif":e.endsWith(".bmp")?"bmp":e.endsWith(".svg")?"svg":"jpeg"}catch(t){return"jpeg"}}function s(t,e){const n=t.split(";base64,"),i=n[0].split(":")[1],s=window.atob(n[1]),o=s.length,a=new Uint8Array(o);for(let t=0;t<o;++t)a[t]=s.charCodeAt(t);const r=new Blob([a],{type:i});return new File([r],e,{type:i})}function o(t){return new Promise((e,n)=>{const i=t.split(";base64,");if(i.length<2)return void n(new Error("Invalid base64 string"));const s=i[0].split(":")[1],o=atob(i[1]),a=new ArrayBuffer(o.length),r=new Uint8Array(a);for(let t=0;t<o.length;t++)r[t]=o.charCodeAt(t);e(new Blob([a],{type:s}))})}function a(t,e){return t<2?e?.1:-.1:t<5?e?.05:-.05:e?.02:-.02}function r(t){return"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t))}function h(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():`id-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}class l{constructor(){this.width=0,this.height=0,this.originalWidth=0,this.originalHeight=0,this.scale=1,this.minScale=1,this.maxScale=10,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}setSize(t,e){this.width=t,this.height=e}setOriginalSize(t,e){this.originalWidth=t,this.originalHeight=e}calculateInitialView(){if(0===this.originalWidth||0===this.originalHeight)return;const t=this.width/this.originalWidth,e=this.height/this.originalHeight;this.scale=Math.min(t,e),this.initialScale=this.scale,this.minScale=this.initialScale,this.offset={x:(this.width-this.originalWidth*this.scale)/2,y:(this.height-this.originalHeight*this.scale)/2},this.initialOffset=Object.assign({},this.offset),this.calculateBoundaries(),this.isInitialScale=!0}calculateBoundaries(){const t=this.originalWidth*this.scale,e=this.originalHeight*this.scale;this.maxOffsetX=0,this.maxOffsetY=0,this.minOffsetX=this.width-t,this.minOffsetY=this.height-e,this.minOffsetX>this.maxOffsetX&&([this.minOffsetX,this.maxOffsetX]=[this.maxOffsetX,this.minOffsetX]),this.minOffsetY>this.maxOffsetY&&([this.minOffsetY,this.maxOffsetY]=[this.maxOffsetY,this.minOffsetY])}constrainViewport(){this.offset.x>this.maxOffsetX?this.offset.x=this.maxOffsetX:this.offset.x<this.minOffsetX&&(this.offset.x=this.minOffsetX),this.offset.y>this.maxOffsetY?this.offset.y=this.maxOffsetY:this.offset.y<this.minOffsetY&&(this.offset.y=this.minOffsetY)}toImageCoordinates(t,e){return{x:(t-this.offset.x)/this.scale,y:(e-this.offset.y)/this.scale}}toCanvasCoordinates(t,e){return{x:this.offset.x+t*this.scale,y:this.offset.y+e*this.scale}}updateScale(t,e,n){const i=this.scale,s=(e-this.offset.x)/i,o=(n-this.offset.y)/i;this.scale=Math.max(this.minScale,Math.min(t,this.maxScale));const a=s*this.scale+this.offset.x,r=o*this.scale+this.offset.y;this.offset.x+=e-a,this.offset.y+=n-r,this.calculateBoundaries(),this.constrainViewport(),this.isInitialScale=this.scale===this.initialScale}resetToInitial(){this.scale=this.initialScale,this.offset=Object.assign({},this.initialOffset),this.calculateBoundaries(),this.isInitialScale=!0}updateOffset(t,e){this.offset.x+=t,this.offset.y+=e,this.constrainViewport()}reset(){this.scale=1,this.minScale=1,this.offset={x:0,y:0},this.initialScale=1,this.initialOffset={x:0,y:0},this.isInitialScale=!0,this.minOffsetX=0,this.minOffsetY=0,this.maxOffsetX=0,this.maxOffsetY=0}}const d={minX:Number.NEGATIVE_INFINITY,minY:Number.NEGATIVE_INFINITY,maxX:Number.POSITIVE_INFINITY,maxY:Number.POSITIVE_INFINITY};function c(t,e,n){return Math.min(Math.max(t,e),n)}function g(t){var e,n,i,s;const{anchor:o,boxWidth:a,boxHeight:r,position:h}=t,l=null!==(e=t.bounds)&&void 0!==e?e:d,g=null!==(n=t.gap)&&void 0!==n?n:4,x=null!==(i=h.offsetX)&&void 0!==i?i:0,u=null!==(s=h.offsetY)&&void 0!==s?s:0,f=h.align||"center";let p;switch(f){case"left":p=o.x+x;break;case"right":p=o.x+o.width-a+x;break;default:p=o.x+o.width/2-a/2+x}const y=c(p,l.minX,Math.max(l.minX,l.maxX-a)),v=x+(y-p),M=h.vertical||"top";let w,m=M;return"inside-top"===M?w=o.y+g+u:"bottom"===M?(w=o.y+o.height+g+u,w+r>l.maxY&&(m="top",w=o.y-r-g+u)):(w=o.y-r-g+u,w<l.minY&&(m="bottom",w=o.y+o.height+g+u)),w=c(w,l.minY,Math.max(l.minY,l.maxY-r)),{x:y,y:w,vertical:m,align:f,offsetX:v}}function x(t){const{x:e,y:n}=g(t);return{x:e,y:n}}function u(t,e){if("polygon"===t.type){const n=t.data;if(0===n.length)return null;let i=1/0,s=1/0,o=-1/0,a=-1/0;return n.forEach(t=>{const n=e?e.offset.x+t.point.x*e.scale:t.point.x,r=e?e.offset.y+t.point.y*e.scale:t.point.y;n<i&&(i=n),r<s&&(s=r),n>o&&(o=n),r>a&&(a=r)}),{x:i,y:s,width:o-i,height:a-s}}const n=t.data[0];return e?{x:e.offset.x+n.start.x*e.scale,y:e.offset.y+n.start.y*e.scale,width:n.width*e.scale,height:n.height*e.scale}:{x:n.start.x,y:n.start.y,width:n.width,height:n.height}}function f(t,e,n){if(!n)return e;const{originalWidth:i,originalHeight:s}=t;return i&&s?{x:Math.max(0,Math.min(e.x,i)),y:Math.max(0,Math.min(e.y,s))}:e}function p(t,e,n,i,s){t&&s.id&&t(n,{id:s.id,type:e,index:i,data:r(s)})}const y=new class{constructor(){this.type="rect"}startDrawing(t,e){t.isDrawing=!0,t.drawStartPoint=e,t.operate={type:"rect",data:[{start:Object.assign({},e),width:0,height:0}],status:"pending"}}updateDrawing(t,e){if(!t.isDrawing||"rect"!==t.operate.type)return;const n=t.operate.data[0];n.width=e.x-t.drawStartPoint.x,n.height=e.y-t.drawStartPoint.y}addPoint(t,e){return!1}finishDrawing(t){if(!t.isDrawing||"rect"!==t.operate.type)return!1;const e=t.operate.data[0];return Math.abs(e.width)>5&&Math.abs(e.height)>5&&t.pushRecord(Object.assign({},t.operate)),t.operate.data=[],t.isDrawing=!1,!0}cancelDrawing(t){t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data=[],t.isDrawing=!1,!0)}hitTest(t,n){return e(n,t.data[0])}getHandles(t,e,n){const i=t.data[0],s=e.offset.x+i.start.x*e.scale,o=e.offset.y+i.start.y*e.scale,a=i.width*e.scale,r=i.height*e.scale;return[{x:s,y:o,index:0},{x:s+a,y:o,index:1},{x:s,y:o+r,index:2},{x:s+a,y:o+r,index:3}]}move(t,e,n){const i=t.data[0];i.start.x+=e,i.start.y+=n}snapshotForResize(t){const e=t.data[0];return{start:Object.assign({},e.start),width:e.width,height:e.height}}resize(t,e,n,i){const s=t.data[0],o=i,a=o.start.x,r=o.start.x+o.width,h=o.start.y,l=o.start.y+o.height;let d,c;switch(e){case 0:d=r,c=l;break;case 1:d=a,c=l;break;case 2:d=r,c=h;break;case 3:d=a,c=h;break;default:return}const g=Math.min(n.x,d),x=Math.max(n.x,d),u=Math.min(n.y,c),f=Math.max(n.y,c);s.start.x=g,s.start.y=u,s.width=x-g,s.height=f-u;const p=n.x<d,y=n.y<c;let v;return 0===e?p||y?!p&&y?v=1:p&&!y&&(v=2):v=3:1===e?p&&!y?v=2:p&&y?v=0:p||y||(v=3):2===e?!p&&y?v=1:p&&y?v=0:p||y||(v=3):3===e&&(p&&y?v=0:!p&&y?v=1:p&&!y&&(v=2)),o.start.x=s.start.x,o.start.y=s.start.y,o.width=s.width,o.height=s.height,v}getBounds(t){const e=t.data[0];return{x:e.start.x,y:e.start.y,width:e.width,height:e.height}}};const v=new class{constructor(){this.type="polygon"}startDrawing(t,e){t.isDrawing=!0,t.operate={type:"polygon",data:[{point:e}],status:"pending"},t.tempPolygonPoint=e}updateDrawing(t,e){t.tempPolygonPoint=e}addPoint(t,e){if(!t.isDrawing||"polygon"!==t.operate.type)return!1;const n=t.operate.data.length>0?t.operate.data[t.operate.data.length-1]:null;return!(n&&Math.abs(n.point.x-e.x)<=5&&Math.abs(n.point.y-e.y)<=5)&&(t.operate.data.push({point:e}),!0)}finishDrawing(t){return!(!t.isDrawing||"polygon"!==t.operate.type)&&(t.operate.data.length>=3&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate={type:"polygon",data:[],status:"pending"},t.isDrawing=!1,t.tempPolygonPoint=null,!0)}cancelDrawing(t){t.isDrawing&&"polygon"===t.operate.type&&t.operate.data.length>=2&&(t.operate.status="fullfilled",t.pushRecord(Object.assign({},t.operate))),t.operate.data=[],t.isDrawing=!1,t.tempPolygonPoint=null}withdrawInProgress(t){return 0!==t.operate.data.length&&(t.operate.data.pop(),0===t.operate.data.length&&(t.isDrawing=!1),!0)}hitTest(t,e){return n(e,t.data)}getHandles(t,e,n){const i=t.data,s=[];for(let t=0;t<i.length;t++){const n=i[t];s.push({x:e.offset.x+n.point.x*e.scale,y:e.offset.y+n.point.y*e.scale,index:t})}return s}move(t,e,n){t.data.forEach(t=>{t.point.x+=e,t.point.y+=n})}snapshotForResize(t){return t.data.map(t=>({point:Object.assign({},t.point)}))}resize(t,e,n,i){const s=t.data;e>=0&&e<s.length&&(s[e].point.x=n.x,s[e].point.y=n.y)}getBounds(t){const e=t.data;if(0===e.length)return{x:0,y:0,width:0,height:0};let n=1/0,i=1/0,s=-1/0,o=-1/0;return e.forEach(t=>{t.point.x<n&&(n=t.point.x),t.point.y<i&&(i=t.point.y),t.point.x>s&&(s=t.point.x),t.point.y>o&&(o=t.point.y)}),{x:n,y:i,width:s-n,height:o-i}}};const M=new class{constructor(){this.strategies=new Map}register(t){this.strategies.set(t.type,t)}get(t){const e=this.strategies.get(t);if(!e)throw new Error(`No strategy registered for shape type: ${t}`);return e}selectShapeExclusive(t,e,n){return"shape"===n.kind?(e.deselectTextAnnotation(),t.selectAnnotation(n.ref,{lock:n.locked})):(t.deselectAnnotation(),e.selectTextAnnotation(n.index))}deselectAll(t,e){t.deselectAnnotation(),e.deselectTextAnnotation()}withdrawAll(t,e){return t.withdraw()||e.withdraw()}};M.register(y),M.register(v);class w{constructor(t,e,n,i){this.viewport=t,this.container=e,this.renderCallback=n,this.changeCallback=i,this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.drawStartPoint={x:0,y:0},this.tempPolygonPoint=null,this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.annotationMoveStart={x:0,y:0},this.originalRect=null,this.originalPolygon=null,this.deleteHistory=[],this.editingTitleIndex=null,this.titleInput=null,this.strokeStyle="red",this.lineWidth=5,this.lineStyle="solid",this.vertexStyle={size:8,fillColor:"red",strokeColor:"white",strokeWidth:2,shape:"circle"},this.selectionStyle={strokeColor:"#00D9FF",fillColor:"rgba(0,217,255,0.15)",handleSize:12,handleColor:"#00D9FF"},this.colorConfig={rect:"red",polygon:"red",default:"red"},this.titleStyle={font:"12px Arial",color:"#FFFFFF",backgroundColor:"rgba(0, 0, 0, 0.7)",paddingX:6,paddingY:3,borderRadius:4,placeholder:"输入标题..."},this.titlePosition={vertical:"top",align:"center",offsetX:0,offsetY:0},this.enableTitle=!1,this.clampEnabled=!0,this.applyColorConfig()}strategyOf(t){return M.get(t)}clamp(t){return f(this.viewport,t,this.clampEnabled)}clampToImageBounds(t){return f(this.viewport,t,this.clampEnabled)}clampRecordToImageBounds(t){if(!this.clampEnabled)return;const{originalWidth:e,originalHeight:n}=this.viewport;if(!e||!n)return;if("rect"===t.type){const i=t.data[0];if(!i)return;const s=Math.min(i.start.x,i.start.x+i.width),o=Math.max(i.start.x,i.start.x+i.width),a=Math.min(i.start.y,i.start.y+i.height),r=Math.max(i.start.y,i.start.y+i.height);if(s>=0&&a>=0&&o<=e&&r<=n)return;const h=Math.min(o-s,e),l=Math.min(r-a,n);return i.start.x=Math.max(0,Math.min(s,e-h)),i.start.y=Math.max(0,Math.min(a,n-l)),i.width=h,void(i.height=l)}const i=t.data;if(!i||0===i.length)return;let s=1/0,o=1/0,a=-1/0,r=-1/0;for(const t of i)s=Math.min(s,t.point.x),a=Math.max(a,t.point.x),o=Math.min(o,t.point.y),r=Math.max(r,t.point.y);let h=0,l=0;if(a-s>e||s<0?h=-s:a>e&&(h=e-a),r-o>n||o<0?l=-o:r>n&&(l=n-r),0!==h||0!==l)for(const t of i)t.point.x+=h,t.point.y+=l}pushRecord(t){const e=Object.assign(Object.assign({},t),{id:h(),style:this.getCurrentStyle()});this.recordList.push(e),this.deleteHistory=[],this.notifyChange("create",this.recordList.length-1,e)}initTitleSupport(){this.container&&this.enableTitle&&this.createTitleInput()}setColorConfig(t){this.colorConfig="string"==typeof t?{rect:t,polygon:t,default:t}:Object.assign(Object.assign({},this.colorConfig),t),this.applyColorConfig()}getColorConfig(){return Object.assign({},this.colorConfig)}applyColorConfig(){this.strokeStyle=this.colorConfig.default||"red"}getColorForType(t){return this.colorConfig[t]||this.colorConfig.default||"red"}getCurrentStyle(){return{strokeColor:this.strokeStyle,lineWidth:this.lineWidth,lineStyle:this.lineStyle,vertexStyle:Object.assign({},this.vertexStyle)}}notifyChange(t,e,n){p(this.changeCallback,n.type,t,e,n)}notifyUpdate(t){const e=this.recordList[t];e&&this.notifyChange("update",t,e)}resolveIndex(t){return"number"==typeof t?t:this.recordList.findIndex(e=>e.id===t)}getAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return r(this.recordList[e])}updateAnnotationStyle(t){const e=this.resolveIndex(t);return!(e<0||e>=this.recordList.length)&&(this.recordList[e].style=this.getCurrentStyle(),this.notifyUpdate(e),!0)}setLineStyle(t){this.lineStyle=t}setVertexStyle(t){this.vertexStyle=Object.assign(Object.assign({},this.vertexStyle),t),t.fillColor&&(this.strokeStyle=t.fillColor)}getLineStyle(){return this.lineStyle}getVertexStyle(){return Object.assign({},this.vertexStyle)}getAnnotationStyle(t){return t.style||this.getCurrentStyle()}withdraw(){if(this.operate.data.length>0){const t="polygon"===this.operate.type?"polygon":"rect";return this.strategyOf(t).withdrawInProgress(this),!0}if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.recordList.splice(e,0,t),!0}return this.recordList.length>0&&(this.recordList.pop(),!0)}selectAnnotation(t,e){var n;const i=this.resolveIndex(t);if(i<0||i>=this.recordList.length)return this.deselectAnnotation(),!1;const s=this.recordList[i],o=void 0!==(null==e?void 0:e.lock)?!!e.lock:(null===(n=this.selectedAnnotation)||void 0===n?void 0:n.index)===i&&!0===this.selectedAnnotation.locked;return this.selectedAnnotation={index:i,type:s.type,locked:o},!0}deselectAnnotation(){this.selectedAnnotation=null,this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null}deleteSelectedAnnotation(){if(!this.selectedAnnotation)return!1;const t=this.selectedAnnotation.index,e=this.recordList[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.recordList.splice(t,1),this.deselectAnnotation(),this.notifyChange("delete",t,e),!0}startMovingAnnotation(t){return!(!this.selectedAnnotation||!0===this.selectedAnnotation.locked)&&(this.isMovingAnnotation=!0,this.annotationMoveStart={x:t.clientX,y:t.clientY},!0)}updateMoveStart(t){this.annotationMoveStart=t}finishMovingAnnotation(){var t;const e=this.isMovingAnnotation||this.isResizing;if(this.isMovingAnnotation=!1,this.isResizing=!1,this.activeHandle=null,this.originalRect=null,this.originalPolygon=null,e&&this.selectedAnnotation){const e=this.recordList[this.selectedAnnotation.index];(null==e?void 0:e.title)&&this.autoAdjustTitlePosition(e,e.title),this.notifyUpdate(this.selectedAnnotation.index),null===(t=this.renderCallback)||void 0===t||t.call(this)}}clear(){this.recordList=[],this.operate={type:"rect",data:[],status:"pending"},this.isDrawing=!1,this.tempPolygonPoint=null,this.deselectAnnotation(),this.deleteHistory=[]}getAnnotations(){return this.recordList.map(t=>r(t))}getSelectedAnnotation(){if(!this.selectedAnnotation)return null;const t=this.recordList[this.selectedAnnotation.index];return t?{index:this.selectedAnnotation.index,type:this.selectedAnnotation.type,data:r(t)}:null}setTitleStyle(t){this.titleStyle=Object.assign(Object.assign({},this.titleStyle),t)}getTitleStyle(){return Object.assign({},this.titleStyle)}setTitlePosition(t){this.titlePosition=Object.assign(Object.assign({},this.titlePosition),t)}getTitlePosition(){return Object.assign({},this.titlePosition)}getEffectiveTitleStyle(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titleStyle),e.titleStyle||{})}getEffectiveTitlePosition(t){const e=this.getAnnotationStyle(t);return Object.assign(Object.assign({},this.titlePosition),e.titlePosition||{})}captureTitleStyleSnapshot(t){t.style||(t.style=this.getCurrentStyle()),t.style.titleStyle=Object.assign({},this.titleStyle),t.style.titlePositionExplicit||(t.style.titlePosition=Object.assign({},this.titlePosition))}autoAdjustTitlePosition(t,e){var n,i,s;if(!e||(null===(n=t.style)||void 0===n?void 0:n.titlePositionExplicit))return;const{originalWidth:o,originalHeight:a,initialScale:r,scale:h}=this.viewport;if(o<=0||a<=0)return;const l=u(t);if(!l)return;const d=r>0?r:h>0?h:1,c={x:l.x*d,y:l.y*d,width:l.width*d,height:l.height*d},x=this.getEffectiveTitleStyle(t),f=x.font||"12px Arial",p=f.match(/(\d+)px/),y=(p?parseInt(p[1]):12)+2*(null!==(i=x.paddingY)&&void 0!==i?i:3),v=this.measureTitleWidth,M=v?{minX:0,minY:0,maxX:o*d,maxY:a*d}:{minX:Number.NEGATIVE_INFINITY,minY:0,maxX:Number.POSITIVE_INFINITY,maxY:a*d},w=v?v(e,f)+2*(null!==(s=x.paddingX)&&void 0!==s?s:6):0,m=Object.assign({},this.titlePosition),A=g({anchor:c,boxWidth:w,boxHeight:y,position:m,bounds:M});t.style||(t.style=this.getCurrentStyle()),t.style.titlePosition=Object.assign(Object.assign({},m),{vertical:A.vertical,align:A.align,offsetX:A.offsetX})}adjustTitlePositions(){this.viewport.originalWidth<=0||this.viewport.originalHeight<=0||this.recordList.forEach(t=>{var e;t.title&&!(null===(e=t.style)||void 0===e?void 0:e.titlePositionExplicit)&&this.autoAdjustTitlePosition(t,t.title)})}setAnnotationTitleStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titleStyle=Object.assign(Object.assign({},i.style.titleStyle||this.titleStyle),e),this.notifyUpdate(n),!0}setAnnotationTitlePosition(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.style||(i.style=this.getCurrentStyle()),i.style.titlePosition=Object.assign(Object.assign({},i.style.titlePosition||this.titlePosition),e),i.style.titlePositionExplicit=!0,this.notifyUpdate(n),!0}createTitleInput(){this.container&&(this.titleInput=document.createElement("input"),this.titleInput.type="text",this.titleInput.style.position="absolute",this.titleInput.style.zIndex="99998",this.titleInput.style.display="none",this.titleInput.style.outline="none",this.titleInput.style.border="1px solid #00D9FF",this.titleInput.style.borderRadius="4px",this.titleInput.style.padding="4px 8px",this.titleInput.style.fontSize="13px",this.titleInput.style.fontFamily="Arial, sans-serif",this.titleInput.style.backgroundColor="#ffffff",this.titleInput.style.color="#333",this.titleInput.style.boxShadow="0 2px 8px rgba(0,0,0,0.3)",this.titleInput.style.minWidth="80px",this.titleInput.style.maxWidth="200px",this.titleInput.placeholder=this.titleStyle.placeholder||"输入标题...",this.titleInput.addEventListener("blur",()=>{this.finishTitleEditing()}),this.titleInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?this.finishTitleEditing():"Escape"===t.key&&(t.preventDefault(),this.cancelTitleEditing())}),this.container.appendChild(this.titleInput))}setTitle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.recordList.length)return!1;const i=this.recordList[n];return i.title=e||void 0,e&&(this.captureTitleStyleSnapshot(i),this.autoAdjustTitlePosition(i,e)),this.notifyUpdate(n),!0}getTitle(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.recordList.length))return this.recordList[e].title}startTitleEditing(t){if(!this.enableTitle||!this.titleInput||t<0||t>=this.recordList.length)return!1;const e=this.recordList[t];let n,i;if(this.editingTitleIndex=t,this.deselectAnnotation(),"rect"===e.type){const t=e.data[0];n=this.viewport.offset.x+t.start.x*this.viewport.scale,i=this.viewport.offset.y+t.start.y*this.viewport.scale}else{const t=e.data[0];n=this.viewport.offset.x+t.point.x*this.viewport.scale,i=this.viewport.offset.y+t.point.y*this.viewport.scale}return this.titleInput.value=e.title||"",this.titleInput.placeholder=this.getEffectiveTitleStyle(e).placeholder||"输入标题...",this.titleInput.style.left=`${n}px`,this.titleInput.style.top=i-32+"px",this.titleInput.style.display="block",setTimeout(()=>{this.titleInput&&(this.titleInput.focus(),this.titleInput.select())},10),!0}finishTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex,e=this.titleInput.value.trim();if(t>=0&&t<this.recordList.length){const n=this.recordList[t];n.title=e||void 0,e&&(this.captureTitleStyleSnapshot(n),this.autoAdjustTitlePosition(n,e)),this.notifyUpdate(t),this.selectAnnotation(t)}return this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}cancelTitleEditing(){if(!this.titleInput||null===this.editingTitleIndex)return!1;const t=this.editingTitleIndex;return t>=0&&t<this.recordList.length&&this.selectAnnotation(t),this.resetTitleEditingState(),this.renderCallback&&this.renderCallback(),!0}resetTitleEditingState(){this.titleInput&&(this.titleInput.style.display="none"),this.editingTitleIndex=null}destroyTitleInput(){this.titleInput&&this.titleInput.parentNode&&(this.titleInput.parentNode.removeChild(this.titleInput),this.titleInput=null)}}class m extends w{startRectDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("rect").startDrawing(this,t)}updateRectDrawing(t){this.isDrawing&&"rect"===this.operate.type&&(t=this.clampToImageBounds(t),this.strategyOf("rect").updateDrawing(this,t))}finishRectDrawing(){return this.strategyOf("rect").finishDrawing(this)}startPolygonDrawing(t){t=this.clampToImageBounds(t),this.strategyOf("polygon").startDrawing(this,t)}addPolygonPoint(t){return!(!this.isDrawing||"polygon"!==this.operate.type)&&(t=this.clampToImageBounds(t),this.strategyOf("polygon").addPoint(this,t))}updatePolygonTempPoint(t){this.strategyOf("polygon").updateDrawing(this,this.clampToImageBounds(t))}finishPolygonDrawing(){return this.strategyOf("polygon").finishDrawing(this)}cancelDrawing(){const t="polygon"===this.operate.type?"polygon":"rect";this.strategyOf(t).cancelDrawing(this)}moveSelectedAnnotation(t,e){if(!this.selectedAnnotation)return!1;const n=this.recordList[this.selectedAnnotation.index];return!!n&&(this.strategyOf(n.type).move(n,t,e),this.clampRecordToImageBounds(n),!0)}startResizing(t,e){if(!this.selectedAnnotation)return!1;this.activeHandle=t,this.isResizing=!0;const n=this.recordList[this.selectedAnnotation.index];return"rect"===n.type?this.originalRect=this.strategyOf("rect").snapshotForResize(n):"polygon"===n.type&&(this.originalPolygon=this.strategyOf("polygon").snapshotForResize(n)),!0}resizeRect(t){if(!this.selectedAnnotation||"rect"!==this.selectedAnnotation.type||!this.originalRect||!this.activeHandle)return!1;if(this.activeHandle.index<0||this.activeHandle.index>3)return!1;const e=this.recordList[this.selectedAnnotation.index],n=this.clampToImageBounds(t),i=this.strategyOf("rect").resize(e,this.activeHandle.index,n,this.originalRect);return"number"==typeof i&&(this.activeHandle.index=i),!0}resizePolygon(t){var e;if(!this.selectedAnnotation||"polygon"!==this.selectedAnnotation.type||!this.activeHandle)return!1;const n=this.recordList[this.selectedAnnotation.index],i=this.activeHandle.index,s=n.data;return!(i<0||i>=s.length)&&(this.strategyOf("polygon").resize(n,i,this.clampToImageBounds(t),null!==(e=this.originalPolygon)&&void 0!==e?e:[]),!0)}getAnnotationAtPoint(t){for(let e=this.recordList.length-1;e>=0;e--){const n=this.recordList[e],i=n.type;if(this.strategyOf(i).hitTest(n,t))return{index:e,type:i}}return null}getHandleAtPoint(t,e){if(!this.selectedAnnotation)return null;if(!0===this.selectedAnnotation.locked)return null;const n=this.recordList[this.selectedAnnotation.index],i=this.selectionStyle.handleSize,s=i/2,o=this.selectedAnnotation.type,a=this.strategyOf(o).getHandles(n,this.viewport,i);for(const n of a)if(t>=n.x-s&&t<=n.x+s&&e>=n.y-s&&e<=n.y+s)return"rect"===o?{type:"rect-corner",index:n.index}:{type:"polygon-vertex",index:n.index};return null}}class A{constructor(t,e,n,i,s){this.viewport=t,this.container=e,this.ctx=n,this.renderCallback=i,this.changeCallback=s,this.textAnnotations=[],this.editingTextIndex=null,this.currentEditingIndex=null,this.movingTextIndex=null,this.isTextMoving=!1,this.textMoveStart={x:0,y:0},this.textBeforeEditing="",this.selectedTextIndex=null,this.clampEnabled=!0,this.textInput=null,this.deleteHistory=[],this.defaultInputStyle={border:"2px solid #00D9FF",borderRadius:"6px",padding:"6px 10px",fontSize:"16px",fontFamily:"Arial, sans-serif",backgroundColor:"#ffffff",color:"#333",boxShadow:"0 4px 12px rgba(0,0,0,0.3)",minWidth:"60px",maxWidth:"200px"},this.textStyle={font:"16px Arial",color:"#FFD700",padding:6,backgroundColor:"rgba(0,0,0,0.6)",borderRadius:4,selectedBorderColor:"#00D9FF",selectedBackgroundColor:"rgba(0,217,255,0.15)",inputStyle:Object.assign({},this.defaultInputStyle)},this.createTextInput()}createTextInput(){this.textInput=document.createElement("input"),this.textInput.type="text",this.textInput.style.position="absolute",this.textInput.style.zIndex="99999",this.textInput.style.display="none",this.textInput.style.outline="none",this.textInput.style.width="fit-content",this.textInput.placeholder="输入文字...",this.applyInputStyle(),this.textInput.addEventListener("blur",()=>{this.finishEditing(),this.renderCallback&&this.renderCallback()}),this.textInput.addEventListener("keydown",t=>{t.stopPropagation(),"Enter"===t.key?(this.finishEditing(),this.renderCallback&&this.renderCallback()):"Escape"===t.key?(t.preventDefault(),this.cancelEditing()):"Delete"===t.key&&""===this.textInput.value&&(t.preventDefault(),this.deleteEditingAnnotation())}),this.textInput.addEventListener("input",()=>{this.adjustInputWidth()}),this.container.appendChild(this.textInput)}applyInputStyle(){if(!this.textInput)return;const t=Object.assign(Object.assign({},this.defaultInputStyle),this.textStyle.inputStyle);this.textInput.style.border=t.border,this.textInput.style.borderRadius=t.borderRadius,this.textInput.style.padding=t.padding,this.textInput.style.fontSize=t.fontSize,this.textInput.style.fontFamily=t.fontFamily,this.textInput.style.backgroundColor=t.backgroundColor,this.textInput.style.color=t.color,this.textInput.style.boxShadow=t.boxShadow,this.textInput.style.minWidth=t.minWidth,this.textInput.style.maxWidth=t.maxWidth}setTextStyle(t){this.textStyle=Object.assign(Object.assign({},this.textStyle),t),this.applyInputStyle()}setInputStyle(t){this.textStyle.inputStyle=Object.assign(Object.assign({},this.textStyle.inputStyle),t),this.applyInputStyle()}setSelectionStyle(t){void 0!==t.selectedBorderColor&&(this.textStyle.selectedBorderColor=t.selectedBorderColor),void 0!==t.selectedBackgroundColor&&(this.textStyle.selectedBackgroundColor=t.selectedBackgroundColor)}getCurrentStyle(){return{font:this.textStyle.font,color:this.textStyle.color,backgroundColor:this.textStyle.backgroundColor}}notifyChange(t,e,n){p(this.changeCallback,"text",t,e,n)}resolveIndex(t){return"number"==typeof t?t:this.textAnnotations.findIndex(e=>e.id===t)}getTextAnnotation(t){const e=this.resolveIndex(t);if(!(e<0||e>=this.textAnnotations.length))return r(this.textAnnotations[e])}updateTextAnnotationStyle(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];return i.style=Object.assign(Object.assign({},i.style||this.getCurrentStyle()),e),this.notifyChange("update",n,this.textAnnotations[n]),!0}clampToImageBounds(t){return f(this.viewport,t,this.clampEnabled)}addTextAnnotation(t,e,n=""){var i;const s=this.clampToImageBounds({x:t,y:e});t=s.x,e=s.y,this.ctx.font=this.textStyle.font;const o=n||"输入文字...",a=this.ctx.measureText(o);let r;if(a.actualBoundingBoxAscent&&a.actualBoundingBoxDescent)r=a.actualBoundingBoxAscent+a.actualBoundingBoxDescent;else{r=1.2*parseInt((null===(i=this.textStyle.font.match(/\d+/))||void 0===i?void 0:i[0])||"16")}const l={id:h(),position:{x:t,y:e},text:n,style:this.getCurrentStyle(),width:Math.max(a.width,60),height:r};this.textAnnotations.push(l);const d=this.textAnnotations.length-1;return this.notifyChange("create",d,l),this.deleteHistory=[],this.startEditing(d),d}updateTextAnnotation(t,e){const n=this.resolveIndex(t);if(n<0||n>=this.textAnnotations.length)return!1;const i=this.textAnnotations[n];i.text=e,this.ctx.font=this.textStyle.font;const s=this.ctx.measureText(e);return i.width=s.width,i.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",n,this.textAnnotations[n]),!0}moveTextAnnotation(t,e,n){const i=this.resolveIndex(t);return!(i<0||i>=this.textAnnotations.length)&&(this.textAnnotations[i].position={x:e,y:n},this.notifyChange("update",i,this.textAnnotations[i]),!0)}removeTextAnnotation(t){const e=this.resolveIndex(t);if(e<0||e>=this.textAnnotations.length)return!1;const n=this.textAnnotations[e];return this.deleteHistory.push({annotation:Object.assign({},n),index:e}),this.textAnnotations.splice(e,1),this.notifyChange("delete",e,n),this.editingTextIndex===e?this.resetEditingState():null!==this.editingTextIndex&&this.editingTextIndex>e&&this.editingTextIndex--,this.movingTextIndex===e?this.endTextMoving():null!==this.movingTextIndex&&this.movingTextIndex>e&&this.movingTextIndex--,!0}clearTextAnnotations(){this.textAnnotations=[],this.selectedTextIndex=null,this.cancelEditing(),this.deleteHistory=[]}startEditing(t){if(!this.textInput||t<0||t>=this.textAnnotations.length)return!1;const e=this.textAnnotations[t];this.editingTextIndex=t,this.currentEditingIndex=t,this.textBeforeEditing=e.text;const n=this.viewport.offset.x+e.position.x*this.viewport.scale,i=this.viewport.offset.y+e.position.y*this.viewport.scale;return this.textInput.value=e.text,this.textInput.style.left=`${n}px`,this.textInput.style.top=`${i}px`,this.textInput.style.display="block",this.adjustInputWidth(),setTimeout(()=>{this.textInput&&(this.textInput.focus(),this.textInput.select())},10),!0}finishEditing(){if(!this.textInput)return!1;const t=this.currentEditingIndex,e=this.textInput.value.trim();if(null===t||t<0||t>=this.textAnnotations.length)return this.resetEditingState(),!1;if(""===e){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}else{const n=this.textAnnotations[t];n.text=e,this.ctx.font=this.textStyle.font;const i=this.ctx.measureText(n.text);n.width=i.width,n.height=1.2*parseInt(this.textStyle.font),this.notifyChange("update",t,n)}return this.resetEditingState(),!0}cancelEditing(){if(!this.textInput||null===this.editingTextIndex)return!1;this.textInput.value=this.textBeforeEditing;const t=this.editingTextIndex;if(t>=0&&t<this.textAnnotations.length){if(""===this.textAnnotations[t].text&&""===this.textBeforeEditing){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}}return this.resetEditingState(),!0}deleteEditingAnnotation(){if(null===this.editingTextIndex)return!1;const t=this.editingTextIndex;if(this.textInput&&(this.textInput.style.display="none"),t>=0&&t<this.textAnnotations.length){const e=this.textAnnotations[t];this.textAnnotations.splice(t,1),this.notifyChange("delete",t,e)}return this.resetEditingState(),!0}resetEditingState(){this.textInput&&(this.textInput.style.display="none"),this.editingTextIndex=null,this.currentEditingIndex=null,this.textBeforeEditing=""}adjustInputWidth(){if(!this.textInput||null===this.editingTextIndex)return;this.ctx.font=this.textStyle.font;const t=this.textInput.value||this.textInput.placeholder||"",e=this.ctx.measureText(t).width,n=Math.min(Math.max(e+24,60),200);this.textInput.style.width=`${n}px`}startMoving(t,e){return!(e<0||e>=this.textAnnotations.length)&&(this.movingTextIndex=e,this.isTextMoving=!0,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}moveAnnotation(t){if(!this.isTextMoving||null===this.movingTextIndex)return!1;const e=t.clientX-this.textMoveStart.x,n=t.clientY-this.textMoveStart.y,i=this.textAnnotations[this.movingTextIndex];return!!i&&(i.position.x+=e/this.viewport.scale,i.position.y+=n/this.viewport.scale,this.textMoveStart={x:t.clientX,y:t.clientY},!0)}finishMoving(){if(this.isTextMoving=!1,null!==this.movingTextIndex){const t=this.textAnnotations[this.movingTextIndex];t&&this.notifyChange("update",this.movingTextIndex,t)}this.movingTextIndex=null}endTextMoving(){this.isTextMoving=!1,this.movingTextIndex=null}isEditingVisible(){var t;return"block"===(null===(t=this.textInput)||void 0===t?void 0:t.style.display)}checkTextClick(t,e){for(let n=this.textAnnotations.length-1;n>=0;n--){const i=this.textAnnotations[n],s=this.viewport.offset.x+i.position.x*this.viewport.scale,o=this.viewport.offset.y+i.position.y*this.viewport.scale,a=Math.max(i.width,60)+2*this.textStyle.padding,r=i.height+2*this.textStyle.padding;if(t>=s&&t<=s+a&&e>=o&&e<=o+r)return n}return null}checkTextClickForMove(t){const e=this.checkTextClick(t.offsetX,t.offsetY);return null!==e?(this.startMoving(t,e),{index:e,handled:!0}):{index:-1,handled:!1}}getTextAnnotations(){return this.textAnnotations.map(t=>r(t))}withdraw(){if(this.deleteHistory.length>0){const{annotation:t,index:e}=this.deleteHistory.pop();return this.textAnnotations.splice(e,0,t),!0}return this.textAnnotations.length>0&&(this.textAnnotations.pop(),!0)}selectTextAnnotation(t){return t<0||t>=this.textAnnotations.length?(this.deselectTextAnnotation(),!1):(this.selectedTextIndex=t,null!==this.editingTextIndex&&this.finishEditing(),!0)}deselectTextAnnotation(){this.selectedTextIndex=null}deleteSelectedTextAnnotation(){if(null===this.selectedTextIndex)return!1;const t=this.selectedTextIndex,e=this.textAnnotations[t];return this.deleteHistory.push({annotation:Object.assign({},e),index:t}),this.textAnnotations.splice(t,1),this.selectedTextIndex=null,this.notifyChange("delete",t,e),null!==this.editingTextIndex&&this.editingTextIndex>t&&this.editingTextIndex--,null!==this.movingTextIndex&&this.movingTextIndex>t&&this.movingTextIndex--,!0}getSelectedTextAnnotation(){if(null===this.selectedTextIndex)return null;const t=this.textAnnotations[this.selectedTextIndex];return t?{index:this.selectedTextIndex,data:r(t)}:null}destroy(){this.textInput&&this.textInput.parentNode&&this.textInput.parentNode.removeChild(this.textInput)}}function I(t,e){switch(e){case"dashed":t.setLineDash([10,5]);break;case"dotted":t.setLineDash([2,4]);break;default:t.setLineDash([])}}class T{draw(t,e,n,i){const s=n.data[0];t.strokeRect(e.offset.x+s.start.x*e.scale,e.offset.y+s.start.y*e.scale,s.width*e.scale,s.height*e.scale)}drawInProgress(t,e,n){const i=n.operate.data[0];t.strokeRect(e.offset.x+i.start.x*e.scale,e.offset.y+i.start.y*e.scale,i.width*e.scale,i.height*e.scale)}drawSelection(t,e,n,i,s){const o=n.data[0],a=e.offset.x+o.start.x*e.scale,r=e.offset.y+o.start.y*e.scale,h=o.width*e.scale,l=o.height*e.scale;if(t.fillStyle=i.fillColor,t.fillRect(a,r,h,l),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.strokeRect(a,r,h,l),s)return;const d=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),t.fillRect(a-d/2,r-d/2,d,d),t.fillRect(a+h-d/2,r-d/2,d,d),t.fillRect(a-d/2,r+l-d/2,d,d),t.fillRect(a+h-d/2,r+l-d/2,d,d)}drawForExport(t,e,n){const i=e.data[0];t.strokeRect(i.start.x,i.start.y,i.width,i.height)}getTitleAnchor(t,e){return u(t,e)}}class S{constructor(t){this.store=t}draw(t,e,n,i){const s=i.vertexStyle||this.store.getVertexStyle();this.drawPolygon(t,e,n.data,"fullfilled"===n.status,s)}drawInProgress(t,e,n){const i=n.operate.data,s=n.tempPolygonPoint;if(t.beginPath(),i.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),s){const n=Math.round(e.offset.x+s.x*e.scale),i=Math.round(e.offset.y+s.y*e.scale);t.lineTo(n,i)}if(t.stroke(),this.drawPolygonVertices(t,e,i,n.getVertexStyle()),s){const i=n.getVertexStyle(),o=Math.round(e.offset.x+s.x*e.scale),a=Math.round(e.offset.y+s.y*e.scale),r=i.size/2;switch(t.fillStyle=i.fillColor,t.strokeStyle=i.strokeColor,t.lineWidth=i.strokeWidth,t.beginPath(),i.shape){case"square":t.rect(o-r,a-r,2*r,2*r);break;case"diamond":t.moveTo(o,a-r),t.lineTo(o+r,a),t.lineTo(o,a+r),t.lineTo(o-r,a),t.closePath();break;default:t.arc(o,a,r,0,2*Math.PI)}t.fill(),i.strokeWidth>0&&t.stroke()}}drawSelection(t,e,n,i,s){const o=n.data;if(t.beginPath(),o.forEach((n,i)=>{const s=e.offset.x+n.point.x*e.scale,o=e.offset.y+n.point.y*e.scale;0===i?t.moveTo(s,o):t.lineTo(s,o)}),t.closePath(),t.fillStyle=i.fillColor,t.fill(),t.strokeStyle=i.strokeColor,t.lineWidth=2,t.setLineDash([5,5]),t.stroke(),s)return;const a=i.handleSize;t.fillStyle=i.handleColor,t.setLineDash([]),o.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),s=Math.round(e.offset.y+n.point.y*e.scale);t.fillRect(i-a/2,s-a/2,a,a)})}drawForExport(t,e,n){if("fullfilled"!==e.status)return;const i=e.data;t.beginPath(),i.forEach((e,n)=>{0===n?t.moveTo(e.point.x,e.point.y):t.lineTo(e.point.x,e.point.y)});const s=e.data[0];t.lineTo(s.point.x,s.point.y),t.stroke(),i.forEach(e=>{t.beginPath(),t.arc(e.point.x,e.point.y,4,0,2*Math.PI),t.fillStyle=n.strokeColor,t.fill()})}getTitleAnchor(t,e){return u(t,e)}drawPolygon(t,e,n,i,s){if(0!==n.length){if(t.beginPath(),n.forEach((n,i)=>{const s=Math.round(e.offset.x+n.point.x*e.scale),o=Math.round(e.offset.y+n.point.y*e.scale);0===i?t.moveTo(s,o):t.lineTo(s,o)}),i&&n.length>1){const i=n[0];t.lineTo(e.offset.x+i.point.x*e.scale,e.offset.y+i.point.y*e.scale)}t.stroke(),this.drawPolygonVertices(t,e,n,s)}}drawPolygonVertices(t,e,n,i){const s=i||this.store.getVertexStyle(),o=s.size/2;n.forEach(n=>{const i=Math.round(e.offset.x+n.point.x*e.scale),a=Math.round(e.offset.y+n.point.y*e.scale);switch(t.fillStyle=s.fillColor,t.strokeStyle=s.strokeColor,t.lineWidth=s.strokeWidth,t.beginPath(),s.shape){case"square":t.rect(i-o,a-o,2*o,2*o);break;case"diamond":t.moveTo(i,a-o),t.lineTo(i+o,a),t.lineTo(i,a+o),t.lineTo(i-o,a),t.closePath();break;default:t.arc(i,a,o,0,2*Math.PI)}t.fill(),s.strokeWidth>0&&t.stroke()})}}class b{constructor(t,e,n,i){this.ctx=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.shapeRenderers={rect:new T,polygon:new S(n)}}render(t){this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.drawBackgroundImage(t),this.drawAnnotations(),function(t,e,n){const i=n.textStyle;n.textAnnotations.forEach((s,o)=>{if(n.editingTextIndex===o&&n.isEditingVisible())return;if(!s.text)return;const a=s.style||{font:i.font,color:i.color,backgroundColor:i.backgroundColor},r=e.offset.x+s.position.x*e.scale,h=e.offset.y+s.position.y*e.scale,l=n.selectedTextIndex===o;t.font=a.font;const d=t.measureText(s.text),c=d.actualBoundingBoxAscent||.8*s.height,g=c+(d.actualBoundingBoxDescent||.2*s.height),x=i.borderRadius,u=r,f=h,p=s.width+2*i.padding,y=g+2*i.padding;t.fillStyle=a.backgroundColor,t.beginPath(),t.roundRect(u,f,p,y,x),t.fill(),l&&(t.strokeStyle=i.selectedBorderColor,t.lineWidth=2,t.setLineDash([5,5]),t.beginPath(),t.roundRect(u,f,p,y,x),t.stroke(),t.setLineDash([]));const v=r+i.padding,M=h+i.padding+c;t.fillStyle=a.color,t.fillText(s.text,v,M)})}(this.ctx,this.viewport,this.textManager)}drawBackgroundImage(t){this.ctx.drawImage(t,this.viewport.offset.x,this.viewport.offset.y,this.viewport.originalWidth*this.viewport.scale,this.viewport.originalHeight*this.viewport.scale)}drawAnnotations(){this.annotationManager.recordList.forEach(t=>{const e=this.annotationManager.getAnnotationStyle(t);this.ctx.strokeStyle=e.strokeColor,this.ctx.lineWidth=e.lineWidth,I(this.ctx,e.lineStyle||"solid"),this.ctx.fillStyle=this.ctx.strokeStyle,"rect"===t.type?this.shapeRenderers.rect.draw(this.ctx,this.viewport,t,e):"polygon"===t.type&&this.shapeRenderers.polygon.draw(this.ctx,this.viewport,t,e),this.annotationManager.enableTitle&&t.title&&this.drawAnnotationTitle(t)}),this.annotationManager.operate.data.length>0&&(this.ctx.strokeStyle=this.annotationManager.strokeStyle,this.ctx.lineWidth=this.annotationManager.lineWidth,this.ctx.fillStyle=this.ctx.strokeStyle,I(this.ctx,this.annotationManager.lineStyle),"rect"===this.annotationManager.operate.type?this.shapeRenderers.rect.drawInProgress(this.ctx,this.viewport,this.annotationManager):"polygon"===this.annotationManager.operate.type&&this.shapeRenderers.polygon.drawInProgress(this.ctx,this.viewport,this.annotationManager)),this.ctx.setLineDash([]),this.drawSelectionHighlight()}drawSelectionHighlight(){const t=this.annotationManager.selectedAnnotation;if(!t)return;const e=this.annotationManager.recordList[t.index];if(!e)return;const n=this.annotationManager.selectionStyle,i=!0===t.locked;this.ctx.save(),"rect"===e.type?this.shapeRenderers.rect.drawSelection(this.ctx,this.viewport,e,n,i):"polygon"===e.type&&this.shapeRenderers.polygon.drawSelection(this.ctx,this.viewport,e,n,i),this.ctx.restore()}drawAnnotationTitle(t){var e,n,i;if(!t.title)return;const s=this.annotationManager.getEffectiveTitleStyle(t),o=this.annotationManager.getEffectiveTitlePosition(t),a=s.font||"12px Arial",r=s.color||"#FFFFFF",h=s.backgroundColor||"rgba(0, 0, 0, 0.7)",l=null!==(e=s.paddingX)&&void 0!==e?e:6,d=null!==(n=s.paddingY)&&void 0!==n?n:3,c=null!==(i=s.borderRadius)&&void 0!==i?i:4;this.ctx.save(),this.ctx.font=a;const g=this.ctx.measureText(t.title).width,u=a.match(/(\d+)px/),f=u?parseInt(u[1]):12,p=("rect"===t.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(t,this.viewport);if(!p)return void this.ctx.restore();const y=g+2*l,v=f+2*d,{x:M,y:w}=x({anchor:p,boxWidth:y,boxHeight:v,position:o});this.ctx.fillStyle=h,this.ctx.setLineDash([]),this.ctx.beginPath(),this.ctx.roundRect(M,w,y,v,c),this.ctx.fill(),this.ctx.fillStyle=r,this.ctx.textAlign="left",this.ctx.textBaseline="top",this.ctx.fillText(t.title,M+l,w+d),this.ctx.restore()}drawForExport(t,e,n,i){t.drawImage(e,0,0,n,i),this.annotationManager.recordList.forEach(e=>{const n=this.annotationManager.getAnnotationStyle(e);t.strokeStyle=n.strokeColor,t.lineWidth=n.lineWidth,"rect"===e.type?this.shapeRenderers.rect.drawForExport(t,e,n):"polygon"===e.type&&this.shapeRenderers.polygon.drawForExport(t,e,n)}),this.textManager.textAnnotations.forEach(e=>{const n=this.textManager.textStyle,i=e.style||{font:n.font,color:n.color,backgroundColor:n.backgroundColor};t.font=i.font;const s=t.measureText(e.text),o=s.actualBoundingBoxAscent||.8*e.height,a=o+(s.actualBoundingBoxDescent||.2*e.height),r=e.position.x,h=e.position.y,l=e.width+2*n.padding,d=a+2*n.padding,c=n.borderRadius;t.fillStyle=i.backgroundColor,t.roundRect?(t.roundRect(r,h,l,d,c),t.fill()):t.fillRect(r,h,l,d),t.fillStyle=i.color,t.fillText(e.text,e.position.x+n.padding,e.position.y+n.padding+o)}),this.annotationManager.enableTitle&&this.annotationManager.recordList.forEach(e=>{var n,i,s;if(!e.title)return;const o=this.annotationManager.getEffectiveTitleStyle(e),a=this.annotationManager.getEffectiveTitlePosition(e),r=o.font||"12px Arial",h=o.color||"#FFFFFF",l=o.backgroundColor||"rgba(0, 0, 0, 0.7)",d=null!==(n=o.paddingX)&&void 0!==n?n:6,c=null!==(i=o.paddingY)&&void 0!==i?i:3,g=null!==(s=o.borderRadius)&&void 0!==s?s:4;t.font=r;const u=t.measureText(e.title).width,f=r.match(/(\d+)px/),p=f?parseInt(f[1]):12,y=("rect"===e.type?this.shapeRenderers.rect:this.shapeRenderers.polygon).getTitleAnchor(e);if(!y)return;const v=u+2*d,M=p+2*c,{x:w,y:m}=x({anchor:y,boxWidth:v,boxHeight:M,position:a});t.fillStyle=l,t.roundRect?(t.roundRect(w,m,v,M,g),t.fill()):t.fillRect(w,m,v,M),t.fillStyle=h,t.textAlign="left",t.textBaseline="top",t.fillText(e.title,w+d,m+c)})}}class C{constructor(t,e,n,i,s,o,a,r,h,l){this.canvas=t,this.viewport=e,this.annotationManager=n,this.textManager=i,this.renderer=s,this.getDrawType=o,this.getBgImage=a,this.renderCallback=r,this.setDrawTypeCallback=h,this.notifyUndo=l,this.isDragging=!1,this.dragStart={x:0,y:0},this.justFinishedMove=!1,this.justDeselected=!1}handleWheel(t){if(t.preventDefault(),!this.getBgImage())return;const e=t.deltaY>0?-.02:.02,n=this.viewport.scale,i=Math.max(this.viewport.minScale,Math.min(n+e,this.viewport.maxScale)),s=this.canvas.getBoundingClientRect(),o=t.clientX-s.left,a=t.clientY-s.top,r=(o-this.viewport.offset.x)/n,h=(a-this.viewport.offset.y)/n;this.viewport.scale=i;const l=r*i+this.viewport.offset.x,d=h*i+this.viewport.offset.y;this.viewport.offset.x+=o-l,this.viewport.offset.y+=a-d,this.viewport.calculateBoundaries(),this.viewport.constrainViewport(),this.viewport.isInitialScale=this.viewport.scale===this.viewport.initialScale,this.renderCallback()}handleMouseDown(t){var e,n;if(0!==t.button)return;const i=this.getDrawType(),s=this.getBgImage();if(this.annotationManager.selectedAnnotation&&s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),void this.renderCallback()}if("text"===i){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(s){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if("rect"===(null==n?void 0:n.type))return this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(e);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();if(this.annotationManager.selectedAnnotation)return this.annotationManager.deselectAnnotation(),void this.renderCallback()}return null!==this.textManager.selectedTextIndex?(this.textManager.deselectTextAnnotation(),void this.renderCallback()):void this.handleTextModeClick(t)}if(!s)return;const o=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if("rect"===i){if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"rect"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.startRectDrawing(o)}else if("polygon"===i){if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e&&"polygon-vertex"===e.type)return this.annotationManager.startResizing(e,o),void this.renderCallback();const n=this.annotationManager.getAnnotationAtPoint(o);return n&&"polygon"===n.type?(this.annotationManager.selectAnnotation(n.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback()):(this.annotationManager.deselectAnnotation(),this.justDeselected=!0,void this.renderCallback())}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();const i=this.annotationManager.getAnnotationAtPoint(o);if("rect"===(null==i?void 0:i.type))return this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();const s=this.annotationManager.getAnnotationAtPoint(o);if("polygon"===(null==s?void 0:s.type))return this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),void this.renderCallback();this.annotationManager.isDrawing?this.checkPolygonPointValid(o)&&this.annotationManager.addPolygonPoint(o):this.annotationManager.startPolygonDrawing(o),this.annotationManager.updatePolygonTempPoint(o),this.renderCallback()}else if("drag"===i){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return this.annotationManager.startResizing(e,o),void this.renderCallback()}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.selectedTextIndex===e?this.textManager.startMoving(t,e):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:e}),void this.renderCallback();if(this.handleRectModeClick(t,o))return;if(this.handlePolygonModeClick(t,o))return;this.isDragging=!0,this.dragStart={x:t.clientX,y:t.clientY},this.canvas.style.cursor="grabbing"}else""===i&&this.handleNoModeClick(t,o)}handleTextModeClick(t){const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return this.textManager.startMoving(t,e),this.canvas.style.cursor="grabbing",this.renderCallback(),!0;const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return this.textManager.addTextAnnotation(n.x,n.y),!0}handleRectModeClick(t,e){var n,i;if("rect"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"rect"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"rect"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handlePolygonModeClick(t,e){var n,i;if("polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)){const n=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(n&&"polygon-vertex"===n.type)return this.annotationManager.startResizing(n,e),this.renderCallback(),!0}const s=this.annotationManager.getAnnotationAtPoint(e);return s&&"polygon"===s.type?(this.annotationManager.selectAnnotation(s.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback(),!0):"polygon"===(null===(i=this.annotationManager.selectedAnnotation)||void 0===i?void 0:i.type)&&(this.annotationManager.deselectAnnotation(),this.renderCallback(),!0)}handleNoModeClick(t,e){const n=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==n)return this.textManager.selectedTextIndex===n?this.textManager.startMoving(t,n):M.selectShapeExclusive(this.annotationManager,this.textManager,{kind:"text",index:n}),void this.renderCallback();this.textManager.deselectTextAnnotation();const i=this.annotationManager.getAnnotationAtPoint(e);i?(this.annotationManager.selectAnnotation(i.index),this.annotationManager.startMovingAnnotation(t),this.renderCallback()):this.annotationManager.deselectAnnotation()}checkPolygonPointValid(t){const e=this.annotationManager.operate.data.length>0?this.annotationManager.operate.data[this.annotationManager.operate.data.length-1]:null;return!e||Math.abs(e.point.x-t.x)>5||Math.abs(e.point.y-t.y)>5}handleMouseMove(t){if(!this.getBgImage())return;const e=this.getDrawType();if(this.isDragging&&"drag"===e){const e=t.clientX-this.dragStart.x,n=t.clientY-this.dragStart.y;return this.viewport.updateOffset(e,n),this.dragStart={x:t.clientX,y:t.clientY},void this.renderCallback()}if(this.textManager.isTextMoving&&null!==this.textManager.movingTextIndex)this.textManager.moveAnnotation(t)&&this.renderCallback();else if((this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&this.annotationManager.selectedAnnotation)this.handleAnnotationMove(t);else{if(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||this.updateCursor(t),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updateRectDrawing(e),this.renderCallback()}if("polygon"===e&&this.annotationManager.isDrawing){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);this.annotationManager.updatePolygonTempPoint(e),this.renderCallback()}}}handleAnnotationMove(t){var e,n;if(this.annotationManager.isResizing&&this.annotationManager.activeHandle){const i=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);return"rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)?this.annotationManager.resizeRect(i):"polygon"===(null===(n=this.annotationManager.selectedAnnotation)||void 0===n?void 0:n.type)&&this.annotationManager.resizePolygon(i),void this.renderCallback()}if(!this.annotationManager.isMovingAnnotation||!this.annotationManager.selectedAnnotation)return;const i=(t.clientX-this.annotationManager.annotationMoveStart.x)/this.viewport.scale,s=(t.clientY-this.annotationManager.annotationMoveStart.y)/this.viewport.scale;this.annotationManager.moveSelectedAnnotation(i,s),this.annotationManager.updateMoveStart({x:t.clientX,y:t.clientY}),this.renderCallback()}isHoverLockedAnnotation(t){return!(!t||!this.annotationManager.selectedAnnotation)&&(!0===this.annotationManager.selectedAnnotation.locked&&t.index===this.annotationManager.selectedAnnotation.index)}updateCursor(t){const e=this.getDrawType();if("text"===e){if(this.getBgImage()){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY);if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}const n=this.annotationManager.getAnnotationAtPoint(e);if(n)return void(this.canvas.style.cursor=this.isHoverLockedAnnotation(n)?"default":"move")}const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);return void(this.canvas.style.cursor=null!==e?"move":"crosshair")}"rect"!==e?"polygon"!==e?"drag"!==e?""!==e?this.canvas.style.cursor="default":this.updateNoModeCursor(t):this.updateDragModeCursor(t):this.updatePolygonModeCursor(t):this.updateRectModeCursor(t)}updateRectModeCursor(t){var e;if("rect"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void(this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updatePolygonModeCursor(t){var e;if("polygon"===(null===(e=this.annotationManager.selectedAnnotation)||void 0===e?void 0:e.type)){if(this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="crosshair")}const n=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),i=this.annotationManager.getAnnotationAtPoint(n);i?this.canvas.style.cursor=this.isHoverLockedAnnotation(i)?"default":"move":null===this.textManager.checkTextClick(t.offsetX,t.offsetY)?this.canvas.style.cursor="crosshair":this.canvas.style.cursor="move"}updateDragModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"grab"}updateNoModeCursor(t){if(this.annotationManager.selectedAnnotation){const e=this.annotationManager.getHandleAtPoint(t.offsetX,t.offsetY);if(e)return void("rect-corner"===e.type?this.canvas.style.cursor=0===e.index||3===e.index?"nwse-resize":"nesw-resize":this.canvas.style.cursor="crosshair")}if(null!==this.textManager.checkTextClick(t.offsetX,t.offsetY))return void(this.canvas.style.cursor="move");const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);this.canvas.style.cursor=n?this.isHoverLockedAnnotation(n)?"default":"move":"default"}handleMouseUp(t){if(this.isDragging){this.isDragging=!1;const t=this.getDrawType();return void(this.canvas.style.cursor="drag"===t?"grab":"default")}if(this.textManager.isTextMoving){this.justFinishedMove=!0,this.textManager.finishMoving();const t=this.getDrawType();"drag"===t?this.canvas.style.cursor="grab":""===t?this.canvas.style.cursor="move":(this.textManager.endTextMoving(),this.canvas.style.cursor="default")}(this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing)&&(this.justFinishedMove=!0,this.annotationManager.finishMovingAnnotation(),this.canvas.style.cursor=this.annotationManager.selectedAnnotation?"move":"default"),this.annotationManager.isDrawing&&"rect"===this.annotationManager.operate.type&&(this.annotationManager.finishRectDrawing(),this.renderCallback())}handleMouseLeave(t){(this.isDragging||this.textManager.isTextMoving||this.annotationManager.isResizing||this.annotationManager.isMovingAnnotation)&&this.handleMouseUp(t)}handleDoubleClick(t){if(!this.getBgImage())return;this.justFinishedMove=!1;const e=this.textManager.checkTextClick(t.offsetX,t.offsetY);if(null!==e)return void this.textManager.startEditing(e);if(this.annotationManager.selectedAnnotation){const e=this.viewport.toImageCoordinates(t.offsetX,t.offsetY),n=this.annotationManager.getAnnotationAtPoint(e);if(n&&n.index===this.annotationManager.selectedAnnotation.index)return void this.annotationManager.startTitleEditing(n.index)}if("polygon"===this.getDrawType()){if(this.annotationManager.isDrawing&&this.annotationManager.operate.data.length<=2)return;this.annotationManager.finishPolygonDrawing(),this.renderCallback()}}handleClick(t){var e;const n=this.getDrawType();!this.getBgImage()||"polygon"!==n||this.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving||(this.justDeselected?this.justDeselected=!1:null===(e=this.annotationManager.selectedAnnotation)||void 0===e||e.type)}handleKeyDown(t){const e=t.target;if(!e||"INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName&&"SELECT"!==e.tagName&&!e.isContentEditable){if("z"===t.key&&(t.ctrlKey||t.metaKey)){return M.withdrawAll(this.annotationManager,this.textManager)&&this.notifyUndo(),void this.renderCallback()}if(" "===t.key)return this.viewport.resetToInitial(),void this.renderCallback();if("Escape"!==t.key){if("Delete"===t.key||"Backspace"===t.key){if(null!==this.textManager.editingTextIndex)return this.textManager.removeTextAnnotation(this.textManager.editingTextIndex),void this.renderCallback();if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.renderCallback();this.annotationManager.selectedAnnotation&&(this.annotationManager.deleteSelectedAnnotation(),this.renderCallback())}}else this.annotationManager.isDrawing?(this.annotationManager.cancelDrawing(),this.renderCallback()):this.annotationManager.selectedAnnotation&&(this.annotationManager.deselectAnnotation(),this.renderCallback())}}}class k{constructor(){this.listeners=new Map}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.delete(e)}emit(t,e){var n;null===(n=this.listeners.get(t))||void 0===n||n.forEach(t=>t(e))}clear(){this.listeners.clear()}}class P{constructor(t){this.canvas=document.createElement("canvas"),this.emitter=new k,this.bgImage=null,this.bgImageSrc="",this.bgImageExt="jpeg",this.drawType="";const{drawType:e,useEvents:n=!0,id:i="container",annotationColor:s,lineStyle:o,vertexStyle:a,textStyle:r,enableTitle:h=!1,clampToImageBounds:d=!0}=t,c=document.getElementById(i);if(!c)throw new Error(`Container with id "${i}" not found`);this.container=c,"absolute"!==c.style.position&&"fixed"!==c.style.position&&"relative"!==c.style.position&&(c.style.position="relative"),this.ctx=this.canvas.getContext("2d"),this.viewport=new l,this.viewport.setSize(c.clientWidth,c.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.canvas.style.cursor="default",this.canvas.style.display="block",c.appendChild(this.canvas),this.annotationManager=new m(this.viewport,this.container,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),this.annotationManager.measureTitleWidth=(t,e)=>(this.ctx.font=e,this.ctx.measureText(t).width),s&&this.annotationManager.setColorConfig(s),o&&this.annotationManager.setLineStyle(o),a&&this.annotationManager.setVertexStyle(a),this.annotationManager.enableTitle=h,h&&this.annotationManager.initTitleSupport(),this.annotationManager.clampEnabled=d,this.textManager=new A(this.viewport,this.container,this.ctx,()=>this.render(),(t,e)=>this.emitter.emit(t,e)),r&&this.textManager.setTextStyle(r),this.textManager.clampEnabled=d,this.renderer=new b(this.ctx,this.viewport,this.annotationManager,this.textManager),this.eventHandler=new C(this.canvas,this.viewport,this.annotationManager,this.textManager,this.renderer,()=>this.drawType,()=>this.bgImage,()=>this.render(),t=>this.setDrawType(t),()=>this.emitter.emit("undo",void 0)),this.events={wheel:t=>this.eventHandler.handleWheel(t),mousedown:t=>this.eventHandler.handleMouseDown(t),mousemove:t=>this.eventHandler.handleMouseMove(t),mouseup:t=>this.eventHandler.handleMouseUp(t),mouseleave:t=>this.eventHandler.handleMouseLeave(t),dblclick:t=>this.eventHandler.handleDoubleClick(t),click:t=>this.eventHandler.handleClick(t),keydown:t=>this.eventHandler.handleKeyDown(t)},this.setDrawType(e||""),n&&this.addEventListeners()}setDrawType(t){"polygon"===this.drawType&&this.annotationManager.isDrawing&&this.annotationManager.operate.data.length>0?console.warn("Cannot switch mode while polygon is being drawn. Please complete or cancel the polygon first."):this.drawType!==t&&(this.annotationManager.operate.data=[],this.annotationManager.isDrawing=!1,this.annotationManager.tempPolygonPoint=null,""!==t&&this.deselectAnnotation(),this.annotationManager.operate.type=t,this.drawType=t,this.canvas.style.cursor="drag"===t?"grab":"text"===t?"text":"default")}drawImage(t){this.bgImageSrc=t,this.bgImageExt=i(t);const e=new Image;e.crossOrigin="anonymous",e.src=t,e.onload=()=>{this.bgImage=e,this.viewport.setOriginalSize(e.width,e.height),this.viewport.calculateInitialView(),this.annotationManager.adjustTitlePositions(),this.render()}}render(){this.renderer.render(this.bgImage)}clear(t=""){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.setDrawType(t),this.render(),this.emitter.emit("clear",void 0)}withdraw(){const t=this.annotationManager.withdraw(),e=this.textManager.withdraw();(t||e)&&(this.render(),this.emitter.emit("undo",void 0))}resize(){const t=this.canvas.parentElement;t&&(this.viewport.setSize(t.clientWidth,t.clientHeight),this.canvas.width=this.viewport.width,this.canvas.height=this.viewport.height,this.canvas.style.width=`${this.viewport.width}px`,this.canvas.style.height=`${this.viewport.height}px`,this.render())}addEventListeners(){this.canvas.addEventListener("mousedown",this.events.mousedown),this.canvas.addEventListener("mousemove",this.events.mousemove),this.canvas.addEventListener("mouseup",this.events.mouseup),this.canvas.addEventListener("mouseleave",this.events.mouseleave),this.canvas.addEventListener("wheel",this.events.wheel),this.canvas.addEventListener("contextmenu",t=>t.preventDefault()),document.addEventListener("keydown",this.events.keydown),this.handleClickEventListener()}handleClickEventListener(){let t=null,e=0;this.canvas.addEventListener("click",n=>{if(this.eventHandler.isDragging||this.annotationManager.isMovingAnnotation||this.annotationManager.isResizing||this.textManager.isTextMoving)return;const i=this.eventHandler.justFinishedMove;i&&(this.eventHandler.justFinishedMove=!1),e++,1===e?t=window.setTimeout(()=>{1!==e||i||this.events.click(n),e=0,t=null},300):2===e&&(this.eventHandler.justFinishedMove=!1,this.events.dblclick(n),e=0,null!==t&&(clearTimeout(t),t=null))})}changeScale(t){if(!this.bgImage)return;const e=a(this.viewport.scale,t),n=this.viewport.width/2,i=this.viewport.height/2,s=this.viewport.scale+e;this.viewport.updateScale(s,n,i),this.render()}clearCanvas(t=!1,e=!0){this.annotationManager.clear(),this.textManager.clearTextAnnotations(),this.textManager.deselectTextAnnotation(),this.emitter.emit("clear",void 0),!t&&e&&(this.bgImage=null,this.bgImageSrc="",this.viewport.setOriginalSize(0,0),this.viewport.reset()),this.ctx.clearRect(0,0,this.viewport.width,this.viewport.height),t&&this.bgImage&&this.render(),"drag"===this.drawType&&(this.canvas.style.cursor="default")}clearAnnotations(){this.clearCanvas(!0,!1)}getAnnotations(){return this.annotationManager.getAnnotations()}getAnnotation(t){return this.annotationManager.getAnnotation(t)}getTextAnnotation(t){return this.textManager.getTextAnnotation(t)}on(t,e){this.emitter.on(t,e)}off(t,e){this.emitter.off(t,e)}setAnnotationTitle(t,e){const n=this.annotationManager.setTitle(t,e);return n&&this.render(),n}getAnnotationTitle(t){return this.annotationManager.getTitle(t)}setTitleStyle(t){this.annotationManager.setTitleStyle(t),this.render()}getTitleStyle(){return this.annotationManager.getTitleStyle()}setTitlePosition(t){this.annotationManager.setTitlePosition(t),this.render()}getTitlePosition(){return this.annotationManager.getTitlePosition()}setAnnotationTitleStyle(t,e){const n=this.annotationManager.setAnnotationTitleStyle(t,e);return n&&this.render(),n}setAnnotationTitlePosition(t,e){const n=this.annotationManager.setAnnotationTitlePosition(t,e);return n&&this.render(),n}getTextAnnotations(){return this.textManager.getTextAnnotations()}exportAnnotationImage(){return new Promise((t,e)=>{if(!this.bgImage)return void e(new Error("No background image loaded"));const n=document.createElement("canvas");n.width=this.viewport.originalWidth,n.height=this.viewport.originalHeight;const i=n.getContext("2d");if(!i)return void e(new Error("Could not create offscreen canvas context"));const s=new Image;s.src=this.bgImageSrc,s.crossOrigin="anonymous",s.onload=()=>{try{this.renderer.drawForExport(i,s,this.viewport.originalWidth,this.viewport.originalHeight);const e=n.toDataURL(`image/${this.bgImageExt}`,.7);t(e)}catch(n){this.exportCurrentViewImage().then(t).catch(t=>e(new Error(`Both methods failed: ${t.message}`)))}},s.onerror=()=>{e(new Error("Failed to load image for export"))}})}exportCurrentViewImage(){return new Promise((t,e)=>{try{t(this.canvas.toDataURL(`image/${this.bgImageExt}`))}catch(t){e(new Error(`Failed to export current view: ${t.message}`))}})}base64ToFile(t,e){return s(t,e)}static base64ToBlob(t){return o(t)}addTextAnnotation(t,e,n=""){this.textManager.addTextAnnotation(t,e,n),this.render()}updateTextAnnotation(t,e){this.textManager.updateTextAnnotation(t,e)&&this.render()}moveTextAnnotation(t,e,n){this.textManager.moveTextAnnotation(t,e,n)&&this.render()}removeTextAnnotation(t){this.textManager.removeTextAnnotation(t)&&this.render()}clearTextAnnotations(){this.textManager.clearTextAnnotations(),this.render()}selectAnnotation(t,e){this.annotationManager.selectAnnotation(t,e)&&this.render()}deselectAnnotation(){this.annotationManager.deselectAnnotation(),this.textManager.deselectTextAnnotation(),this.textManager.editingTextIndex=null,this.render()}getSelectedAnnotation(){const t=this.annotationManager.getSelectedAnnotation();if(t)return t;const e=this.textManager.getSelectedTextAnnotation();return e?{index:e.index,type:"text",data:e.data}:null}deleteSelectedAnnotation(){if(null!==this.textManager.selectedTextIndex)return this.textManager.deleteSelectedTextAnnotation(),void this.render();this.annotationManager.deleteSelectedAnnotation()&&this.render()}moveSelectedAnnotation(t,e){if(this.annotationManager.moveSelectedAnnotation(t,e)){const t=this.annotationManager.selectedAnnotation;t&&this.annotationManager.notifyUpdate(t.index),this.render()}}setAnnotationColor(t){this.annotationManager.setColorConfig(t),this.render()}getAnnotationColor(){return this.annotationManager.getColorConfig()}updateSelectedAnnotationStyle(t){if(void 0!==t){const e=this.annotationManager.updateAnnotationStyle(t);return e&&this.render(),e}const e=this.annotationManager.selectedAnnotation;if(!e)return!1;const n=this.annotationManager.recordList[e.index];return!!n&&(n.style=this.annotationManager.getCurrentStyle(),this.annotationManager.notifyUpdate(e.index),this.render(),!0)}setLineStyle(t){this.annotationManager.setLineStyle(t),this.render()}getLineStyle(){return this.annotationManager.getLineStyle()}setVertexStyle(t){this.annotationManager.setVertexStyle(t),this.render()}getVertexStyle(){return this.annotationManager.getVertexStyle()}setTextStyle(t){this.textManager.setTextStyle(t),this.render()}updateTextAnnotationStyle(t,e){const n=this.textManager.updateTextAnnotationStyle(t,e);return n&&this.render(),n}setTextInputStyle(t){this.textManager.setInputStyle(t)}setTextSelectionStyle(t){this.textManager.setSelectionStyle(t),this.render()}destroy(){this.emitter.clear(),document.removeEventListener("keydown",this.events.keydown),this.textManager.destroy(),this.annotationManager.destroyTitleInput(),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}t.AnnotationManager=m,t.Drawer=P,t.Emitter=k,t.EventHandler=C,t.Renderer=b,t.TextAnnotationManager=A,t.ViewportManager=l,t.base64ToBlob=o,t.base64ToFile=s,t.default=P,t.getImageTypeFromUrl=i,t.getZoomDelta=a,t.isPointInPolygon=n,t.isPointInRect=e,Object.defineProperty(t,"__esModule",{value:!0})}),"undefined"!=typeof ImageAnnotationDrawer&&ImageAnnotationDrawer.default&&(ImageAnnotationDrawer=ImageAnnotationDrawer.default);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "image-annotation-drawer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.3",
|
|
5
5
|
"description": "A lightweight image annotation library based on HTML5 Canvas, supporting rectangles, polygons, text annotations, zoom and drag operations.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.esm.js",
|