UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

3 lines (2 loc) 14.5 kB
!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,i){"use strict";function n(t,e,i){return(e=function(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var i=t[Symbol.toPrimitive];if(void 0!==i){var n=i.call(t,e);if("object"!=typeof n)return n;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:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function r(t,e){return Math.abs(t-e)}function o(t,e,i){let n=1/0,o=[];for(const s of e){const e=r(t[i],s[i]);n>e&&(o=[],n=e),n==e&&o.push(s)}return{dis:n,arr:o}}function s(t){const{target:e,isScale:i,isUniform:n,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:v}=e,m=p*f+(e.strokeUniform?0:e.strokeWidth),b=(g+m)/m;if(0==b)return[];if(i?(e.set("scaleX",p*b),n&&e.set("scaleY",v*b)):(e.set("width",f*b),n&&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:i,isUniform:n,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:v}=e,m=v*u+(e.strokeUniform?0:e.strokeWidth),b=(g+m)/m;if(0==b)return[];if(i?(e.set("scaleY",v*b),n&&e.set("scaleX",p*b)):(e.set("height",u*b),n&&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 i=this.canvas.getTopContext(),n=this.canvas.viewportTransform,r=this.canvas.getZoom();i.save(),i.transform(...n),i.lineWidth=this.width/r,this.lineDash&&i.setLineDash(this.lineDash),i.strokeStyle=this.color,i.beginPath(),i.moveTo(t.x,t.y),i.lineTo(e.x,e.y),i.stroke(),this.lineDash&&i.setLineDash([]),this.drawX(t,-1),this.drawX(e,1),i.restore()}function l(t,e){const i=this.canvas.getTopContext(),n=this.canvas.getZoom(),r=this.xSize/n;i.save(),i.translate(t.x,t.y),i.beginPath(),i.moveTo(-r,-r),i.lineTo(r,r),i.moveTo(r,-r),i.lineTo(-r,r),i.stroke(),i.restore()}function h(t){const e=this.canvas.getTopContext(),i=this.canvas.viewportTransform,n=this.canvas.getZoom();e.save(),e.transform(...i),e.lineWidth=this.width/n,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:i,target:n}=JSON.parse(t),r=new e.Point(n.x,i.y);this.drawLine(r,n)}}function f(){if(!this.closeHLine)for(const t of this.horizontalLines){const{origin:i,target:n}=JSON.parse(t),r=new e.Point(i.x,n.y);this.drawLine(r,n)}}function u(t,e){const i=t.getCoords();i.push(t.getCenterPoint());const n={target:t,list:i,points:e,margin:this.margin/this.canvas.getZoom()};return{vLines:v({...n,type:"x"}),hLines:v({...n,type:"y"})}}const p=[["left","top"],["right","top"],["right","bottom"],["left","bottom"],["center","center"]];function v(t){const{target:e,list:i,points:n,margin:r,type:s}=t,a=[],c=[];let l=1/0;for(const t of i){const e=o(t,n,s);c.push(e),l>e.dis&&(l=e.dis)}if(l>r)return a;let h=!1;for(let t=0;t<i.length;t++){if(c[t].dis!=l)continue;for(const e of c[t].arr)a.push({origin:i[t],target:e});if(h)continue;h=!0;const n=c[t].arr[0][s]-i[t][s];i.forEach(t=>{t[s]+=n}),e.setXY(i[t],...p[t]),e.setCoords()}return a}function m(t){const i=new Set,n=t.canvas;if(!n)return i;const r=t instanceof e.ActiveSelection?t.getObjects():[t];return n.forEachObject(t=>{t.isOnScreen()&&t.visible&&(t.constructor!=e.Group?i.add(t):w(i,t))}),b(i,r),i}function b(t,i){for(const n of i)n.constructor==e.Group?b(t,n.getObjects()):t.delete(n)}function w(t,i){const n=i.getObjects();for(const i of n)i.visible&&(i.constructor!=e.Group?t.add(i):w(t,i))}const y=function(t){let i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"left",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"top";return async function(r){const{originX:o=i,originY:s=n}=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(i){const{colorStops:n}=i,r=null==n?void 0:n.map(t=>{let{color:i,opacity:n,offset:r}=t;if(void 0===n||1===n)return{color:i,offset:r};return{color:new e.Color(i).setAlpha(n).toRgba(),offset:r}});return await t.call(this,{...i,colorStops:r})};const{wrapWithFixedAnchor:O,wrapWithFireEvent:P}=e.controlsUtils,S=P("CROPPING",O((t,i,n,r)=>{const{target:o}=i,{width:s}=o,a=o,c=e.controlsUtils.changeObjectWidth(t,i,n,r),l=a._element.width-a.cropX;return c&&(a.width>l&&(a.width=l),a.width<1&&(a.width=1)),s!==a.width})),z=P("CROPPING",O((t,i,n,r)=>{const{target:o}=i,{height:s}=o,a=o,c=e.controlsUtils.changeObjectHeight(t,i,n,r),l=a._element.height-a.cropY;return c&&(a.height>l&&(a.height=l),a.height<1&&(a.height=1)),s!==a.height})),R=P("CROPPING",O((t,i,n,r)=>{const{target:o}=i,s=o,{width:a,cropX:c}=s,l=e.controlsUtils.changeObjectWidth(t,i,n,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})),T=P("CROPPING",O((t,i,n,r)=>{const{target:o}=i,s=o,{height:a,cropY:c}=s,l=e.controlsUtils.changeObjectHeight(t,i,n,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})),x=t=>{let{transform:i}=t;const{target:n,original:r}=i,o=n,s=new e.Point(n.left-r.left,n.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},{degreesToRadians:j}=e.util;function L(t,e,i,n,r){t.save();const{stroke:o,xSize:s,ySize:a,opName:c}=this.commonRenderProps(t,e,i,r,n),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:X}=e.controlsUtils,Y=()=>"crop",D=()=>({ml:new e.Control({x:-.5,y:0,sizeX:4,sizeY:20,cursorStyleHandler:X,actionHandler:R,getActionName:Y}),mr:new e.Control({x:.5,y:0,sizeX:4,sizeY:20,cursorStyleHandler:X,actionHandler:S,getActionName:Y}),mb:new e.Control({x:0,y:.5,sizeX:20,sizeY:4,cursorStyleHandler:X,actionHandler:z,getActionName:Y}),mt:new e.Control({x:0,y:-.5,sizeX:20,sizeY:4,cursorStyleHandler:X,actionHandler:T,getActionName:Y}),tl:new e.Control({angle:0,x:-.5,y:-.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:X,actionHandler:function(){const t=R(...arguments),e=T(...arguments);return t||e},getActionName:Y}),tr:new e.Control({angle:90,x:.5,y:-.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:X,actionHandler:function(){const t=S(...arguments),e=T(...arguments);return t||e},getActionName:Y}),bl:new e.Control({angle:270,x:-.5,y:.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:X,actionHandler:function(){const t=z(...arguments),e=R(...arguments);return t||e},getActionName:Y}),br:new e.Control({angle:180,x:.5,y:.5,sizeX:20,sizeY:4,render:L,cursorStyleHandler:X,actionHandler:function(){const t=z(...arguments),e=S(...arguments);return t||e},getActionName:Y})});t.AligningGuidelines=class{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};n(this,"canvas",void 0),n(this,"horizontalLines",new Set),n(this,"verticalLines",new Set),n(this,"cacheMap",new Map),n(this,"onlyDrawPoint",!1),n(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"]}),n(this,"xSize",2.4),n(this,"lineDash",void 0),n(this,"margin",4),n(this,"width",1),n(this,"color","rgba(255,0,0,0.9)"),n(this,"closeVLine",!1),n(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 m(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 i=null!==(e=t.aCoords)&&void 0!==e?e:t.calcACoords();return{tl:i.br,tr:i.bl,br:i.tl,bl:i.tr,mt:i.br.add(i.bl).scalarDivide(2),mr:i.bl.add(i.tl).scalarDivide(2),mb:i.tl.add(i.tr).scalarDivide(2),ml:i.tr.add(i.br).scalarDivide(2)}}(t)}getCaCheMapValue(t){const e=[t.calcTransformMatrix().toString(),t.width,t.height].join(),i=this.cacheMap.get(e);if(i)return i;const n=t.getCoords();return n.push(t.getCenterPoint()),this.cacheMap.set(e,n),n}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 i=t.target;i.setCoords();const n=String(t.transform.action).startsWith("scale");this.verticalLines.clear(),this.horizontalLines.clear();const r=this.getObjectsByTarget(i);let o=t.transform.corner;i.flipX&&(o.includes("l")?o=o.replace("l","r"):o.includes("r")&&(o=o.replace("r","l"))),i.flipY&&(o.includes("t")?o=o.replace("t","b"):o.includes("b")&&(o=o.replace("b","t")));const c=this.getPointMap(i);if(!(o in c))return;if(this.onlyDrawPoint=o.includes("m"),this.onlyDrawPoint){if(i.getTotalAngle()%90!=0)return}const l=this.getContraryMap(i),h=c[o];let d=l[o];const g="center"==t.transform.original.originX&&"center"==t.transform.original.originY;if(g){const t=i.group?h.transform(e.util.invertTransform(i.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 v={target:i,point:h,diagonalPoint:d,corner:o,list:p,isScale:n,isUniform:u,isCenter:g},m=this.onlyDrawPoint&&(o.includes("t")||o.includes("b")),b=this.onlyDrawPoint&&(o.includes("l")||o.includes("r")),w=m?[]:s.call(this,v),y=b?[]:a.call(this,v);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 i=this.getObjectsByTarget(e),n=[];for(const t of i)n.push(...this.getCaCheMapValue(t));const{vLines:r,hLines:o}=u.call(this,e,n);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 i.Region(t.upperCanvasEl);t.addOrRemove(function(t){for(var e=arguments.length,i=new Array(e>1?e-1:0),n=1;n<e;n++)i[n-1]=arguments[n];return t.removeEventListener(...i)}),e.addGesture((t=>new i.Rotate(t.upperCanvasEl,e=>{let{rotation:i,event:n}=e;t.fireEventFromPointerEvent(n,"rotate","rotate",{rotation:i})}))(t)),e.addGesture((t=>new i.Pinch(t.upperCanvasEl,e=>{let{scale:i,event:n}=e;t.fireEventFromPointerEvent(n,"pinch","pinch",{scale:i})}))(t)),e.addGesture((t=>new i.Tap(t.upperCanvasEl,e=>{let{event:i}=e;t.fireEventFromPointerEvent(i,"mouse:tripleclick","mousetripleclick",void 0),i.preventDefault()},{numTaps:3,maxRetain:400}))(t)),e.addGesture((t=>new i.Tap(t.upperCanvasEl,e=>{let{event:i}=e;t.fireEventFromPointerEvent(i,"mouse:dblclick","mousedblclick",void 0),i.preventDefault()},{numTaps:2,maxRetain:300}))(t)),t.addOrRemove(function(t){for(var e=arguments.length,i=new Array(e>1?e-1:0),n=1;n<e;n++)i[n-1]=arguments[n];return t.addEventListener(...i)},!0)},t.changeCropHeight=z,t.changeCropWidth=S,t.changeCropX=R,t.changeCropY=T,t.createImageCroppingControls=D,t.enterCropMode=function t(e){var i;let{target:n}=e;const r=n,{controls:o}=r;r.controls=D(),r.on("moving",x),r.setCoords();r.once("mousedblclick",()=>{var e;r.off("moving",x),r.controls=o,r.setCoords(),r.once("mousedblclick",t),null===(e=r.canvas)||void 0===e||e.requestRenderAll()}),null===(i=r.canvas)||void 0===i||i.requestRenderAll()},t.gradientUpdaterWrapper=C,t.installGradientUpdater=()=>{e.Gradient.fromObject=C(e.Gradient.fromObject)},t.installOriginWrapperUpdater=(t,i)=>{e.BaseFabricObject._fromObject=y(e.BaseFabricObject._fromObject,t,i),e.FabricImage.fromObject=y(e.FabricImage.fromObject,t,i),e.Group.fromObject=y(e.Group.fromObject,t,i)},t.originUpdaterWrapper=y,t.pinchEventHandler=function(t){let{scale:e,target:i,scenePoint:n}=t;i&&this.getActiveObject()===i?(i.scaleX*=e,i.scaleY*=e):this.zoomToPoint(n,this.getZoom()*e)},t.rotateEventHandler=function(t){let{rotation:i,target:n}=t;n&&this.getActiveObject()===n&&n.rotate(n.angle+e.util.radiansToDegrees(i))}}); //# sourceMappingURL=fabric-extensions.min.js.map