UNPKG

lost-sia

Version:

Single Image Annotation Tool

2 lines (1 loc) 9.35 kB
import{jsxs as P,jsx as C,Fragment as Je}from"react/jsx-runtime";import{useState as E,useRef as ye,useEffect as w}from"react";import D from"../models/AnnotationTool.js";import i from"../models/EditorModes.js";import Qe from"../utils/KeyMapper.js";import a from"../models/KeyAction.js";import Ee from"../Annotation/logic/Annotation.js";import Ze from"../models/CanvasAction.js";import qe from"../Annotation/ui/AnnotationComponent.js";import me from"../utils/mouse.js";import N from"../models/AnnotationMode.js";import et from"./LabelInput.js";import{FontAwesomeIcon as tt}from"@fortawesome/react-fontawesome";import{faBan as nt}from"@fortawesome/free-solid-svg-icons";import I from"../models/AnnotationStatus.js";import x from"../utils/transform.js";import ot from"../models/NotificationType.js";import rt from"../utils/TimeUtils.js";import he from"../utils/windowViewport.js";const wt=({annotations:A=[],annotationSettings:W,defaultLabelId:Q,image:Z,isFullscreen:pe=!1,isImageJunk:B=!1,isPolygonSelectionMode:K=!1,polygonOperationResult:F={annotationsToDelete:[],polygonsToCreate:[]},possibleLabels:q,preventScrolling:ee=!0,selectedAnnotation:r,selectedAnnoTool:R,toolbarHeight:X=0,uiConfig:U,onAnnoCreated:Ce,onAnnoCreationFinished:te,onAnnoChanged:ne,onAnnoEditing:xe=g=>{},onNotification:oe=g=>{},onRequestNewAnnoId:z,onSelectAnnotation:v,onSetIsImageJunk:Ae,onSetSelectedTool:Oe=g=>{},onShouldDeleteAnno:re})=>{const[g,O]=E(i.VIEW),[Te,ve]=E(),[se,Me]=E(Q),[k,we]=E({x:-1,y:-1}),[ie,ce]=E(0),V={x:k.x,y:k.y},[u,Y]=E({x:-1,y:-1}),[l,G]=E({x:-1,y:-1}),[m,ae]=E({x:-1,y:-1}),[d,L]=E(1),[c,S]=E({x:0,y:0}),H={x:c.x+ie,y:c.y},[h,$]=E(),[j,b]=E(!1),p=ye(null),y=ye(null),T=((e,t)=>{if(e.x===0||e.y===0||t.x===0||t.y===0)return 0;const n=t.x/e.x,o=t.y/e.y;return Math.min(n,o)})(u,l),De=()=>{if((y==null?void 0:y.current)===null)return{x:0,y:0};const e=u.x*T;if(U.imageCentered&&l.x>e){const f=(l.x-e)/2;ce(f)}else ce(0);const{top:t,left:n}=p.current.getBoundingClientRect(),o={x:n+window.scrollX,y:t+window.scrollY};we(o)},Ie=new Qe(e=>Ve(e)),Se=e=>{O(i.CREATE);const t=x.convertStageCoordinatesToPercentaged([e],T,u);R===D.BBox&&t.push(t[0]);const n=z(),o=new Ee(n,R,t);if(ve(performance.now()),se!==void 0&&(o.labelIds=[se]),Ce(o),R===D.Point){const s={...o,coordinates:[e],annoTime:0};J(s)}},be=()=>{if(r&&![D.Line,D.Polygon].includes(r.type))return;const e=A.find(t=>t.internalId===(r==null?void 0:r.internalId));e!==void 0&&(e.mode=N.CREATE,e.status=I.CREATING,e.selectedNode=e.coordinates.length-1,O(i.ADD),Oe(e.type),xe(e))},_e=()=>{const e=r?r.internalId:0,t=A.find(n=>n.internalId>e);if(t)return v(t);if(A.length>0)return v(A[0])},Ne=()=>{const e=r?r.internalId:0,t=[...A];t.sort((o,s)=>s.internalId-o.internalId);const n=t.find(o=>o.internalId<e);if(n)return v(n);if(A.length>0)return v(A[A.length-1])},Re=()=>{if(r){const e=JSON.stringify(r);localStorage.setItem("lostAnnotationClipboard",e);const t={title:"Success",message:"Annotation copied",type:ot.SUCCESS};oe(t)}},ke=()=>{const e=localStorage.getItem("lostAnnotationClipboard");if(e==null)return;const t=JSON.parse(e);t.internalId=z(),t.externalId="",te(t,!0),v(t)},Ve=e=>{switch(e){case a.EDIT_LABEL:r&&b(!0);break;case a.DELETE_ANNO:r&&re(r.internalId);break;case a.DELETE_ANNO_IN_CREATION:g===i.CREATE&&(re(r.internalId),O(i.VIEW));break;case a.ENTER_ANNO_ADD_MODE:console.log("KeyAction TODO: ENTER_ANNO_ADD_MODE");break;case a.LEAVE_ANNO_ADD_MODE:console.log("KeyAction TODO: LEAVE_ANNO_ADD_MODE");break;case a.UNDO:console.log("KeyAction TODO: UNDO");break;case a.REDO:console.log("KeyAction TODO: REDO");break;case a.TRAVERSE_ANNOS:_e();break;case a.TRAVERSE_ANNOS_BACKWARDS:Ne();break;case a.CAM_MOVE_LEFT:_(20*d,0);break;case a.CAM_MOVE_RIGHT:_(-20*d,0);break;case a.CAM_MOVE_UP:_(0,20*d);break;case a.CAM_MOVE_DOWN:_(0,-20*d);break;case a.CAM_MOVE_STOP:console.log("KeyAction TODO: CAM_MOVE_STOP");break;case a.COPY_ANNOTATION:Re();break;case a.PASTE_ANNOTATION:ke();break;case a.RECREATE_ANNO:console.log("KeyAction TODO: RECREATE_ANNO"),be();break;case a.TOGGLE_IMAGE_JUNK:if(g===i.ADD||g===i.CREATE)return;Ae(!B);break;default:console.log("Unknown KeyAction",e);break}},_=(e,t)=>{let n=c.x+e/d,o=c.y+t/d;const s=l.x*.45,f=l.x*.55,M=l.y*.45,$e=l.y*.55,je={x:0,y:0},fe=he.getViewportCoordinates(c,l,d,je),ge=he.getViewportCoordinates(c,l,d,l);fe.vX>=s?n=c.x-5:ge.vX<=f?n=c.x+5:fe.vY>=M?o=c.y-5:ge.vY<=$e&&(o=c.y+5),S({x:n,y:o})},Le=(e=>m.x<=0||m.y<=0||u.x<=0||u.y<=0?[]:A.map(n=>({...n,coordinates:x.convertPercentagedCoordinatesToStage(n.coordinates,u,m)})))(),Pe=()=>{if(O(i.VIEW),ae({x:-1,y:-1}),y.current!==null){const{width:e,height:t}=y.current.getBoundingClientRect();Y({x:e,y:t})}L(1),S({x:0,y:0}),$(void 0),b(!1)};w(()=>{if((p==null?void 0:p.current)!==void 0){const{width:e,height:t}=p.current.getBoundingClientRect(),n=t-X;G({x:e,y:n});const o=new ResizeObserver(()=>{const{width:s,height:f}=p.current.getBoundingClientRect(),M=f-X;G({x:s,y:M})});return o.observe(p.current),()=>o.disconnect()}Pe()},[Z,pe]),w(()=>{De()},[y,c,l]),w(()=>{if(p.current===null)return;const{width:e,height:t}=p.current.getBoundingClientRect(),n=t-X;G({x:e,y:n})},[p]),w(()=>{if(y.current===null)return;const{width:e,height:t}=y.current.getBoundingClientRect();Y({x:e,y:t});const n=new ResizeObserver(()=>{const{width:o,height:s}=y.current.getBoundingClientRect();Y({x:o,y:s})});return n.observe(y.current),()=>n.disconnect()},[y]),w(()=>{if(T===0)return;const e={x:u.x*T,y:u.y*T};ae(e)},[T,u]),w(()=>{K&&F.polygonsToCreate!==void 0&&F.polygonsToCreate.forEach(e=>{const t=z(),n=new Ee(t,e.type,x.convertPercentagedCoordinatesToStage(e.coordinates,u,m),N.VIEW,I.CREATED);J(n)})},[F]);const J=e=>{O(i.VIEW);const t={...e,mode:N.VIEW};if(e.type!==D.Point){const s=rt.getRoundedDuration(Te,performance.now());t.annoTime=s}const n=x.convertStageCoordinatesToPercentaged(e.coordinates,T,u);t.coordinates=n,ne(t);const o=R===D.Point||K;te(t,o)},We=e=>{e.preventDefault(),Ie.keyDown(e.key,e.shiftKey,e.ctrlKey)},Be=e=>{e.preventDefault()},Ke=e=>{if(e.button!==0){if(e.button===1)O(i.CAMERA_MOVE);else if(e.button===2){if(!W.canCreate||g===i.ADD||g===i.CREATE)return;const t=me.getAntiScaledMouseStagePosition(e,V,d,c),n={x:t.x-ie,y:t.y};Se(n)}}},Fe=()=>{ee&&(document.body.style.overflow="hidden")},Xe=e=>{switch(e.button){case 1:O(i.VIEW);break}},de=(e,t)=>{g===i.CAMERA_MOVE&&_(e,t)},Ue=()=>{ee&&(document.body.style.overflow="")},ze=e=>{const o=(e.deltaY<0?1:-1)>0?d*1.25:d/1.25,s=me.getAntiScaledMouseStagePosition(e,V,d,c),f=d/o,M={x:f*(s.x+c.x)-s.x,y:f*(s.y+c.y)-s.y};o<1?(L(1),(c.x!=0||c.y!=0)&&S({x:0,y:0})):o>200?(L(200),S(M)):(L(o),S(M))},Ye=(e,t)=>{if(t!==Ze.ANNO_SELECTED){console.log("Unknown Canvas Action:",t);return}const n={...e,coordinates:x.convertStageCoordinatesToPercentaged([...e.coordinates],T,u)};v(n);const o=x.getMostLeftPoints(e.coordinates),s=x.getTopPoint(o)[0],f=x.convertStageToPage(s,V,d,c);$(f)},le=e=>{const t=x.convertStageCoordinatesToPercentaged(e.coordinates,T,u),n={...e,coordinates:t};n.status===I.LOADED&&(n.status=I.CHANGED),ne(n)},Ge=()=>{if(g===i.CAMERA_MOVE)return C(Je,{});const t=[i.CREATE,i.ADD,i.MOVE].includes(g),n=Le.map(o=>{const s=o.internalId===(r==null?void 0:r.internalId);return t&&!s?C("g",{},`annotationComponent_${o.internalId}`):C(qe,{scaledAnnotation:o,annotationSettings:W,possibleLabels:q,svgScale:d,svgTranslation:H,pageToStageOffset:V,nodeRadius:U.nodeRadius,strokeWidth:U.strokeWidth,isSelected:s,isDisabled:K&&s,onFinishAnnoCreate:J,onLabelIconClicked:()=>b(!0),onAction:Ye,onAnnoChanged:le,onAnnotationModeChange:f=>{f===N.MOVE&&O(i.MOVE),g===i.MOVE&&f===N.VIEW&&O(i.VIEW)},onNotification:oe},`annotationComponent_${o.internalId}`)});return C("g",{children:n})},He=()=>C("circle",{cx:m.x/2,cy:m.y/2,r:"100%",style:{opacity:0},onContextMenu:e=>e.preventDefault(),onClick:()=>{b(!1)}}),ue={x:k.x+l.x/2,y:k.y+l.y/2};return P("div",{ref:p,style:{width:"100%",height:"100%"},children:[C("div",{style:{position:"absolute",left:(h==null?void 0:h.x)!==void 0?h.x:0,top:(h==null?void 0:h.y)!==void 0?h.y:0,display:(h==null?void 0:h.y)!==void 0?"inherit":"none",zIndex:j?7e3:-1},children:C(et,{defaultLabelId:Q,isVisible:j,selectedLabelsIds:r==null?void 0:r.labelIds,possibleLabels:q,isMultilabel:W.canHaveMultipleLabels,onLabelSelect:e=>{if(b(!1),e.length>0){const o=e.filter(s=>!r.labelIds.includes(s));o.length>0&&Me(o[0])}const t=r.status===I.LOADED?I.CHANGED:r.status,n={...r,coordinates:x.convertPercentagedCoordinatesToStage(r.coordinates,u,m),labelIds:[...e],status:t};le(n)}})}),B&&P("div",{style:{position:"absolute",left:ue.x,top:ue.y,transform:"translate(-50%, -50%)",textAlign:"center",color:"white"},children:[C(tt,{icon:nt,size:"5x",style:{marginBottom:15}}),C("h2",{children:"Marked as Junk"})]}),P("svg",{width:"100%",height:"100%",onKeyDown:We,onKeyUp:Be,onMouseMove:e=>de(e.movementX,e.movementY),tabIndex:0,onMouseDown:e=>Ke(e),children:[P("g",{transform:`scale(${d}) translate(${H.x}, ${H.y})`,onMouseOver:Fe,onMouseLeave:Ue,onMouseUp:Xe,onWheel:ze,onMouseMove:e=>de(e.movementX,e.movementY),onClick:()=>{v(void 0)},children:[C("image",{onContextMenu:e=>e.preventDefault(),href:Z,ref:y,width:m.x>0?m.x:void 0,height:m.y>0?m.y:void 0}),Ge()]}),j&&He(),B&&C("rect",{x:"0",y:"0",width:l.x,height:l.y,style:{opacity:.8},onContextMenu:e=>e.preventDefault(),onClick:()=>{$(void 0)}})]})]})};export{wt as default};