UNPKG

@sfgrp/sled

Version:

UI for image segmentation of slide collections

2 lines (1 loc) 11.2 kB
(function(e,S){typeof exports=="object"&&typeof module<"u"?module.exports=S(require("vue")):typeof define=="function"&&define.amd?define(["vue"],S):(e=typeof globalThis<"u"?globalThis:e||self,e.sled=S(e.Vue))})(this,function(e){"use strict";const S=["x1","y1","x2","y2"],V={__name:"SvgLine",props:{x1:{type:[Number,String],required:!0},x2:{type:[Number,String],required:!0},y1:{type:[Number,String],required:!0},y2:{type:[Number,String],required:!0},scale:{type:[Number,String],required:!0},lineThickness:{type:[Number,String]}},setup(t){const B=t,r=e.computed(()=>B.y1===B.y2),u=e.computed(()=>({stroke:"rgb(255,0,0)",strokeWidth:B.lineThickness,strokeLinecap:"round",cursor:r.value?"ns-resize":"ew-resize"}));return(i,o)=>(e.openBlock(),e.createElementBlock("line",{x1:t.x1/t.scale,y1:t.y1/t.scale,x2:t.x2/t.scale,y2:t.y2/t.scale,style:e.normalizeStyle(u.value)},null,12,S))}},D=["cx","cy"],q={__name:"SvgCircle",props:{hLines:{type:Array,required:!0},vLines:{type:Array,required:!0},scale:{type:Number,default:1},ix:{type:Number,default:0},iy:{type:Number,default:0},strokeColor:{type:String,default:"black"}},emits:["dragging"],setup(t,{emit:B}){const r=t,u=B;function i(){u("dragging",[r.ix,r.iy])}const o=e.computed(()=>r.ix<0?(.7*r.vLines[0]+.3*r.vLines[r.vLines.length-1])/r.scale:r.vLines[r.ix]/r.scale),m=e.computed(()=>r.iy<0?(.7*r.hLines[0]+.3*r.hLines[r.hLines.length-1])/r.scale:r.hLines[r.iy]/r.scale),s=e.computed(()=>({stroke:r.strokeColor,strokeWidth:2,strokeOpacity:.7,fillOpacity:0,zIndex:3}));return(L,g)=>(e.openBlock(),e.createElementBlock("circle",{cx:o.value,cy:m.value,r:10,style:e.normalizeStyle(s.value),onMousedown:i},null,44,D))}},O=["width","height"],U=["width","height","xlink:href"],F={__name:"SvgComponent",props:{imageData:{type:String,required:!0},imageWidth:{type:Number,required:!0},imageHeight:{type:Number,required:!0},scale:{type:Number,default:1},hLines:{type:Array,required:!0},vLines:{type:Array,required:!0},lineThickness:{type:Number}},emits:["circleUL","circleLR","dragUL","dragLR","dragVline","dragHline"],setup(t,{emit:B}){const r=t,u=B;e.ref([0,0,-1]),e.ref([0,0,-1]);const i=e.ref(!1),o=e.ref(),m=e.ref([]),s=e.ref(),L=e.ref();function g(){i.value=!1,s.value=void 0}function h(x=0){return Math.random().toString(16).substr(2,8)+x}function v({clientX:x,clientY:c}){var f;if(i.value){const d=(f=L.value)==null?void 0:f.getBoundingClientRect();m.value;const b=x-d.left-r.vLines[m.value[0]]/r.scale,C=c-d.top-r.hLines[m.value[1]]/r.scale;s.value?u(s.value,[b,C]):m.value[0]>=0?u("dragVline",[b,C,m.value[0]]):u("dragHline",[b,C,m.value[1]])}}return e.onMounted(()=>{window.addEventListener("mouseup",g),window.addEventListener("mousemove",v)}),e.onBeforeUnmount(()=>{window.removeEventListener("mouseup",g),window.removeEventListener("mousemove",v)}),(x,c)=>(e.openBlock(),e.createElementBlock("svg",{ref_key:"rootRef",ref:L,width:t.imageWidth/t.scale,height:t.imageHeight/t.scale,style:{zIndex:2,position:"absolute"}},[e.createElementVNode("image",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",width:t.imageWidth/t.scale,height:t.imageHeight/t.scale,"xlink:href":t.imageData},null,8,U),t.hLines.length>1&&t.vLines.length>1?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.hLines,(f,d)=>(e.openBlock(),e.createBlock(V,{key:h(d),x1:t.vLines[0],y1:t.hLines[d],x2:t.vLines[t.vLines.length-1],y2:t.hLines[d],scale:t.scale,"line-thickness":t.lineThickness,onMousedown:()=>{i.value=!0,m.value=[-1,d]}},null,8,["x1","y1","x2","y2","scale","line-thickness","onMousedown"]))),128)),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.vLines,(f,d)=>(e.openBlock(),e.createBlock(V,{key:h(d),x1:t.vLines[d],y1:t.hLines[0],x2:t.vLines[d],y2:t.hLines[t.hLines.length-1],scale:t.scale,"line-thickness":t.lineThickness,index:d,dragging:i.value,onMousedown:()=>{i.value=!0,m.value=[d,-1]},onMousemove:c[0]||(c[0]=b=>o.value=b)},null,8,["x1","y1","x2","y2","scale","line-thickness","index","dragging","onMousedown"]))),128)),e.createVNode(q,{ix:0,iy:0,"h-lines":t.hLines,"v-lines":t.vLines,scale:t.scale,"stroke-color":"red",style:{cursor:"move"},onDragging:c[1]||(c[1]=f=>{i.value=!0,s.value="dragUL",m.value=f})},null,8,["h-lines","v-lines","scale"]),e.createVNode(q,{ix:t.vLines.length-1,iy:t.hLines.length-1,"h-lines":t.hLines,"v-lines":t.vLines,scale:t.scale,"stroke-color":"red",style:{cursor:"nwse-resize"},onDragging:c[2]||(c[2]=f=>{i.value=!0,s.value="dragLR",m.value=f})},null,8,["ix","iy","h-lines","v-lines","scale"])],64)):e.createCommentVNode("",!0)],8,O))}},A=["innerHTML"],j=["disabled"],Y=e.createElementVNode("option",{value:"none"},"None",-1),G=["value"],X=["disabled"],M=5,K={__name:"Cell",props:{modelValue:{type:Object,required:!0},metadata:{type:Object,default:void 0},scale:{type:Number,default:1},locked:{type:Boolean,default:!1}},emits:["update:modelValue","onChange"],setup(t,{emit:B}){const r={position:"absolute",right:"10px",bottom:"10px"},u={position:"absolute",top:"4px",backgroundColor:"#FFF",borderRadius:"3px",padding:"4px",opacity:.9},i={position:"absolute",top:"50%",left:"50%",transform:"translate(-50%, -50%)"},o=t,m=B,s=e.computed({get(){return o.modelValue},set(h){m("update:modelValue",h)}}),L=e.computed({get(){return!s.value.metadata},set(h){s.value.metadata=h?null:s.value.metadata||"none"}}),g=e.computed(()=>{const{upperCorner:h,lowerCorner:v}=s.value;return{position:"absolute",top:`${h.y/o.scale+M}px`,left:`${h.x/o.scale+M}px`,width:`${(v.x-h.x)/o.scale-M*2}px`,height:`${(v.y-h.y)/o.scale-M*2}px`,zIndex:2}});return(h,v)=>{var x;return e.openBlock(),e.createElementBlock("div",{style:e.normalizeStyle(g.value)},[(x=s.value)!=null&&x.textfield?(e.openBlock(),e.createElementBlock("span",{key:0,class:"cell-textfield",style:u,innerHTML:s.value.textfield},null,8,A)):e.createCommentVNode("",!0),L.value?e.createCommentVNode("",!0):e.withDirectives((e.openBlock(),e.createElementBlock("select",{key:1,class:"cell-select","onUpdate:modelValue":v[0]||(v[0]=c=>s.value.metadata=c),disabled:t.locked,style:i,onChange:v[1]||(v[1]=c=>m("onChange",s.value))},[Y,(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.metadata,(c,f)=>(e.openBlock(),e.createElementBlock("option",{key:f,value:f},e.toDisplayString(c),9,G))),128))],40,j)),[[e.vModelSelect,s.value.metadata]]),e.withDirectives(e.createElementVNode("input",{type:"checkbox",class:"cell-checkbox",disabled:t.locked,style:r,"onUpdate:modelValue":v[2]||(v[2]=c=>L.value=c)},null,8,X),[[e.vModelCheckbox,L.value]])],4)}}};return Object.assign({name:"Sled"},{__name:"Sled",props:e.mergeModels({metadataAssignment:{type:Object,default:()=>({})},imageWidth:{type:Number,required:!0},imageHeight:{type:Number,required:!0},fileImage:{type:String},lineWeight:{type:[Number,String],default:4},autosize:{type:Boolean,default:!0},locked:{type:Boolean,default:!1}},{verticalLines:{type:Array,required:!0},verticalLinesModifiers:{},horizontalLines:{type:Array,required:!0},horizontalLinesModifiers:{}}),emits:e.mergeModels(["onComputeCells","resize"],["update:verticalLines","update:horizontalLines"]),setup(t,{expose:B,emit:r}){const u=t,i=e.useModel(t,"verticalLines"),o=e.useModel(t,"horizontalLines"),m=r,s=e.ref(0),L=e.ref(0),g=e.ref([]),h=e.ref(0),v=e.ref(0),x=e.ref(void 0),c=e.ref(1),f=e.ref(null),d=e.computed(()=>o.value.length-1),b=e.computed(()=>i.value.length-1);e.watch([o,i],()=>{const n=I(o.value),a=I(i.value);n.isSorted||(o.value=n.arr),a.isSorted||(i.value=a.arr),J()},{deep:!0,immediate:!0}),e.watch(()=>u.imageHeight,n=>{L.value=n,E()},{immediate:!0}),e.watch(()=>u.imageWidth,n=>{s.value=n,E()},{immediate:!0}),e.watch(()=>u.fileImage,n=>{h.value=s.value,v.value=L.value,E()}),e.watch(()=>u.autosize,n=>{n?(x.value=new ResizeObserver($),x.value.observe(f.value)):x.value.disconnect(),c.value=W()}),e.onMounted(()=>{u.autosize&&(x.value=new ResizeObserver($),x.value.observe(f.value))}),e.onBeforeUnmount(()=>{x.value.disconnect()});function C(n,a){g.value[n]=a,m("onComputeCells",g.value)}function H(n,a){const[l]=n;return l+a<0}function R(n){if(!H(i.value,n))for(let a=0;a<i.value.length;a++)N(a,n)}function T(n){if(!H(o.value,n))for(let a=0;a<o.value.length;a++)z(a,n)}function N(n,a){const l=Math.round(i.value[n]+a);l<0||l>u.imageWidth||(i.value[n]=l)}function z(n,a){const l=Math.round(o.value[n]+a);l<0||l>u.imageHeight||(o.value[n]=l)}function I(n){const a=n.toSorted((l,y)=>l-y);return{isSorted:a.every((l,y)=>n[y]===l),arr:a}}function E(){if(h.value>1){const n=s.value/h.value,a=i.value.length;let l=0;for(l=0;l<a;l++)i.value[l]=Math.round(i.value[l]*n)}if(v.value>1){const n=L.value/v.value,a=o.value.length;let l=0;for(l=0;l<a;l++)o.value[l]=Math.round(o.value[l]*n)}h.value=s.value,v.value=L.value}function P(){if(o.value.length>1&&i.value.length>1){g.value=[];const n=(o.value[d.value]-o.value[0])/d.value,a=(i.value[b.value]-i.value[0])/b.value;for(let l=0;l<d.value;l++)o.value[l]=Math.round(o.value[0]+l*n);for(let l=0;l<b.value;l++)i.value[l]=Math.round(i.value[0]+l*a)}}function J(){if(o.value.length>0&&i.value.length>0){let n,a,l=-1;for(let y=0;y<d.value;y++)for(let w=0;w<b.value;w++){l=b.value*y+w,n={x:i.value[w],y:o.value[y]},a={x:i.value[w+1],y:o.value[y+1]};const{metadata:k=null,textfield:p}=g.value[l]||{};g.value[l]={index:l,upperCorner:n,lowerCorner:a,row:y,column:w,metadata:k,textfield:p}}g.value=l===-1?[]:g.value.slice(0,l+1),m("onComputeCells",g.value)}}function Q(n){const[a,l]=n,y=i.value.at(-1),w=o.value.at(-1);if(!(y+a>u.imageWidth||w+l>u.imageHeight)){for(let k=1;k<i.value.length;k++){const p=Math.round(i.value[k]+k*a/b.value);p>0&&p<=u.imageWidth&&(i.value[k]=Math.round(i.value[k]+k*a/b.value))}for(let k=1;k<o.value.length;k++){const p=Math.round(o.value[k]+k*l/d.value);p>0&&p<=u.imageHeight&&(o.value[k]=Math.round(o.value[k]+k*l/d.value))}}}function Z(n){const[a,l]=n;R(a),T(l)}function _(n){const a=n[1],l=n[2];z(l,a)}function ee(n){const a=n[0],l=n[2];N(l,a)}function W(){if(u.autosize){const n=f.value.getBoundingClientRect(),a=n.height<L.value?L.value/n.height:1,l=n.width<s.value?s.value/n.width:1;return a>l?a:l}else return 1}function $(n,a){const l=f.value.getBoundingClientRect();c.value=W(),m("resize",{...l,scale:c.value})}return B({moveX:R,moveY:T,moveH:z,moveV:N,equalizeLines:P}),(n,a)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"rootRef",ref:f,style:e.normalizeStyle({display:"block",position:"relative",height:`${L.value}px`})},[t.fileImage?(e.openBlock(),e.createBlock(F,{key:0,"image-width":s.value,"image-height":L.value,"image-data":t.fileImage,"h-lines":o.value,"v-lines":i.value,scale:c.value,"line-thickness":t.lineWeight,onDragUL:Z,onDragLR:Q,onDragHline:_,onDragVline:ee},null,8,["image-width","image-height","image-data","h-lines","v-lines","scale","line-thickness"])):e.createCommentVNode("",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(g.value,(l,y)=>(e.openBlock(),e.createBlock(K,{key:y,locked:t.locked,metadata:t.metadataAssignment,scale:c.value,modelValue:g.value[y],"onUpdate:modelValue":w=>g.value[y]=w,onOnChange:w=>C(y,w)},null,8,["locked","metadata","scale","modelValue","onUpdate:modelValue","onOnChange"]))),128))],4))}})});