@leafer-in/editor 1.0.0-rc.6 → 1.0.0-rc.7

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.
@@ -1 +1 @@
1
- this.LeaferIN=this.LeaferIN||{},this.LeaferIN.editor=function(t,e){"use strict";var i;!function(t){t[t.topLeft=0]="topLeft",t[t.top=1]="top",t[t.topRight=2]="topRight",t[t.right=3]="right",t[t.bottomRight=4]="bottomRight",t[t.bottom=5]="bottom",t[t.bottomLeft=6]="bottomLeft",t[t.left=7]="left"}(i||(i={}));const{scaleOfOuter:s,reset:o}=e.MatrixHelper,{topLeft:r,top:n,topRight:a,right:h,bottomRight:l,bottom:c,bottomLeft:g,left:y}=i,d={};const{topLeft:u,top:v,topRight:_,right:x,bottomRight:b,bottom:f,bottomLeft:p,left:R}=i;function E(t,e){const i=t.enterPoint;if(!i||!t.target||!t.visible)return;let{rotation:s}=t,{resizeCursor:o,rotateCursor:r,resizeable:n}=t.config;const a=t.tool.getMirrorData(t),{__direction:h,__isResizePoint:l}=i.__;t.enterPoint=i,l&&(e.metaKey||e.ctrlKey||!n)&&(o=r),(a.x||a.y)&&(z(o=[...o],a.x,a.y),z(r=[...r],a.y,a.x),a.x+a.y===1&&(s=-s));let c=(h+Math.round(s/45))%8;c<0&&(c+=8),i.cursor=l?o[c]:r[c]}function z(t,e,i){if(e){const e=t[v],i=t[u],s=t[_];t[v]=t[f],t[u]=t[p],t[_]=t[b],t[f]=e,t[p]=i,t[b]=s}if(i){const e=t[R],i=t[u],s=t[p];t[R]=t[x],t[u]=t[_],t[p]=t[b],t[x]=e,t[_]=i,t[b]=s}}const w={name:"RectTool",getMirrorData(t){const{scaleX:e,scaleY:i}=t.target;return{x:e<0?1:0,y:i<0?1:0}},resize(t){const{target:e,bounds:i,resizeType:s,old:o}=t,{x:r,y:n,width:a,height:h}=i,l={x:r-o.x,y:n-o.y};e.innerToWorld(l,null,!0,e.parent),e.x+=l.x,e.y+=l.y,"scale"===s?(e.scaleX*=a/o.width,e.scaleY*=h/o.height):(a<0?(e.width=-a,e.scaleX*=-1):e.width!==a&&(e.width=a),h<0?(e.height=-h,e.scaleY*=-1):e.height!==h&&(e.height=h))},rotate(t){const{target:e,rotation:i,origin:s}=t;e.rotateOf(s,i)},update(t){const{target:i,config:s,rotatePoints:o,targetRect:r,rect:n,circle:a,resizeLines:h,resizePoints:l}=t,{type:c,resizeable:g,rotateable:y,stroke:d,pointFill:u,pointSize:v,pointRadius:_}=s,x={fill:u,stroke:d,width:v,height:v,cornerRadius:_},b=s.point instanceof Array?s.point:[s.point||x],f=new e.Bounds(i.boxBounds),p=i.worldTransform,R=t.parent.worldTransform,E=new e.Matrix(p);E.divide(R);const z=E.e,w=E.f;let{scaleX:m,scaleY:P,rotation:M,skewX:T,skewY:L}=p;m/=R.scaleX,P/=R.scaleY,M-=R.rotation,T-=R.skewX,L-=R.skewY;const{x:k,y:I,width:D,height:F}=f.scale(m,P);t.set({x:z,y:w,rotation:M,skewX:T,skewY:L}),r.set({x:k,y:I,width:f.width/m,height:f.height/P,scaleX:m,scaleY:P,visible:!0});const O=[{x:k,y:I},{x:k+D/2,y:I},{x:k+D,y:I},{x:k+D,y:I+F/2},{x:k+D,y:I+F},{x:k+D/2,y:I+F},{x:k,y:I+F},{x:k,y:I+F/2}],X=[];let Y,A,C,K,B;for(let t=0;t<8;t++)Y=O[t],A=b[t%b.length],K=l[t],B=h[Math.floor(t/2)],C=o[t],K.set(A),K.x=C.x=B.x=Y.x,K.y=C.y=B.y=Y.y,K.visible=B.visible=g||y,C.visible=y&&g,t%2?((t+1)/2%2?(B.width=Math.abs(D),C.width=Math.max(10,Math.abs(D)-30)):(B.height=Math.abs(F),C.height=Math.max(10,Math.abs(F)-30)),K.rotation=90,K.visible="mobile"===c,C.visible=!1):(C.visible="mobile"!==c,X.push(Y.x,Y.y));A=s.rotatePoint||A,a.set(A),a.x=k+D/2,A.y||(a.y=I-(10+(K.height+a.height)/2)*(this.getMirrorData(t).y?-1:1)),a.visible=y&&"mobile"===c,n.set(s.rect||{stroke:d}),n.points=X,n.visible=!0}},{left:m,right:P}=i,M={name:"LineTool",getMirrorData:t=>({x:0,y:0}),resize(t){const{direction:e,dragEvent:i,lockRatio:s,around:o}=t,r=t.target,n={x:0,y:0},{toPoint:a}=r;r.rotation=0;let{x:h,y:l}=i.getInnerMove(r);s&&(Math.abs(h)>Math.abs(l)?l=0:h=0),e===m?(n.x+=h,n.y+=l,o&&(a.x-=h,a.y-=l)):(o&&(n.x-=h,n.y-=l),a.x+=h,a.y+=l),r.getLocalPointByInner(n,null,null,!0),r.getLocalPointByInner(a,null,null,!0),r.x=n.x,r.y=n.y,r.getInnerPointByLocal(a,null,null,!0),r.toPoint=a},rotate(t){w.rotate(t)},update(t){const{rotatePoints:e,circle:i,resizeLines:s,resizePoints:o}=t;w.update(t);for(let t=0;t<8;t++)t<4&&(s[t].visible=!1),o[t].visible=e[t].visible=t===m||t===P;i.visible=!1}};class T extends e.Event{constructor(t,e){super(t),e&&Object.assign(this,e)}}T.RESIZE="editor.resize";class L extends e.Event{constructor(t,e){super(t),e&&Object.assign(this,e)}}L.ROTATE="editor.rotate";class k extends e.Group{get target(){return this._target}set target(t){this.__removeTargetEvents(),this.visible=!!t,this._target=t,t&&this.onTarget()}constructor(t,i){super(i),this.config={type:"pc",stroke:"#836DFF",pointFill:"#FFFFFF",pointSize:10,pointRadius:10,rotateGap:90,hideOnMove:!1,moveCursor:"move",resizeType:"auto",resizeCursor:["nwse-resize","ns-resize","nesw-resize","ew-resize","nwse-resize","ns-resize","nesw-resize","ew-resize"],rotateCursor:["ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize","n-resize"],resizeable:!0,rotateable:!0},this.resizePoints=[],this.rotatePoints=[],this.resizeLines=[],this.targetRect=new e.Rect({hitFill:"all",hitRadius:5}),this.rect=new e.Polygon({hittable:!1,strokeAlign:"center"}),this.circle=new e.Rect({around:"center",hitRadius:10}),this.__eventIds=[],this.__targetEventIds=[],t&&(this.config=e.DataHelper.default(t,this.config)),this.init()}init(){let t,i,s;const{resizePoints:o,rotatePoints:r,resizeLines:n}=this,a=[{x:1,y:1},"center",{x:0,y:1},"center",{x:0,y:0},"center",{x:1,y:0},"center"];for(let h=0;h<8;h++)t=new e.Rect({around:a[h],width:15,height:15,hitFill:"all"}),r.push(t),this.__listenPointEvents(t,"rotate",h),h%2&&(i=new e.Rect({around:"center",width:10,height:10,hitFill:"all"}),n.push(i),this.__listenPointEvents(i,"resize",h)),s=new e.Rect({around:"center",hitRadius:5}),o.push(s),this.__listenPointEvents(s,"resize",h);this.__listenPointEvents(this.circle,"rotate",1),this.addMany(...r,this.targetRect,this.rect,this.circle,...n,...o),this.__listenEvents()}onTarget(){this.tool=this.getTool(this.target),this.waitLeafer((()=>{this.update(),this.updateMoveCursor(),this.__listenTargetEvents()}))}getTool(t){return"Line"===t.tag&&t.resizeable?M:w}update(){this.target&&this.tool.update(this)}onDrag(t){const{resizeable:e,rotateable:i}=this.config;t.metaKey||t.ctrlKey||!e?i&&this.onRotate(t):this.onResize(t)}onMove(t){const{target:e}=this,{x:i,y:s}=t.getLocalMove(e);t.shiftKey?Math.abs(i)>Math.abs(s)?e.x+=i:e.y+=s:(e.x+=i,e.y+=s)}onRotate(t){const{target:i}=this,{rotateGap:s}=this.config,{x:o,y:r,width:n,height:a}=i.boxBounds,h={x:o+n/2,y:r+a/2};let l;if(t instanceof e.RotateEvent)l=t.rotation;else{const s=t,o={x:s.x-t.moveX,y:s.y-t.moveY};l=e.PointHelper.getChangeAngle(o,i.getWorldPoint(h),s)}l=e.MathHelper.getGapRotation(i.rotation+l,s)-i.rotation;const c=new L(L.ROTATE,{editor:this,target:i,origin:h,rotation:l});this.tool.rotate(c),i.emitEvent(c)}onResize(t){const{target:e}=this,{__direction:i}=t.current.__;let{resizeType:u,around:v,lockRatio:_}=this.config;t.shiftKey&&(_=!0),t.altKey&&!v&&(v="center"),"auto"===u&&(u=e.resizeable?"size":"scale");const x=function(t,e,i,u,v){v&&(i.x*=2,i.y*=2);let _,x=1,b=1;const{x:f,y:p,width:R,height:E}=t,z=(-i.y+E)/E,w=(i.x+R)/R,m=(i.y+E)/E,P=(-i.x+R)/R;switch(e){case n:b=z,u&&(x=b),_={x:f+R/2,y:p+E};break;case h:x=w,u&&(b=x),_={x:f,y:p+E/2};break;case c:b=m,u&&(x=b),_={x:f+R/2,y:p};break;case y:x=P,u&&(b=x),_={x:f+R,y:p+E/2};break;case r:b=z,x=P,u&&(x=b),_={x:f+R,y:p+E};break;case a:b=z,x=w,u&&(x=b),_={x:f,y:p+E};break;case l:b=m,x=w,u&&(x=b),_={x:f,y:p};break;case g:b=m,x=P,u&&(x=b),_={x:f+R,y:p}}return v&&(_="object"==typeof v?{x:f+R/v.x,y:p+E/v.y}:{x:f+R/2,y:p+E/2}),o(d),s(d,_,x,b),{bounds:{x:t.x+d.e,y:t.y+d.f,width:R*x,height:E*b},old:t,origin:_,scaleX:x,scaleY:b,direction:e,lockRatio:u,around:v}}(e.boxBounds,i,t.getInnerMove(this.targetRect),_,v),b=new T(T.RESIZE,Object.assign(Object.assign({},x),{target:e,editor:this,dragEvent:t,resizeType:u}));this.tool.resize(b),e.emitEvent(b)}updateMoveCursor(){this.targetRect.cursor=this.config.moveCursor}__listenEvents(){this.__eventIds=[this.targetRect.on_(e.DragEvent.START,(()=>{this.opacity=this.config.hideOnMove?0:1})),this.targetRect.on_(e.DragEvent.DRAG,this.onMove,this),this.targetRect.on_(e.DragEvent.END,(()=>{this.opacity=1})),this.targetRect.on_(e.PointerEvent.ENTER,this.updateMoveCursor,this)]}__removeListenEvents(){this.targetRect.off_(this.__eventIds),this.__eventIds.length=0}__listenPointEvents(t,i,s){t.__.__direction=s;const o=t.__.__isResizePoint="resize"===i;t.on_(e.DragEvent.DRAG,o?this.onDrag:this.onRotate,this),t.on_(e.PointerEvent.LEAVE,(()=>this.enterPoint=null)),t.on_(e.PointerEvent.ENTER,(e=>{this.enterPoint=t,E(this,e)}))}__listenTargetEvents(){if(this.target){const{leafer:t}=this.target;this.__targetEventIds=[t.on_(e.RenderEvent.START,this.update,this),t.on_([e.KeyEvent.HOLD,e.KeyEvent.UP],(t=>{E(this,t)}))]}}__removeTargetEvents(){if(this.__targetEventIds.length){const{leafer:t}=this.target;t&&t.off_(this.__targetEventIds),this.__targetEventIds.length=0}}destroy(){this.__removeListenEvents(),this._target=null,super.destroy()}}return t.Editor=k,t.EditorResizeEvent=T,t.EditorRotateEvent=L,t.LineTool=M,t.RectTool=w,t}({},LeaferUI);
1
+ this.LeaferIN=this.LeaferIN||{},this.LeaferIN.editor=function(t,e){"use strict";function i(t,e,i,s){var o,n=arguments.length,r=n<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(t,e,i,s);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(r=(n<3?o(r):n>3?o(e,i,r):o(e,i))||r);return n>3&&r&&Object.defineProperty(e,i,r),r}"function"==typeof SuppressedError&&SuppressedError;class s extends e.Event{constructor(t,e){super(t),e&&Object.assign(this,e)}}s.SELECT="editor.select",s.HOVER="editor.hover";class o extends s{constructor(t,e){super(t,e)}}o.MOVE="editor.move";class n extends s{constructor(t,e){super(t,e)}}n.SCALE="editor.scale";class r extends s{constructor(t,e){super(t,e)}}r.ROTATE="editor.rotate";class a extends s{constructor(t,e){super(t,e)}}function h(t){return(i,s)=>{const o="_"+s;e.defineKey(i,s,{get(){return this[o]},set(e){this[o]!==e&&(this[o]=e,t(this))}})}}a.SKEW="editor.skew";const l=e.MatrixHelper.get(),{abs:d}=Math,{copy:c,scale:g}=e.MatrixHelper;class u extends e.UI{constructor(){super(),this.list=[],this.hittable=!1,this.strokeAlign="center"}setTarget(t,e){const{stroke:i,strokeWidth:s}=e;this.set({stroke:i,strokeWidth:s}),this.target=t}__draw(t,i){const{list:s}=this;if(s.length){let o;const{stroke:n,strokeWidth:r}=this.__,{bounds:a}=i;for(let h=0;h<s.length;h++)if(o=s[h],a&&a.hit(o.__world,i.matrix)){let s;if("scale"===o.__.editSize){const e=d(o.__world.scaleX),n=d(o.__world.scaleY);if(e!==n){c(l,o.__world),g(l,1/e,1/n),t.setWorld(l,i.matrix),t.beginPath(),this.__.strokeWidth=r;const{x:a,y:h,width:d,height:u}=o.__layout.boxBounds;t.rect(a*e,h*n,d*e,u*n),s=!0}}s||(t.setWorld(o.__world,i.matrix),t.beginPath(),o.__.__pathForRender?o.__drawRenderPath(t):o.__drawPathByBox(t),this.__.strokeWidth=r/d(o.__world.scaleX)),"string"==typeof n?e.Paint.stroke(n,this,t,i):e.Paint.strokes(n,this,t,i)}this.__.strokeWidth=r}}destroy(){this.target=null,super.destroy()}}i([h((function(t){const e=t.target;t.list=e?e instanceof Array?e:[e]:[],t.forceUpdate()}))],u.prototype,"target",void 0);class f extends e.Group{constructor(t){super(t),this.strokeArea=new e.Rect({strokeAlign:"center"}),this.fillArea=new e.Rect,this.visible=this.hittable=!1,this.addMany(this.fillArea,this.strokeArea)}setStyle(t,e){const{visible:i,stroke:s,strokeWidth:o}=t;this.visible=i,this.strokeArea.reset(Object.assign({stroke:s,strokeWidth:o},e||{})),this.fillArea.reset({visible:!e,fill:s,opacity:.2})}setBounds(t){this.strokeArea.set(t),this.fillArea.set(t)}}var p;!function(t){t[t.No=0]="No",t[t.Yes=1]="Yes",t[t.NoAndSkip=2]="NoAndSkip",t[t.YesAndSkip=3]="YesAndSkip"}(p||(p={}));const{No:y,Yes:v,NoAndSkip:x,YesAndSkip:w}=p,E={findOne:t=>t.list.find((t=>t.editable)),findBounds(t,e){if(t.__.hittable&&!t.__.locked&&e.hit(t.__world)){if(t.__.editable){if(t.isBranch&&!t.__.hitChildren)return t.__.hitSelf?w:x;if(t.isFrame)return e.includes(t.__layout.boxBounds,t.__world)?w:y;if(e.hit(t.__layout.boxBounds,t.__world)&&t.__.hitSelf)return v}return y}return t.isBranch?x:y}},{findOne:k}=E;class _ extends e.Group{get dragging(){return!!this.originList}get running(){return this.editor.hittable&&this.editor.config.selector}get isMoveMode(){return this.app&&this.app.interaction.moveMode}constructor(t){super(),this.hoverStroker=new u,this.targetStroker=new u,this.bounds=new e.Bounds,this.selectArea=new f,this.__eventIds=[],this.editor=t,this.addMany(this.targetStroker,this.hoverStroker,this.selectArea),this.__listenEvents()}onHover(){const{editor:t}=this;if(!this.running||this.dragging||t.dragging)this.hoverStroker.target=null;else{const{stroke:e,strokeWidth:i,hover:s}=t.config;this.hoverStroker.setTarget(s?this.editor.hoverTarget:null,{stroke:e,strokeWidth:i})}}onSelect(){if(this.running){const{config:t,list:e}=this.editor,{stroke:i,strokeWidth:s}=t;this.targetStroker.setTarget(e,{stroke:i,strokeWidth:Math.max(1,s/2)}),this.hoverStroker.target=null}}update(){this.running&&this.targetStroker.forceUpdate()}onPointerMove(t){if(this.running&&!this.isMoveMode){const e=t.shiftKey?this.findDeepOne(t):k(t.path);this.editor.hoverTarget=this.editor.hasItem(e)?null:e}this.isMoveMode&&(this.editor.hoverTarget=null)}onBeforeDown(t){if(this.running&&!this.isMoveMode&&!t.middle){const e=this.lastDownLeaf=k(t.path);e?(t.shiftKey?this.editor.shiftItem(e):this.editor.target=e,this.editor.updateLayout(),e.leafer.interaction.updateDownData()):this.allow(t.target)&&(t.shiftKey||(this.editor.target=null))}}onTap(t){if(this.running&&t.shiftKey&&!t.middle&&!this.lastDownLeaf){const e=this.findDeepOne(t);e&&this.editor.shiftItem(e)}else this.isMoveMode&&(this.editor.target=null);this.lastDownLeaf=null}onDragStart(t){if(this.running&&this.allowDrag(t)){const{editor:e}=this,{stroke:i,strokeWidth:s,area:o}=e.config,{x:n,y:r}=t.getInner(this);this.bounds.set(n,r),this.selectArea.setStyle({visible:!0,stroke:i,strokeWidth:s,x:n,y:r},o),this.selectArea.setBounds(this.bounds.get()),this.originList=e.leafList.clone()}}onDrag(t){if(this.editor.dragging)this.onDragEnd();else if(this.dragging){const{editor:i}=this,s=t.getInnerTotal(this),o=this.bounds.clone().unsign(),n=new e.LeafList(i.app.find(E.findBounds,o));if(this.bounds.width=s.x,this.bounds.height=s.y,this.selectArea.setBounds(o.get()),n.length){const t=[];this.originList.forEach((e=>{n.has(e)||t.push(e)})),n.forEach((e=>{this.originList.has(e)||t.push(e)})),i.target=t}else i.target=this.originList,i.leafList.length&&i.update()}}onDragEnd(){this.dragging&&(this.originList=null,this.selectArea.visible=!1)}onAutoMove(t){if(this.dragging){const{x:e,y:i}=t.getLocalMove(this);this.bounds.x+=e,this.bounds.y+=i}}allow(t){return t.leafer!==this.editor.leafer}allowDrag(t){return!(!this.editor.config.boxSelect||t.target.draggable)&&(!this.editor.hasTarget&&this.allow(t.target)||t.shiftKey&&!k(t.path))}findDeepOne(t){const i={exclude:new e.LeafList(this.editor.editBox.rect)};return k(t.target.leafer.interaction.findPath(t,i))}__listenEvents(){const{editor:t}=this;t.waitLeafer((()=>{const{app:i}=t;i.selector.proxy=t,this.__eventIds=[t.on_(s.HOVER,this.onHover,this),t.on_(s.SELECT,this.onSelect,this),i.on_(e.PointerEvent.MOVE,this.onPointerMove,this),i.on_(e.PointerEvent.BEFORE_DOWN,this.onBeforeDown,this),i.on_(e.PointerEvent.TAP,this.onTap,this),i.on_(e.DragEvent.START,this.onDragStart,this),i.on_(e.DragEvent.DRAG,this.onDrag,this),i.on_(e.DragEvent.END,this.onDragEnd,this),i.on_(e.MoveEvent.MOVE,this.onAutoMove,this),i.on_([e.ZoomEvent.ZOOM,e.MoveEvent.MOVE],(()=>{this.editor.hoverTarget=null}))]}))}__removeListenEvents(){this.__eventIds&&(this.off_(this.__eventIds),this.__eventIds.length=0)}destroy(){this.editor=this.originList=this.lastDownLeaf=null,this.__removeListenEvents(),super.destroy()}}var m;!function(t){t[t.topLeft=0]="topLeft",t[t.top=1]="top",t[t.topRight=2]="topRight",t[t.right=3]="right",t[t.bottomRight=4]="bottomRight",t[t.bottom=5]="bottom",t[t.bottomLeft=6]="bottomLeft",t[t.left=7]="left"}(m||(m={}));const{topLeft:b,top:L,topRight:S,right:T,bottomRight:P,bottom:D,bottomLeft:O,left:A}=m,{toPoint:M}=e.AroundHelper,R={getScaleData(t,e,i,s,o){let n,r=1,a=1;const{width:h,height:l}=t;o&&(i.x*=2,i.y*=2);const d=(-i.y+l)/l,c=(i.x+h)/h,g=(i.y+l)/l,u=(-i.x+h)/h;switch(e){case L:a=d,n={x:.5,y:1};break;case T:r=c,n={x:0,y:.5};break;case D:a=g,n={x:.5,y:0};break;case A:r=u,n={x:1,y:.5};break;case b:a=d,r=u,n={x:1,y:1};break;case S:a=d,r=c,n={x:0,y:1};break;case P:a=g,r=c,n={x:0,y:0};break;case O:a=g,r=u,n={x:1,y:0}}return s&&(1!==r?a=r:r=a),M(o||n,t,n),{origin:n,scaleX:r,scaleY:a,direction:e,lockRatio:s,around:o}},getRotateData(t,i,s,o,n){let r;switch(i){case b:r={x:1,y:1};break;case S:r={x:0,y:1};break;case P:r={x:0,y:0};break;case O:r={x:1,y:0};break;default:r={x:.5,y:.5}}return M(n||r,t,r),{origin:r,rotation:e.PointHelper.getRotation(o,r,s)}},getSkewData(t,i,s,o){let n,r,a=0,h=0;switch(i){case L:r={x:.5,y:0},n={x:.5,y:1},a=1;break;case D:r={x:.5,y:1},n={x:.5,y:0},a=1;break;case A:r={x:0,y:.5},n={x:1,y:.5},h=1;break;case T:r={x:1,y:.5},n={x:0,y:.5},h=1}const{x:l,y:d,width:c,height:g}=t;r.x=l+r.x*c,r.y=d+r.y*g,M(o||n,t,n);const u=e.PointHelper.getRotation(r,n,{x:r.x+(a?s.x:0),y:r.y+(h?s.y:0)});return a?a=-u:h=u,{origin:n,skewX:a,skewY:h}},getAround:(t,i)=>i&&!t?e.AroundHelper.center:t,getRotateDirection:(t,e,i=8)=>((t=(t+Math.round(e/(360/i)))%i)<0&&(t+=i),t)},{topLeft:z,top:B,topRight:I,right:W,bottomRight:Y,bottom:X,bottomLeft:K,left:C}=m;function F(t,e){const{editBox:i}=t,s=i.enterPoint;if(!s||!t.hasTarget||!i.visible)return;let{rotation:o}=i,{resizeCursor:n,rotateCursor:r,resizeable:a,rotateable:h}=t.config;const{direction:l,pointType:d}=s;i.enterPoint=s;const c="resize"===d;if(c&&h&&(e.metaKey||e.ctrlKey||!a)&&(n=r),i.flipped){const{flippedX:t,flippedY:e}=i;N(n=[...n],t,e),N(r=[...r],e,t),i.flippedOne&&(o=-o)}const g=R.getRotateDirection(l,o);s.cursor=c?n[g]:r[g]}function H(t){t.editBox.rect.cursor=t.config.moveCursor}function N(t,e,i){if(e){const e=t[B],i=t[z],s=t[I];t[B]=t[X],t[z]=t[K],t[I]=t[Y],t[X]=e,t[K]=i,t[Y]=s}if(i){const e=t[C],i=t[z],s=t[K];t[C]=t[W],t[z]=t[I],t[K]=t[Y],t[W]=e,t[I]=i,t[Y]=s}}class j extends e.Box{}const G=["top","right","bottom","left"];class V extends e.Group{get flipped(){return this.flippedX||this.flippedY}get flippedX(){return this.scaleX<0}get flippedY(){return this.scaleY<0}get flippedOne(){return this.scaleX*this.scaleY<0}constructor(t){super(),this.rect=new e.Box({name:"rect",hitFill:"all",hitStroke:"none",strokeAlign:"center",hitRadius:5}),this.circle=new j({name:"circle",strokeAlign:"outside",around:"center",cursor:"crosshair",hitRadius:5}),this.buttons=new e.Group({around:"center",hitSelf:!1}),this.resizePoints=[],this.rotatePoints=[],this.resizeLines=[],this.__eventIds=[],this.editor=t,this.visible=!1,this.create(),this.__listenEvents()}create(){let t,e,i;const{resizePoints:s,rotatePoints:o,resizeLines:n,rect:r,circle:a,buttons:h}=this,l=[{x:1,y:1},{x:.5,y:1},{x:0,y:1},{x:0,y:.5},{x:0,y:0},{x:.5,y:0},{x:1,y:0},{x:1,y:.5}];for(let r=0;r<8;r++)t=new j({around:l[r],width:15,height:15,hitFill:"all"}),o.push(t),this.listenPointEvents(t,"rotate",r),r%2&&(e=new j({name:"resize-line",around:"center",width:10,height:10,hitFill:"all"}),n.push(e),this.listenPointEvents(e,"resize",r)),i=new j({name:"resize-point",around:"center",strokeAlign:"outside",hitRadius:5}),s.push(i),this.listenPointEvents(i,"resize",r);h.add(a),this.listenPointEvents(a,"rotate",2),this.addMany(...o,r,h,...n,...s)}update(t){const{config:e,list:i}=this.editor,{width:s,height:o}=t,{rect:n,circle:r,resizePoints:a,rotatePoints:h,resizeLines:l}=this,{middlePoint:d,resizeable:c,rotateable:g,stroke:u,strokeWidth:f}=e,p=this.getDirection8Points(t),y=this.getPointsStyle(),v=this.getMiddlePointsStyle();let x,w,E,k,_;this.visible=i[0]&&!i[0].locked;for(let t=0;t<8;t++)x=p[t],w=this.getPointStyle(t%2?v[(t-1)/2%v.length]:y[t/2%y.length]),k=a[t],E=h[t],_=l[Math.floor(t/2)],k.set(w),k.set(x),E.set(x),_.set(x),k.visible=_.visible=c||g,E.visible=g&&c,t%2?(k.visible=E.visible=!!d,(t+1)/2%2?(_.width=s,k.width>s-30&&(k.visible=!1)):(_.height=o,k.rotation=90,k.width>o-30&&(k.visible=!1))):k.rotation=t/2*90;r.visible=g&&!!e.rotatePoint,r.set(this.getPointStyle(e.rotatePoint||y[0])),n.set(Object.assign({stroke:u,strokeWidth:f},e.rect||{})),n.set(Object.assign(Object.assign({},t),{visible:!0})),this.layoutButtons()}layoutButtons(){const{buttons:t,resizePoints:e}=this,{buttonsDirection:i,buttonsFixed:s,buttonsMargin:o,middlePoint:n}=this.editor.config,{flippedX:r,flippedY:a}=this;let h=G.indexOf(i);(h%2&&r||(h+1)%2&&a)&&s&&(h=(h+2)%4);const l=s?R.getRotateDirection(h,this.flippedOne?this.rotation:-this.rotation,4):h,d=e[2*l+1],c=l%2,g=l&&3!==l?1:-1,u=(o+(h%2?(n?d.width:0)+t.boxBounds.width:(n?d.height:0)+t.boxBounds.height)/2)*g;c?(t.x=d.x+u,t.y=d.y):(t.x=d.x,t.y=d.y+u),s&&(t.rotation=90*(l-h),t.scaleX=r?-1:1,t.scaleY=a?-1:1)}getPointStyle(t){const{stroke:e,strokeWidth:i,pointFill:s,pointSize:o,pointRadius:n}=this.editor.config,r={fill:s,stroke:e,strokeWidth:i,width:o,height:o,cornerRadius:n};return t?Object.assign(r,t):r}getPointsStyle(){const{point:t}=this.editor.config;return t instanceof Array?t:[t]}getMiddlePointsStyle(){const{middlePoint:t}=this.editor.config;return t instanceof Array?t:t?[t]:this.getPointsStyle()}getDirection8Points(t){const{x:e,y:i,width:s,height:o}=t;return[{x:e,y:i},{x:e+s/2,y:i},{x:e+s,y:i},{x:e+s,y:i+o/2},{x:e+s,y:i+o},{x:e+s/2,y:i+o},{x:e,y:i+o},{x:e,y:i+o/2}]}onDragStart(t){this.dragging=!0,"rect"===t.target.name&&(this.editor.opacity=this.editor.config.hideOnMove?0:1)}onDragEnd(t){this.dragging=!1,"rect"===t.target.name&&(this.editor.opacity=1)}onDrag(t){const{editor:e}=this;"rotate"===t.current.pointType||t.metaKey||t.ctrlKey||!e.config.resizeable?e.config.rotateable&&e.onRotate(t):e.onScale(t)}onArrow(t){if(this.editor.hasTarget){const e={x:0,y:0},i=t.shiftKey?10:1;switch(t.code){case"ArrowDown":e.y=i;break;case"ArrowUp":e.y=-i;break;case"ArrowLeft":e.x=-i;break;case"ArrowRight":e.x=i}(e.x||e.y)&&this.editor.move(e.x,e.y)}}onDoubleClick(){const{editor:t}=this;t.single&&t.element.isBranch}listenPointEvents(t,i,s){const{editor:o}=this;t.direction=s,t.pointType=i,t.on_(e.DragEvent.START,this.onDragStart,this),t.on_(e.DragEvent.DRAG,this.onDrag,this),t.on_(e.DragEvent.END,this.onDragEnd,this),t.on_(e.PointerEvent.LEAVE,(()=>this.enterPoint=null)),"circle"!==t.name&&t.on_(e.PointerEvent.ENTER,(e=>{this.enterPoint=t,F(o,e)}))}__listenEvents(){const{rect:t,editor:i}=this;this.__eventIds=[i.on_(s.SELECT,(()=>{this.visible=i.hasTarget})),t.on_(e.DragEvent.START,this.onDragStart,this),t.on_(e.DragEvent.DRAG,i.onMove,i),t.on_(e.DragEvent.END,this.onDragEnd,this),t.on_(e.PointerEvent.ENTER,(()=>H(i))),t.on_(e.PointerEvent.DOUBLE_CLICK,this.onDoubleClick,this)]}__removeListenEvents(){this.off_(this.__eventIds),this.__eventIds.length=0}destroy(){this.editor=null,this.__removeListenEvents(),super.destroy()}}const U={editSize:"auto",stroke:"#836DFF",strokeWidth:2,pointFill:"#FFFFFF",pointSize:8,pointRadius:16,rotateGap:45,buttonsDirection:"bottom",buttonsMargin:12,moveCursor:"move",resizeCursor:["nwse-resize","ns-resize","nesw-resize","ew-resize","nwse-resize","ns-resize","nesw-resize","ew-resize"],rotateCursor:["ne-resize","e-resize","se-resize","s-resize","sw-resize","w-resize","nw-resize","n-resize"],selector:!0,hover:!0,boxSelect:!0,resizeable:!0,rotateable:!0,skewable:!0};class Z{constructor(){this.tag="EditTool"}onMove(t){const{moveX:e,moveY:i,editor:s}=t,{app:o,list:n}=s;o.lockLayout(),n.forEach((t=>{const s=t.getLocalPoint({x:e,y:i},null,!0);t.move(s.x,s.y)})),o.unlockLayout()}onScale(t){const{scaleX:e,scaleY:i,transform:s,worldOrigin:o,editor:n}=t,{app:r,list:a}=n;r.lockLayout(),a.forEach((t=>{const r="size"===n.getEditSize(t);s?t.transform(s,r):t.scaleOf(t.getInnerPoint(o),e,i,r)})),r.unlockLayout()}onRotate(t){const{rotation:e,worldOrigin:i,editor:s}=t,{app:o,list:n}=s;o.lockLayout(),n.forEach((t=>{t.rotateOf(t.getInnerPoint(i),e)})),o.unlockLayout()}onSkew(t){const{skewX:e,skewY:i,transform:s,worldOrigin:o,editor:n}=t,{app:r,list:a}=n;r.lockLayout(),a.forEach((t=>{const r="size"===n.getEditSize(t);s?t.transform(s,r):t.skewOf(t.getInnerPoint(o),e,i,r)})),r.unlockLayout()}update(t){const{simulateTarget:e,element:i}=t;t.multiple&&e.parent.updateLayout();const{x:s,y:o,scaleX:n,scaleY:r,rotation:a,skewX:h,skewY:l,width:d,height:c}=i.getLayoutBounds("box",t,!0);t.editBox.set({x:s,y:o,scaleX:n,scaleY:r,rotation:a,skewX:h,skewY:l}),t.editBox.update({x:0,y:0,width:d,height:c})}}Z.list=[];const{left:q,right:J}=m;class Q extends Z{constructor(){super(...arguments),this.tag="LineEditTool",this.scaleOfEvent=!0}onScaleWithDrag(t){const{drag:e,direction:i,lockRatio:s,around:o}=t,n=t.target,r={x:0,y:0},{toPoint:a}=n;n.rotation=0;let{x:h,y:l}=e.getInnerMove(n);s&&(Math.abs(h)>Math.abs(l)?l=0:h=0),i===q?(r.x+=h,r.y+=l,o&&(a.x-=h,a.y-=l)):(o&&(r.x-=h,r.y-=l),a.x+=h,a.y+=l),n.getLocalPointByInner(r,null,null,!0),n.getLocalPointByInner(a,null,null,!0),n.x=r.x,n.y=r.y,n.getInnerPointByLocal(a,null,null,!0),n.toPoint=a}onSkew(t){}update(t){const{rotatePoints:e,resizeLines:i,resizePoints:s}=t.editBox;super.update(t);for(let t=0;t<8;t++)t<4&&(i[t].visible=!1),s[t].visible=e[t].visible=t===q||t===J}}const $=(t,e)=>t.parent.children.indexOf(t)-e.parent.children.indexOf(e),tt=(t,e)=>e.parent.children.indexOf(e)-t.parent.children.indexOf(t),et={group(t,i,s){t.sort(tt);const{app:o,parent:n}=t[0];s||(s=new e.Group),n.addAt(s,n.children.indexOf(t[0])),t.sort($);const r=new e.Matrix(i.worldTransform);return r.divideParent(n.worldTransform),s.setTransform(r),s.editable=!0,s.hitChildren=!1,o.lockLayout(),t.forEach((t=>t.dropTo(s))),o.unlockLayout(),s},ungroup(t){const{app:e}=t[0],i=[];return e.lockLayout(),t.forEach((t=>{if(t.isBranch){const{parent:e,children:s}=t;for(;s.length;)i.push(s[0]),s[0].dropTo(e,e.children.indexOf(t));t.remove()}else i.push(t)})),e.unlockLayout(),i},toTop(t){t.sort($),t.forEach((t=>{let e;const{parent:i}=t;if(i){const{children:s}=i,o=s.length-1,n=s[o].__.zIndex,r=s.indexOf(t);r!==o?(s.splice(r,1),s.push(t),e=n+1):e=n,t.zIndex=e}}))},toBottom(t){t.sort(tt),t.forEach((t=>{let e;const{parent:i}=t;if(i){const{children:s}=i,o=s[0].__.zIndex,n=s.indexOf(t);0!==n?(s.splice(n,1),s.unshift(t),e=o-1):e=o,t.zIndex=e}}))}};class it extends e.Group{get list(){return this.leafList.list}get hasTarget(){return!!this.list.length}get multiple(){return this.list.length>1}get single(){return 1===this.list.length}get element(){return this.multiple?this.simulateTarget:this.list[0]}get buttons(){return this.editBox.buttons}get dragging(){return this.editBox.dragging}constructor(t,i){super(i),this.config=U,this.leafList=new e.LeafList,this.simulateTarget=new e.Rect({visible:!1}),this.editBox=new V(this),this.selector=new _(this),this.targetEventIds=[],t&&(this.config=e.DataHelper.default(t,this.config)),this.addMany(this.selector,this.editBox)}hasItem(t){return this.leafList.has(t)}addItem(t){this.hasItem(t)||t.locked||(this.leafList.add(t),this.target=this.leafList.list)}removeItem(t){this.hasItem(t)&&(this.leafList.remove(t),this.target=this.leafList.list)}shiftItem(t){this.hasItem(t)?this.removeItem(t):this.addItem(t)}update(){this.target&&(this.editTool.update(this),this.selector.update())}updateEditTool(){this.editTool=function(t){if(1===t.length){const i=t[0];return i instanceof e.Line&&!i.points?new Q:new Z}return new Z}(this.list)}getEditSize(t){let{editSize:e}=this.config;return"auto"===e?t.editSize:e}onMove(t){const e=t.getLocalMove(this.element);t.shiftKey&&(Math.abs(e.x)>Math.abs(e.y)?e.y=0:e.x=0),this.move(e.x,e.y)}onScale(t){const{element:e}=this,{direction:i}=t.current;let{around:s,lockRatio:o}=this.config;t.shiftKey&&(o=!0);const n=R.getScaleData(e.boxBounds,i,t.getInnerMove(e),o,R.getAround(s,t.altKey));this.editTool.onScaleWithDrag?(n.drag=t,this.scaleWithDrag(n)):this.scaleOf(n.origin,n.scaleX,n.scaleY)}onRotate(t){const{skewable:i,around:s,rotateGap:o}=this.config,{direction:n,name:r}=t.current;if(i&&"resize-line"===r)return this.onSkew(t);const{element:a,editBox:h}=this;let l,d;if(t instanceof e.RotateEvent)d=t.rotation,l=a.getInnerPoint(t);else{const e={x:t.x-t.moveX,y:t.y-t.moveY},i=R.getRotateData(a.boxBounds,n,t.getInner(a),a.getInnerPoint(e),t.shiftKey?null:s||"center");d=i.rotation,l=i.origin}d=e.MathHelper.getGapRotation(d,o,a.rotation),d&&(h.flippedOne&&(d=-d),this.rotateOf(l,d))}onSkew(t){const{element:e}=this,{around:i}=this.config,{origin:s,skewX:o,skewY:n}=R.getSkewData(e.boxBounds,t.current.direction,t.getInnerMove(e),R.getAround(i,t.altKey));(o||n)&&this.skewOf(s,o,n)}move(t,e){const{element:i}=this,s=i.getWorldPointByLocal({x:t,y:e},null,!0),n=new o(o.MOVE,{target:i,editor:this,moveX:s.x,moveY:s.y});this.editTool.onMove(n),this.emitEvent(n),this.multiple&&i.move(t,e)}scaleWithDrag(t){const{element:e}=this,i=e.getWorldPoint(t.origin),s=new n(n.SCALE,Object.assign(Object.assign({},t),{target:e,editor:this,worldOrigin:i}));this.editTool.onScaleWithDrag(s),this.emitEvent(s)}scaleOf(t,i,s=i,o){const{element:r}=this,a=r.getWorldPoint(t);let h;if(this.multiple){const o=Object.assign({},r.localTransform);r.scaleOf(t,i,s),h=new e.Matrix(r.localTransform).divide(o)}const l=new n(n.SCALE,{target:r,editor:this,worldOrigin:a,scaleX:i,scaleY:s,transform:h});this.editTool.onScale(l),this.emitEvent(l)}rotateOf(t,e){const{element:i}=this,s=i.getWorldPoint(t),o=new r(r.ROTATE,{target:i,editor:this,worldOrigin:s,rotation:e});this.editTool.onRotate(o),this.emitEvent(o),this.multiple&&i.rotateOf(t,e)}skewOf(t,i,s=0,o){const{element:n}=this,r=n.getWorldPoint(t);let h;if(this.multiple){const o=Object.assign({},n.localTransform);n.skewOf(t,i,s),h=new e.Matrix(n.localTransform).divide(o)}const l=new a(a.SKEW,{target:n,editor:this,skewX:i,skewY:s,transform:h,worldOrigin:r});this.editTool.onSkew(l),this.emitEvent(l)}group(){this.multiple&&(this.target=et.group(this.list,this.element))}ungroup(){this.list.length&&(this.target=et.ungroup(this.list))}lock(){this.list.forEach((t=>t.locked=!0)),this.update()}unlock(){this.list.forEach((t=>t.locked=!1)),this.update()}toTop(){this.list.length&&(et.toTop(this.list),this.leafList.update())}toBottom(){this.list.length&&(et.toBottom(this.list),this.leafList.update())}listenTargetEvents(){if(!this.targetEventIds.length){const{leafer:t}=this.list[0];this.targetEventIds=[t.on_(e.RenderEvent.START,this.update,this),t.on_([e.KeyEvent.HOLD,e.KeyEvent.UP],(t=>{F(this,t)})),t.on_(e.KeyEvent.DOWN,this.editBox.onArrow,this.editBox)]}}removeTargetEvents(){const{targetEventIds:t}=this;t.length&&(this.off_(t),t.length=0)}destroy(){this.destroyed||(this.simulateTarget.destroy(),this.target=this.hoverTarget=this.simulateTarget=null,super.destroy())}}return i([h((function(t){t.emitEvent(new s(s.HOVER,{editor:t}))}))],it.prototype,"hoverTarget",void 0),i([h((function(t){const{target:i}=t;i?t.leafList=i instanceof e.LeafList?i:new e.LeafList(i):t.leafList.reset(),t.emitEvent(new s(s.SELECT,{editor:t})),t.hasTarget?t.waitLeafer((()=>{t.multiple&&function(t){const{simulateTarget:i,leafList:s}=t,{x:o,y:n,width:r,height:a}=(new e.Bounds).setListWithFn(s.list,(t=>t.worldBoxBounds)),h=i.parent=s.list[0].leafer.zoomLayer,{scaleX:l,scaleY:d,e:c,f:g}=h.__world;i.reset({x:(o-c)/l,y:(n-g)/d,width:r/l,height:a/d})}(t),H(t),t.updateEditTool(),t.update(),t.listenTargetEvents()})):t.removeTargetEvents()}))],it.prototype,"target",void 0),e.Creator.editor=function(t){return new it(t)},t.EditBox=V,t.EditDataHelper=R,t.EditPoint=j,t.EditSelect=_,t.EditSelectHelper=E,t.EditTool=Z,t.Editor=it,t.EditorEvent=s,t.EditorHelper=et,t.EditorMoveEvent=o,t.EditorRotateEvent=r,t.EditorScaleEvent=n,t.EditorSkewEvent=a,t.LineEditTool=Q,t.SelectArea=f,t.Stroker=u,t}({},LeaferUI);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer-in/editor",
3
- "version": "1.0.0-rc.6",
3
+ "version": "1.0.0-rc.7",
4
4
  "description": "@leafer-in/editor",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -28,12 +28,10 @@
