fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
3 lines (2 loc) • 16.1 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("fabric"),require("westures")):"function"==typeof define&&define.amd?define(["exports","fabric","westures"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).fabricExtensions={},t.fabric,t.westures)}(this,function(t,e,n){"use strict";function i(t,e,n){return(e=function(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var i=n.call(t,e);if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function r(t,e){return Math.abs(t-e)}function o(t,e,n){let i=1/0,o=[];for(const s of e){const e=r(t[n],s[n]);i>e&&(o=[],i=e),i==e&&o.push(s)}return{dis:i,arr:o}}function s(t){const{target:e,isScale:n,isUniform:i,corner:r,point:s,diagonalPoint:a,list:c,isCenter:l}=t,{dis:h,arr:d}=o(s,c,"x");if(h>this.margin/this.canvas.getZoom())return[];let g=d[d.length-1].x-s.x;g*=r.includes("l")?-1:1;const{width:f,height:u,scaleX:p,scaleY:m}=e,v=p*f+(e.strokeUniform?0:e.strokeWidth),b=(g+v)/v;if(0==b)return[];if(n?(e.set("scaleX",p*b),i&&e.set("scaleY",m*b)):(e.set("width",f*b),i&&e.set("height",u*b)),l)e.setRelativeXY(a,"center","center");else{const t=this.contraryOriginMap;e.setRelativeXY(a,...t[r])}return e.setCoords(),d.map(t=>({origin:s,target:t}))}function a(t){const{target:e,isScale:n,isUniform:i,corner:r,point:s,diagonalPoint:a,list:c,isCenter:l}=t,{dis:h,arr:d}=o(s,c,"y");if(h>this.margin/this.canvas.getZoom())return[];let g=d[d.length-1].y-s.y;g*=r.includes("t")?-1:1;const{width:f,height:u,scaleX:p,scaleY:m}=e,v=m*u+(e.strokeUniform?0:e.strokeWidth),b=(g+v)/v;if(0==b)return[];if(n?(e.set("scaleY",m*b),i&&e.set("scaleX",p*b)):(e.set("height",u*b),i&&e.set("width",f*b)),l)e.setRelativeXY(a,"center","center");else{const t=this.contraryOriginMap;e.setRelativeXY(a,...t[r])}return e.setCoords(),d.map(t=>({origin:s,target:t}))}function c(t,e){const n=this.canvas.getTopContext(),i=this.canvas.viewportTransform,r=this.canvas.getZoom();n.save(),n.transform(...i),n.lineWidth=this.width/r,this.lineDash&&n.setLineDash(this.lineDash),n.strokeStyle=this.color,n.beginPath(),n.moveTo(t.x,t.y),n.lineTo(e.x,e.y),n.stroke(),this.lineDash&&n.setLineDash([]),this.drawX(t,-1),this.drawX(e,1),n.restore()}function l(t,e){const n=this.canvas.getTopContext(),i=this.canvas.getZoom(),r=this.xSize/i;n.save(),n.translate(t.x,t.y),n.beginPath(),n.moveTo(-r,-r),n.lineTo(r,r),n.moveTo(r,-r),n.lineTo(-r,r),n.stroke(),n.restore()}function h(t){const e=this.canvas.getTopContext(),n=this.canvas.viewportTransform,i=this.canvas.getZoom();e.save(),e.transform(...n),e.lineWidth=this.width/i,e.strokeStyle=this.color;for(const e of t)this.drawX(e,0);e.restore()}function d(){const t=[];if(!this.closeVLine)for(const e of this.verticalLines)t.push(JSON.parse(e));if(!this.closeHLine)for(const e of this.horizontalLines)t.push(JSON.parse(e));const e=t.map(t=>t.target);h.call(this,e)}function g(){if(!this.closeVLine)for(const t of this.verticalLines){const{origin:n,target:i}=JSON.parse(t),r=new e.Point(i.x,n.y);this.drawLine(r,i)}}function f(){if(!this.closeHLine)for(const t of this.horizontalLines){const{origin:n,target:i}=JSON.parse(t),r=new e.Point(n.x,i.y);this.drawLine(r,i)}}function u(t,e){const n=t.getCoords();n.push(t.getCenterPoint());const i={target:t,list:n,points:e,margin:this.margin/this.canvas.getZoom()};return{vLines:m({...i,type:"x"}),hLines:m({...i,type:"y"})}}const p=[["left","top"],["right","top"],["right","bottom"],["left","bottom"],["center","center"]];function m(t){const{target:e,list:n,points:i,margin:r,type:s}=t,a=[],c=[];let l=1/0;for(const t of n){const e=o(t,i,s);c.push(e),l>e.dis&&(l=e.dis)}if(l>r)return a;let h=!1;for(let t=0;t<n.length;t++){if(c[t].dis!=l)continue;for(const e of c[t].arr)a.push({origin:n[t],target:e});if(h)continue;h=!0;const i=c[t].arr[0][s]-n[t][s];n.forEach(t=>{t[s]+=i}),e.setXY(n[t],...p[t]),e.setCoords()}return a}function v(t){const n=new Set,i=t.canvas;if(!i)return n;const r=t instanceof e.ActiveSelection?t.getObjects():[t];return i.forEachObject(t=>{t.isOnScreen()&&t.visible&&(t.constructor!=e.Group?n.add(t):w(n,t))}),b(n,r),n}function b(t,n){for(const i of n)i.constructor==e.Group?b(t,i.getObjects()):t.delete(i)}function w(t,n){const i=n.getObjects();for(const n of i)n.visible&&(n.constructor!=e.Group?t.add(n):w(t,n))}const y=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"left",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"top";return async function(r){const{originX:o=n,originY:s=i}=r;delete r.originX,delete r.originY;for(var a=arguments.length,c=new Array(a>1?a-1:0),l=1;l<a;l++)c[l-1]=arguments[l];const h=await t.call(this,r,...c),d=new e.Point(h.left,h.top);return h.setPositionByOrigin(d,o,s),h}},C=t=>async function(n){const{colorStops:i}=n,r=null==i?void 0:i.map(t=>{let{color:n,opacity:i,offset:r}=t;if(void 0===i||1===i)return{color:n,offset:r};return{color:new e.Color(n).setAlpha(i).toRgba(),offset:r}});return await t.call(this,{...n,colorStops:r})};const{wrapWithFixedAnchor:O,wrapWithFireEvent:P}=e.controlsUtils,x=P("CROPPING",O((t,n,i,r)=>{const{target:o}=n,{width:s}=o,a=o,c=e.controlsUtils.changeObjectWidth(t,n,i,r),l=a._element.width-a.cropX;return c&&(a.width>l&&(a.width=l),a.width<1&&(a.width=1)),s!==a.width})),S=P("CROPPING",O((t,n,i,r)=>{const{target:o}=n,{height:s}=o,a=o,c=e.controlsUtils.changeObjectHeight(t,n,i,r),l=a._element.height-a.cropY;return c&&(a.height>l&&(a.height=l),a.height<1&&(a.height=1)),s!==a.height})),T=P("CROPPING",O((t,n,i,r)=>{const{target:o}=n,s=o,{width:a,cropX:c}=s,l=e.controlsUtils.changeObjectWidth(t,n,i,r);let h=c+a-s.width;return s.width=a,l&&(h<0&&(h=0),s.cropX=h,s.width+=c-h),h!==c})),X=P("CROPPING",O((t,n,i,r)=>{const{target:o}=n,s=o,{height:a,cropY:c}=s,l=e.controlsUtils.changeObjectHeight(t,n,i,r);let h=c+a-s.height;return s.height=a,l&&(h<0&&(h=0),s.cropY=h,s.height+=c-h),h!==c})),z=t=>{let{transform:n}=t;const{target:i,original:r}=n,o=i,s=new e.Point(i.left-r.left,i.top-r.top).transform(e.util.invertTransform(e.util.createRotateMatrix({angle:o.getTotalAngle()})));let a=r.cropX-s.x/o.scaleX,c=r.cropY-s.y/o.scaleY;const{width:l,height:h,_element:d}=o;a<0&&(a=0),c<0&&(c=0),a+l>d.width&&(a=d.width-l),c+h>d.height&&(c=d.height-h),o.cropX=a,o.cropY=c,o.left=r.left,o.top=r.top};function R(t,n,i){const r=i.calcTransformMatrix(),o=i.getViewportTransform(),s=e.util.multiplyTransformMatrices(o,r);let a=0,c=0;return a=this.x<0?-i.width/2-i.cropX:i.getElement().width-i.width/2-i.cropX,c=this.y<0?-i.height/2-i.cropY:i.getElement().height-i.height/2-i.cropY,new e.Point(a,c).transform(s)}const Y=(t,n)=>(i,r,o,s)=>{const{target:a}=r,{width:c,height:l}=a.getElement(),h=c-a.width-a.cropX,d=l-a.height-a.cropY,g=t<0?1+h/a.width:-a.cropX/a.width,f=n<0?1+d/a.height:-a.cropY/a.height,u=a.translateToOriginPoint(a.getCenterPoint(),g,f),p=e.controlsUtils.getLocalPoint(r,g,f,o,s),m=(v=p,b=l,w=c,Math.min(Math.abs(v.x/w),Math.abs(v.y/b)));var v,b,w;const y=m/a.scaleX,C=m/a.scaleY,O=h/y,P=d/C,x=a.width/y,S=a.height/C,T=t<0?c-x-O:a.cropX/y,X=n<0?l-S-P:a.cropY/C;if((t<0?O:T)+x>c||(n<0?P:X)+S>l)return!1;a.scaleX=m,a.scaleY=m,a.width=x,a.height=S,a.cropX=T,a.cropY=X;const z=t<0?1+O/x:-T/x,R=n<0?1+P/S:-X/S;return a.setPositionByOrigin(u,z,R),!0};function H(t){let{ctx:e}=t;const n=e.globalAlpha;e.globalAlpha*=.5,e.drawImage(this._element,-this.width/2-this.cropX,-this.height/2-this.cropY),e.globalAlpha=n}const{degreesToRadians:j}=e.util;function L(t,e,n,i,r){t.save();const{stroke:o,xSize:s,ySize:a,opName:c}=this.commonRenderProps(t,e,n,r,i),l=s/2,h=a/2;t.rotate(j(this.angle)),t.beginPath(),t.moveTo(-h,0),t.lineTo(-h,l),t.lineTo(h,l),t.lineTo(h,h),t.lineTo(l,h),t.lineTo(l,-h),t.lineTo(-h,-h),t.closePath(),t[c](),o&&t.stroke(),t.restore()}const{scaleCursorStyleHandler:E}=e.controlsUtils,A=()=>"crop",D=()=>({tls:new e.Control({x:-.5,y:-.5,cursorStyleHandler:E,positionHandler:R,actionHandler:Y(-.5,-.5)}),brs:new e.Control({x:.5,y:.5,cursorStyleHandler:E,positionHandler:R,actionHandler:Y(.5,.5)}),trs:new e.Control({x:.5,y:-.5,cursorStyleHandler:E,positionHandler:R,actionHandler:Y(.5,-.5)}),bls:new e.Control({x:-.5,y:.5,cursorStyleHandler:E,positionHandler:R,actionHandler:Y(-.5,.5)}),mlc:new e.Control({x:-.5,y:0,sizeX:4,sizeY:20,cursorStyleHandler:E,actionHandler:T,getActionName:A}),mrc:new e.Control({x:.5,y:0,sizeX:4,sizeY:20,cursorStyleHandler:E,actionHandler:x,getActionName:A}),mbc:new e.Control({x:0,y:.5,sizeX:20,sizeY:4,cursorStyleHandler:E,actionHandler:S,getActionName:A}),mtc:new e.Control({x:0,y:-.5,sizeX:20,sizeY:4,cursorStyleHandler:E,actionHandler:X,getActionName:A}),tlc:new e.Control({angle:0,x:-.5,y:-.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:E,actionHandler:function(){const t=T(...arguments),e=X(...arguments);return t||e},getActionName:A}),trc:new e.Control({angle:90,x:.5,y:-.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:E,actionHandler:function(){const t=x(...arguments),e=X(...arguments);return t||e},getActionName:A}),blc:new e.Control({angle:270,x:-.5,y:.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:E,actionHandler:function(){const t=S(...arguments),e=T(...arguments);return t||e},getActionName:A}),brc:new e.Control({angle:180,x:.5,y:.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:E,actionHandler:function(){const t=S(...arguments),e=x(...arguments);return t||e},getActionName:A})});t.AligningGuidelines=class{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};i(this,"canvas",void 0),i(this,"horizontalLines",new Set),i(this,"verticalLines",new Set),i(this,"cacheMap",new Map),i(this,"onlyDrawPoint",!1),i(this,"contraryOriginMap",{tl:["right","bottom"],tr:["left","bottom"],br:["left","top"],bl:["right","top"],mt:["center","bottom"],mr:["left","center"],mb:["center","top"],ml:["right","center"]}),i(this,"xSize",2.4),i(this,"lineDash",void 0),i(this,"margin",4),i(this,"width",1),i(this,"color","rgba(255,0,0,0.9)"),i(this,"closeVLine",!1),i(this,"closeHLine",!1),this.canvas=t,Object.assign(this,e),this.mouseUp=this.mouseUp.bind(this),this.scalingOrResizing=this.scalingOrResizing.bind(this),this.moving=this.moving.bind(this),this.beforeRender=this.beforeRender.bind(this),this.afterRender=this.afterRender.bind(this),this.initBehavior()}initBehavior(){this.canvas.on("mouse:up",this.mouseUp),this.canvas.on("object:resizing",this.scalingOrResizing),this.canvas.on("object:scaling",this.scalingOrResizing),this.canvas.on("object:moving",this.moving),this.canvas.on("before:render",this.beforeRender),this.canvas.on("after:render",this.afterRender)}getObjectsByTarget(t){return v(t)}getPointMap(t){return function(t){const e=t.getCoords();return{tl:e[0],tr:e[1],br:e[2],bl:e[3],mt:e[0].add(e[1]).scalarDivide(2),mr:e[1].add(e[2]).scalarDivide(2),mb:e[2].add(e[3]).scalarDivide(2),ml:e[3].add(e[0]).scalarDivide(2)}}(t)}getContraryMap(t){return function(t){var e;const n=null!==(e=t.aCoords)&&void 0!==e?e:t.calcACoords();return{tl:n.br,tr:n.bl,br:n.tl,bl:n.tr,mt:n.br.add(n.bl).scalarDivide(2),mr:n.bl.add(n.tl).scalarDivide(2),mb:n.tl.add(n.tr).scalarDivide(2),ml:n.tr.add(n.br).scalarDivide(2)}}(t)}getCaCheMapValue(t){const e=[t.calcTransformMatrix().toString(),t.width,t.height].join(),n=this.cacheMap.get(e);if(n)return n;const i=t.getCoords();return i.push(t.getCenterPoint()),this.cacheMap.set(e,i),i}drawLine(t,e){c.call(this,t,e)}drawX(t,e){l.call(this,t,e)}mouseUp(){this.verticalLines.clear(),this.horizontalLines.clear(),this.cacheMap.clear(),this.canvas.requestRenderAll()}scalingOrResizing(t){const n=t.target;n.setCoords();const i=String(t.transform.action).startsWith("scale");this.verticalLines.clear(),this.horizontalLines.clear();const r=this.getObjectsByTarget(n);let o=t.transform.corner;n.flipX&&(o.includes("l")?o=o.replace("l","r"):o.includes("r")&&(o=o.replace("r","l"))),n.flipY&&(o.includes("t")?o=o.replace("t","b"):o.includes("b")&&(o=o.replace("b","t")));const c=this.getPointMap(n);if(!(o in c))return;if(this.onlyDrawPoint=o.includes("m"),this.onlyDrawPoint){if(n.getTotalAngle()%90!=0)return}const l=this.getContraryMap(n),h=c[o];let d=l[o];const g="center"==t.transform.original.originX&&"center"==t.transform.original.originY;if(g){const t=n.group?h.transform(e.util.invertTransform(n.group.calcTransformMatrix())):h;d=d.add(t).scalarDivide(2)}const f=t.e[this.canvas.uniScaleKey];let u=this.canvas.uniformScaling&&!f||!this.canvas.uniformScaling&&f;this.onlyDrawPoint&&(u=!1);const p=[];for(const t of r){const e=this.getCaCheMapValue(t);p.push(...e)}const m={target:n,point:h,diagonalPoint:d,corner:o,list:p,isScale:i,isUniform:u,isCenter:g},v=this.onlyDrawPoint&&(o.includes("t")||o.includes("b")),b=this.onlyDrawPoint&&(o.includes("l")||o.includes("r")),w=v?[]:s.call(this,m),y=b?[]:a.call(this,m);w.forEach(t=>{this.verticalLines.add(JSON.stringify(t))}),y.forEach(t=>{this.horizontalLines.add(JSON.stringify(t))})}moving(t){const e=t.target;e.setCoords(),this.onlyDrawPoint=!1,this.verticalLines.clear(),this.horizontalLines.clear();const n=this.getObjectsByTarget(e),i=[];for(const t of n)i.push(...this.getCaCheMapValue(t));const{vLines:r,hLines:o}=u.call(this,e,i);r.forEach(t=>{this.verticalLines.add(JSON.stringify(t))}),o.forEach(t=>{this.horizontalLines.add(JSON.stringify(t))})}beforeRender(){this.canvas.clearContext(this.canvas.contextTop)}afterRender(){this.onlyDrawPoint?d.call(this):(g.call(this),f.call(this))}dispose(){this.canvas.off("mouse:up",this.mouseUp),this.canvas.off("object:resizing",this.scalingOrResizing),this.canvas.off("object:scaling",this.scalingOrResizing),this.canvas.off("object:moving",this.moving),this.canvas.off("before:render",this.beforeRender),this.canvas.off("after:render",this.afterRender)}},t.addGestures=t=>{const e=new n.Region(t.upperCanvasEl);t.addOrRemove(function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),i=1;i<e;i++)n[i-1]=arguments[i];return t.removeEventListener(...n)}),e.addGesture((t=>new n.Rotate(t.upperCanvasEl,e=>{let{rotation:n,event:i}=e;t.fireEventFromPointerEvent(i,"rotate","rotate",{rotation:n})}))(t)),e.addGesture((t=>new n.Pinch(t.upperCanvasEl,e=>{let{scale:n,event:i}=e;t.fireEventFromPointerEvent(i,"pinch","pinch",{scale:n})}))(t)),e.addGesture((t=>new n.Tap(t.upperCanvasEl,e=>{let{event:n}=e;t.fireEventFromPointerEvent(n,"mouse:tripleclick","mousetripleclick",void 0),n.preventDefault()},{numTaps:3,maxRetain:400}))(t)),e.addGesture((t=>new n.Tap(t.upperCanvasEl,e=>{let{event:n}=e;t.fireEventFromPointerEvent(n,"mouse:dblclick","mousedblclick",void 0),n.preventDefault()},{numTaps:2,maxRetain:300}))(t)),t.addOrRemove(function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),i=1;i<e;i++)n[i-1]=arguments[i];return t.addEventListener(...n)},!0)},t.changeCropHeight=S,t.changeCropWidth=x,t.changeCropX=T,t.changeCropY=X,t.createImageCroppingControls=D,t.enterCropMode=function t(e){var n;let{target:i}=e;const r=i,{controls:o,padding:s}=r;r.padding=0,r.controls=D(),r.on("moving",z),r.on("before:render",H),r.setCoords();r.once("mousedblclick",()=>{var e;r.padding=s,r.off("moving",z),r.off("before:render",H),r.controls=o,r.setCoords(),r.once("mousedblclick",t),null===(e=r.canvas)||void 0===e||e.requestRenderAll()}),null===(n=r.canvas)||void 0===n||n.requestRenderAll()},t.gradientUpdaterWrapper=C,t.installGradientUpdater=()=>{e.Gradient.fromObject=C(e.Gradient.fromObject)},t.installOriginWrapperUpdater=(t,n)=>{e.BaseFabricObject._fromObject=y(e.BaseFabricObject._fromObject,t,n),e.FabricImage.fromObject=y(e.FabricImage.fromObject,t,n),e.Group.fromObject=y(e.Group.fromObject,t,n)},t.originUpdaterWrapper=y,t.pinchEventHandler=function(t){let{scale:e,target:n,scenePoint:i}=t;n&&this.getActiveObject()===n?(n.scaleX*=e,n.scaleY*=e):this.zoomToPoint(i,this.getZoom()*e)},t.rotateEventHandler=function(t){let{rotation:n,target:i}=t;i&&this.getActiveObject()===i&&i.rotate(i.angle+e.util.radiansToDegrees(n))}});
//# sourceMappingURL=fabric-extensions.min.js.map