28
28
  "leaferjs"
29
29
  ],
30
30
  "dependencies": {
31
- "@leafer-ui/core": "1.0.0-rc.6",
32
- "@leafer/core": "1.0.0-rc.6"
31
+ "@leafer-ui/core": "1.0.0-rc.7"
33
32
  },
34
33
  "devDependencies": {
35
- "@leafer-ui/interface": "1.0.0-rc.6",
36
- "@leafer/interface": "1.0.0-rc.6",
37
- "@leafer-in/interface": "1.0.0-rc.6"
34
+ "@leafer-ui/interface": "1.0.0-rc.7",
35
+ "@leafer-in/interface": "1.0.0-rc.7"
38
36
  }
39
37
  }
package/src/Editor.ts CHANGED
@@ -1,233 +1,307 @@
1
- import { IGroupInputData, IPolygon, IUI, IEventListenerId, IAround } from '@leafer-ui/interface'
2
- import { IEditor, IEditorConfig, IEditorTool, IDirection8 } from '@leafer-in/interface'
1
+ import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize } from '@leafer-ui/interface'
2
+ import { Group, Rect, DragEvent, RotateEvent, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, KeyEvent } from '@leafer-ui/core'
3
3
 
4
- import { Group, Rect, Polygon, DragEvent, PointHelper, PointerEvent, KeyEvent, RotateEvent, DataHelper, MathHelper, RenderEvent } from '@leafer-ui/core'
4
+ import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent } from '@leafer-in/interface'
5
5
 
6
- import { getResizeData } from './resize'
7
- import { updateCursor } from './cursor'
6
+ import { EditorMoveEvent } from './event/EditorMoveEvent'
7
+ import { EditorScaleEvent } from './event/EditorScaleEvent'
8
+ import { EditorRotateEvent } from './event/EditorRotateEvent'
9
+ import { EditorSkewEvent } from './event/EditorSkewEvent'
8
10
 
9
- import { LineTool } from './tool/LineTool'
10
- import { RectTool } from './tool/RectTool'
11
+ import { EditSelect } from './display/EditSelect'
12
+ import { EditBox } from './display/EditBox'
11
13
 
12
- import { EditorResizeEvent } from './event/EditorResizeEvent'
13
- import { EditorRotateEvent } from './event/EditorRotateEvent'
14
+ import { config } from './config'
15
+ import { getEditTool } from './tool'
16
+
17
+ import { onTarget, onHover } from './editor/target'
18
+ import { targetAttr } from './decorator/data'
19
+ import { EditorHelper } from './helper/EditorHelper'
20
+ import { EditDataHelper } from './helper/EditDataHelper'
21
+ import { updateCursor } from './editor/cursor'
14
22
 
15
23
 
16
24
  export class Editor extends Group implements IEditor {
17
25
 
18
- public config: IEditorConfig = {
19
- type: 'pc',
20
- stroke: '#836DFF',
21
- pointFill: '#FFFFFF',
22
- pointSize: 10,
23
- pointRadius: 10,
24
- rotateGap: 90,
25
- hideOnMove: false,
26
- moveCursor: 'move',
27
- resizeType: 'auto',
28
- resizeCursor: ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize'],
29
- rotateCursor: ['ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize', 'n-resize'],
30
- resizeable: true,
31
- rotateable: true
32
- }
26
+ public config = config
33
27
 
34
- public resizePoints: IUI[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
35
- public rotatePoints: IUI[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
36
- public resizeLines: IUI[] = [] // top, right, bottom, left
28
+ @targetAttr(onHover)
29
+ public hoverTarget: IUI
37
30
 
38
- public targetRect: IUI = new Rect({ hitFill: 'all', hitRadius: 5 })
39
- public rect: IPolygon = new Polygon({ hittable: false, strokeAlign: 'center' })
40
- public circle: IUI = new Rect({ around: 'center', hitRadius: 10 }) // rotate point
31
+ @targetAttr(onTarget)
32
+ public target: IUI | IUI[] | ILeafList
41
33
 
42
- public tool: IEditorTool
34
+ public leafList: ILeafList = new LeafList() // from target
35
+ public get list(): IUI[] { return this.leafList.list as IUI[] }
43
36
 
44
- private _target: IUI
45
- public get target(): IUI { return this._target }
46
- public set target(value: IUI) {
47
- this.__removeTargetEvents()
48
- this.visible = !!value
37
+ public get hasTarget(): boolean { return !!this.list.length }
38
+ public get multiple(): boolean { return this.list.length > 1 }
39
+ public get single(): boolean { return this.list.length === 1 }
49
40
 
50
- this._target = value
51
- if (value) this.onTarget()
52
- }
41
+ public get element() { return this.multiple ? this.simulateTarget : this.list[0] as IUI }
42
+ public simulateTarget: IUI = new Rect({ visible: false })
53
43
 
54
- public enterPoint: IUI
44
+ public editBox: IEditBox = new EditBox(this)
45
+ public get buttons() { return this.editBox.buttons }
46
+
47
+ public editTool: IEditTool
48
+ public selector: EditSelect = new EditSelect(this)
49
+
50
+ public get dragging(): boolean { return this.editBox.dragging }
51
+
52
+ public targetEventIds: IEventListenerId[] = []
55
53
 
56
- protected __eventIds: IEventListenerId[] = []
57
- protected __targetEventIds: IEventListenerId[] = []
58
54
 
59
55
  constructor(userConfig?: IEditorConfig, data?: IGroupInputData) {
60
56
  super(data)
61
57
  if (userConfig) this.config = DataHelper.default(userConfig, this.config)
62
- this.init()
58
+ this.addMany(this.selector, this.editBox)
63
59
  }
64
60
 
65
- protected init() {
66
- let rotatePoint: IUI, resizeLine: IUI, resizePoint: IUI
67
- const { resizePoints, rotatePoints, resizeLines } = this
68
- const arounds: IAround[] = [{ x: 1, y: 1 }, 'center', { x: 0, y: 1 }, 'center', { x: 0, y: 0 }, 'center', { x: 1, y: 0 }, 'center']
69
-
70
- for (let i = 0; i < 8; i++) {
71
- rotatePoint = new Rect({ around: arounds[i], width: 15, height: 15, hitFill: "all" })
72
- rotatePoints.push(rotatePoint)
73
- this.__listenPointEvents(rotatePoint, 'rotate', i)
61
+ // item
74
62
 
75
- if (i % 2) {
76
- resizeLine = new Rect({ around: 'center', width: 10, height: 10, hitFill: "all" })
77
- resizeLines.push(resizeLine)
78
- this.__listenPointEvents(resizeLine, 'resize', i)
79
- }
63
+ public hasItem(item: IUI): boolean {
64
+ return this.leafList.has(item)
65
+ }
80
66
 
81
- resizePoint = new Rect({ around: 'center', hitRadius: 5 })
82
- resizePoints.push(resizePoint)
83
- this.__listenPointEvents(resizePoint, 'resize', i)
84
- }
67
+ public addItem(item: IUI): void {
68
+ if (!this.hasItem(item) && !item.locked) this.leafList.add(item), this.target = this.leafList.list as IUI[]
69
+ }
85
70
 
86
- this.__listenPointEvents(this.circle, 'rotate', 1)
87
- this.addMany(...rotatePoints, this.targetRect, this.rect, this.circle, ...resizeLines, ...resizePoints)
71
+ public removeItem(item: IUI): void {
72
+ if (this.hasItem(item)) this.leafList.remove(item), this.target = this.leafList.list as IUI[]
73
+ }
88
74
 
89
- this.__listenEvents()
75
+ public shiftItem(item: IUI): void {
76
+ this.hasItem(item) ? this.removeItem(item) : this.addItem(item)
90
77
  }
91
78
 
79
+ // update
92
80
 
93
- protected onTarget(): void {
94
- this.tool = this.getTool(this.target)
95
- this.waitLeafer(() => {
96
- this.update()
97
- this.updateMoveCursor()
98
- this.__listenTargetEvents()
99
- })
81
+ public update(): void {
82
+ if (this.target) {
83
+ this.editTool.update(this)
84
+ this.selector.update()
85
+ }
100
86
  }
101
87
 
102
- public getTool(value: IUI): IEditorTool {
103
- return (value.tag === 'Line' && value.resizeable) ? LineTool : RectTool
88
+ public updateEditTool(): void {
89
+ this.editTool = getEditTool(this.list)
104
90
  }
105
91
 
106
- public update(): void {
107
- if (!this.target) return
108
- this.tool.update(this)
92
+ // get
93
+
94
+ public getEditSize(ui: IUI): IEditSize {
95
+ let { editSize } = this.config
96
+ return editSize === 'auto' ? ui.editSize : editSize
109
97
  }
110
98
 
99
+ // operate
111
100
 
112
- protected onDrag(e: DragEvent): void {
113
- const { resizeable, rotateable } = this.config
114
- if (e.metaKey || e.ctrlKey || !resizeable) {
115
- if (rotateable) this.onRotate(e)
116
- } else {
117
- this.onResize(e)
101
+ public onMove(e: DragEvent): void {
102
+ const move = e.getLocalMove(this.element)
103
+
104
+ if (e.shiftKey) {
105
+ if (Math.abs(move.x) > Math.abs(move.y)) move.y = 0
106
+ else move.x = 0
118
107
  }
108
+
109
+ this.move(move.x, move.y)
119
110
  }
120
111
 
121
- protected onMove(e: DragEvent): void {
122
- const { target } = this
123
- const { x, y } = e.getLocalMove(target)
124
- if (e.shiftKey) {
125
- if (Math.abs(x) > Math.abs(y)) {
126
- target.x += x
127
- } else {
128
- target.y += y
129
- }
112
+ public onScale(e: DragEvent): void {
113
+ const { element } = this
114
+ const { direction } = e.current as IEditPoint
115
+
116
+ let { around, lockRatio } = this.config
117
+ if (e.shiftKey) lockRatio = true
118
+
119
+ const data = EditDataHelper.getScaleData(element.boxBounds, direction, e.getInnerMove(element), lockRatio, EditDataHelper.getAround(around, e.altKey))
120
+
121
+ if (this.editTool.onScaleWithDrag) {
122
+ data.drag = e
123
+ this.scaleWithDrag(data)
130
124
  } else {
131
- target.x += x
132
- target.y += y
125
+ this.scaleOf(data.origin, data.scaleX, data.scaleY)
133
126
  }
127
+
134
128
  }
135
129
 
136
- protected onRotate(e: DragEvent | RotateEvent): void {
137
- const { target } = this
138
- const { rotateGap } = this.config
139
- const { x, y, width, height } = target.boxBounds
140
- const origin = { x: x + width / 2, y: y + height / 2 }
130
+ public onRotate(e: DragEvent | RotateEvent): void {
131
+ const { skewable, around, rotateGap } = this.config
132
+ const { direction, name } = e.current as IEditPoint
133
+ if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
141
134
 
142
- let rotation: number
135
+ const { element, editBox } = this
136
+ let origin: IPointData, rotation: number
143
137
 
144
138
  if (e instanceof RotateEvent) {
145
- rotation = e.rotation
139
+ rotation = e.rotation, origin = element.getInnerPoint(e)
146
140
  } else {
147
- const point = e
148
- const last = { x: point.x - e.moveX, y: point.y - e.moveY }
149
- rotation = PointHelper.getChangeAngle(last, target.getWorldPoint(origin), point)
141
+ const last = { x: e.x - e.moveX, y: e.y - e.moveY }
142
+ const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getInner(element), element.getInnerPoint(last), e.shiftKey ? null : (around || 'center'))
143
+ rotation = data.rotation
144
+ origin = data.origin
150
145
  }
151
146
 
152
- rotation = MathHelper.getGapRotation(target.rotation + rotation, rotateGap) - target.rotation
147
+ rotation = MathHelper.getGapRotation(rotation, rotateGap, element.rotation)
148
+ if (!rotation) return
153
149
 
154
- const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { editor: this, target, origin, rotation })
150
+ if (editBox.flippedOne) rotation = -rotation
155
151
 
156
- this.tool.rotate(event)
157
- target.emitEvent(event)
152
+ this.rotateOf(origin, rotation)
158
153
  }
159
154
 
160
- public onResize(e: DragEvent): void {
161
- const { target } = this
162
- const { __direction } = e.current.__
163
155
 
164
- let { resizeType, around, lockRatio } = this.config
156
+ public onSkew(e: DragEvent): void {
157
+ const { element } = this
158
+ const { around } = this.config
165
159
 
166
- if (e.shiftKey) lockRatio = true
167
- if (e.altKey && !around) around = 'center'
160
+ const { origin, skewX, skewY } = EditDataHelper.getSkewData(element.boxBounds, (e.current as IEditPoint).direction, e.getInnerMove(element), EditDataHelper.getAround(around, e.altKey))
161
+ if (!skewX && !skewY) return
162
+
163
+ this.skewOf(origin, skewX, skewY)
164
+ }
165
+
166
+
167
+ // transform
168
168
 
169
- if (resizeType === 'auto') resizeType = target.resizeable ? 'size' : 'scale'
170
- const data = getResizeData(target.boxBounds, __direction, e.getInnerMove(this.targetRect), lockRatio, around)
169
+ public move(x: number, y: number): void {
170
+ const { element } = this
171
+ const world = element.getWorldPointByLocal({ x, y }, null, true)
172
+ const event = new EditorMoveEvent(EditorMoveEvent.MOVE, { target: element, editor: this, moveX: world.x, moveY: world.y })
171
173
 
172
- const event = new EditorResizeEvent(EditorResizeEvent.RESIZE, { ...data, target, editor: this, dragEvent: e, resizeType })
174
+ this.editTool.onMove(event)
175
+ this.emitEvent(event)
173
176
 
174
- this.tool.resize(event)
175
- target.emitEvent(event)
177
+ if (this.multiple) element.move(x, y)
176
178
  }
177
179
 
180
+ public scaleWithDrag(data: IEditorScaleEvent): void {
181
+ const { element } = this
182
+ const worldOrigin = element.getWorldPoint(data.origin)
183
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { ...data, target: element, editor: this, worldOrigin })
178
184
 
179
- public updateMoveCursor(): void {
180
- this.targetRect.cursor = this.config.moveCursor
185
+ this.editTool.onScaleWithDrag(event)
186
+ this.emitEvent(event)
181
187
  }
182
188
 
189
+ public scaleOf(origin: IPointData, scaleX: number, scaleY = scaleX, _resize?: boolean): void {
190
+ const { element } = this
191
+ const worldOrigin = element.getWorldPoint(origin)
183
192
 
184
- protected __listenEvents(): void {
185
- this.__eventIds = [
186
- this.targetRect.on_(DragEvent.START, () => { this.opacity = this.config.hideOnMove ? 0 : 1 }),
187
- this.targetRect.on_(DragEvent.DRAG, this.onMove, this),
188
- this.targetRect.on_(DragEvent.END, () => { this.opacity = 1 }),
189
- this.targetRect.on_(PointerEvent.ENTER, this.updateMoveCursor, this)
190
- ]
193
+ let transform: Matrix
194
+
195
+ if (this.multiple) {
196
+ const childMatrix = { ...element.localTransform }
197
+ element.scaleOf(origin, scaleX, scaleY)
198
+ transform = new Matrix(element.localTransform).divide(childMatrix)
199
+ }
200
+
201
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform })
202
+
203
+ this.editTool.onScale(event)
204
+ this.emitEvent(event)
191
205
  }
192
206
 
193
- protected __removeListenEvents(): void {
194
- this.targetRect.off_(this.__eventIds)
195
- this.__eventIds.length = 0
207
+ public rotateOf(origin: IPointData, rotation: number): void {
208
+ const { element } = this
209
+ const worldOrigin = element.getWorldPoint(origin)
210
+
211
+ const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation })
212
+
213
+ this.editTool.onRotate(event)
214
+ this.emitEvent(event)
215
+
216
+ if (this.multiple) element.rotateOf(origin, rotation)
196
217
  }
197
218
 
219
+ public skewOf(origin: IPointData, skewX: number, skewY = 0, _resize?: boolean): void {
220
+ const { element } = this
221
+ const worldOrigin = element.getWorldPoint(origin)
198
222
 
199
- protected __listenPointEvents(point: IUI, type: 'rotate' | 'resize', direction: IDirection8): void {
200
- point.__.__direction = direction
201
- const resize = point.__.__isResizePoint = type === 'resize'
202
- point.on_(DragEvent.DRAG, resize ? this.onDrag : this.onRotate, this) // i % 2 ? this.onSkew :
203
- point.on_(PointerEvent.LEAVE, () => this.enterPoint = null)
204
- point.on_(PointerEvent.ENTER, (e) => { this.enterPoint = point; updateCursor(this, e) })
223
+ let transform: Matrix
224
+
225
+ if (this.multiple) {
226
+ const childMatrix = { ...element.localTransform }
227
+ element.skewOf(origin, skewX, skewY)
228
+ transform = new Matrix(element.localTransform).divide(childMatrix)
229
+ }
230
+
231
+ const event = new EditorSkewEvent(EditorSkewEvent.SKEW, {
232
+ target: element, editor: this, skewX, skewY, transform, worldOrigin
233
+ })
234
+
235
+ this.editTool.onSkew(event)
236
+ this.emitEvent(event)
205
237
  }
206
238
 
239
+ // group
207
240
 
208
- protected __listenTargetEvents(): void {
209
- if (this.target) {
210
- const { leafer } = this.target
211
- this.__targetEventIds = [
241
+ public group(): void {
242
+ if (this.multiple) this.target = EditorHelper.group(this.list, this.element)
243
+ }
244
+
245
+
246
+ public ungroup(): void {
247
+ if (this.list.length) this.target = EditorHelper.ungroup(this.list)
248
+ }
249
+
250
+ // lock
251
+
252
+ public lock(): void {
253
+ this.list.forEach(leaf => leaf.locked = true)
254
+ this.update()
255
+ }
256
+
257
+ public unlock(): void {
258
+ this.list.forEach(leaf => leaf.locked = false)
259
+ this.update()
260
+ }
261
+
262
+ // level
263
+
264
+ public toTop(): void {
265
+ if (this.list.length) {
266
+ EditorHelper.toTop(this.list)
267
+ this.leafList.update()
268
+ }
269
+ }
270
+
271
+ public toBottom(): void {
272
+ if (this.list.length) {
273
+ EditorHelper.toBottom(this.list)
274
+ this.leafList.update()
275
+ }
276
+ }
277
+
278
+ // event
279
+
280
+ public listenTargetEvents(): void {
281
+ if (!this.targetEventIds.length) {
282
+ const { leafer } = this.list[0]
283
+ this.targetEventIds = [
212
284
  leafer.on_(RenderEvent.START, this.update, this),
213
- leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e) => { updateCursor(this, e) })
285
+ leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e: KeyEvent) => { updateCursor(this, e) }),
286
+ leafer.on_(KeyEvent.DOWN, this.editBox.onArrow, this.editBox)
214
287
  ]
215
288
  }
216
289
  }
217
290
 
218
- protected __removeTargetEvents(): void {
219
- if (this.__targetEventIds.length) {
220
- const { leafer } = this.target
221
- if (leafer) leafer.off_(this.__targetEventIds)
222
- this.__targetEventIds.length = 0
291
+ public removeTargetEvents(): void {
292
+ const { targetEventIds } = this
293
+ if (targetEventIds.length) {
294
+ this.off_(targetEventIds)
295
+ targetEventIds.length = 0
223
296
  }
224
297
  }
225
298
 
226
-
227
299
  public destroy(): void {
228
- this.__removeListenEvents()
229
- this._target = null
230
- super.destroy()
300
+ if (!this.destroyed) {
301
+ this.simulateTarget.destroy()
302
+ this.target = this.hoverTarget = this.simulateTarget = null
303
+ super.destroy()
304
+ }
231
305
  }
232
306
 
233
307
  }
package/src/config.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { IEditorConfig } from '@leafer-in/interface'
2
+
3
+ export const config: IEditorConfig = {
4
+ editSize: 'auto',
5
+
6
+ stroke: '#836DFF',
7
+ strokeWidth: 2,
8
+
9
+ pointFill: '#FFFFFF',
10
+ pointSize: 8,
11
+ pointRadius: 16,
12
+
13
+ rotateGap: 45,
14
+
15
+ buttonsDirection: 'bottom',
16
+ buttonsMargin: 12,
17
+
18
+ moveCursor: 'move',
19
+ resizeCursor: ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize'],
20
+ rotateCursor: ['ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize', 'n-resize'],
21
+
22
+ selector: true,
23
+ hover: true,
24
+ boxSelect: true,
25
+
26
+ resizeable: true,
27
+ rotateable: true,
28
+ skewable: true
29
+ }
@@ -0,0 +1,13 @@
1
+ import { IFunction, ILeaf, IObject } from '@leafer-ui/interface'
2
+ import { defineKey } from '@leafer-ui/core'
3
+
4
+
5
+ export function targetAttr(fn: IFunction) {
6
+ return (target: ILeaf, key: string) => {
7
+ const privateKey = '_' + key
8
+ defineKey(target, key, {
9
+ get() { return (this as IObject)[privateKey] },
10
+ set(value: unknown) { if ((this as IObject)[privateKey] !== value) (this as IObject)[privateKey] = value, fn(this) }
11
+ } as ThisType<ILeaf>)
12
+ }
13
+ }