fabric-texture
Version:
This JavaScript library enables fast and efficient image distortion transformations using Canvas 2D.
3 lines (2 loc) • 11.2 kB
JavaScript
;Object.defineProperty(exports,"__esModule",{value:!0});var t=require("fabric"),e=require("./base.class-7YPThjJT.js"),o=require("./calc-fabric-relative-coord-57kWtQps.js");var r;exports.VertexType=void 0,(r=exports.VertexType||(exports.VertexType={})).TOP_LEFT="tl",r.TOP_RIGHT="tr",r.BOTTOM_LEFT="bl",r.BOTTOM_RIGHT="br";class n extends e.BaseMode{constructor(t=e.THEME_COLOR,o=e.SUB_THEME_COLOR,r={}){super(t,o),this.name="Warp",this.options={enableShiftConstraint:!0,enableGridSplit:!0},this._styleSetters={texture:()=>{},path:()=>{},control:t=>t,curveControl:t=>t,insertControl:t=>t,line:t=>{}},this._positionControlMap=new Map([]),this._insertControlObject=null,this.options=e.defaults(r,this.options)}static createDefaultControl(e){return new t.fabric.Circle({radius:7,fill:e,stroke:"#ffffff",paintFirst:"fill",strokeWidth:2,originX:"center",originY:"center",hasControls:!1,hasBorders:!1})}static createDefaultCurveControl(){return new t.fabric.Rect({width:6,height:6,rx:2,ry:2,fill:"rgba(255, 255, 255, 1)",stroke:"rgba(200, 200, 200, 0.8)",strokeWidth:1,strokeUniform:!0,visible:!1,hasControls:!1,hasBorders:!1,originX:"center",originY:"center"})}static createDefaultInsertControl(e){return new t.fabric.Circle({radius:5,fill:"rgba(255, 255, 255, 0.2)",stroke:e,strokeWidth:2,originX:"center",originY:"center",selectable:!1,hasControls:!1,hasBorders:!1})}static execute(t){if(!t.mesh)return[];const e=[];return t.areaBoundCurves.forEach(((o,r)=>{const n=[];o.forEach(((e,o)=>{const s=[],{vertical:i,horizontal:a}=t.mesh[r][o];for(let t=0;t<a.length;t++)for(let e=0;e<i.length;e++){const o=i[e].get(t/(a.length-1)),r=a[t].get(e/(i.length-1));s.push({x:(o.x+r.x)/2,y:(o.y+r.y)/2})}n.push(s)})),e.push(n)})),e}get controlObjects(){return Array.from(this._positionControlMap.values()).map((t=>t.majorControl))}get subControlObjects(){return Array.from(this._positionControlMap.values()).map((t=>t.subControls.map((t=>t.object)))).flat(1)}get insertControlObject(){return this._insertControlObject}get lineObjects(){return Array.from(this._positionControlMap.values()).map((t=>t.subControls.map((t=>t.line)))).flat(1)}execute(t){return n.execute(t)}dirtyRender(e){var r;const s=e.canvas;if(!s)return;const i=null===(r=e.texture)||void 0===r?void 0:r.areaBoundCurves;if(!i)return;const a=[],l=new Map;this._insertControlObject=this._styleSetters.insertControl(n.createDefaultInsertControl(this.themeColor));const c=()=>{var t,e;s.renderOnAddRemove=!1,this._positionControlMap.forEach((t=>{t.subControls.forEach((t=>{var e;return null===(e=t.line.canvas)||void 0===e?void 0:e.bringToFront(t.line)}))})),this._positionControlMap.forEach((t=>{t.subControls.forEach((t=>{var e;return null===(e=t.object.canvas)||void 0===e?void 0:e.bringToFront(t.object)}))})),this._positionControlMap.forEach((t=>{var e;null===(e=t.majorControl.canvas)||void 0===e||e.bringToFront(t.majorControl)})),null===(e=null===(t=this._insertControlObject)||void 0===t?void 0:t.canvas)||void 0===e||e.bringToFront(this._insertControlObject),s.renderOnAddRemove=!0,s.requestRenderAll()};i.forEach(((o,r)=>{o.forEach(((o,i)=>{const c=o;Object.entries(c).forEach((([o])=>{const f=c[o],u=e.curvePathMap.get(f),d=f.points.map((e=>t.fabric.util.transformPoint(new t.fabric.Point(e.x-u.pathOffset.x,e.y-u.pathOffset.y),u.calcOwnMatrix())));d.forEach(((e,c)=>{if(0===c||3===c)return;const u=[0,0,3,3][c],p=d[u],h={top:[exports.VertexType.TOP_LEFT,exports.VertexType.TOP_RIGHT],bottom:[exports.VertexType.BOTTOM_LEFT,exports.VertexType.BOTTOM_RIGHT],right:[exports.VertexType.TOP_RIGHT,exports.VertexType.BOTTOM_RIGHT],left:[exports.VertexType.TOP_LEFT,exports.VertexType.BOTTOM_LEFT]}[o][Math.sign(u)],b=r+(h.startsWith("b")?1:0),v=i+(h.endsWith("r")?1:0),x=`${b}-${v}`;let C=this._positionControlMap.get(x);if(!C){const t=this._styleSetters.control(n.createDefaultControl(this.themeColor));t.set({left:p.x,top:p.y}),s.add(t),a.push(t),C={majorControl:t,curve:f,rowIndex:r,colIndex:i,splitDotRowIndex:b,splitDotColIndex:v,vertexIndex:u,vertexType:h,subControls:[]}}if(!C.subControls.find((t=>t.attach[0]===f&&t.attach[1]===u))){const o=this._styleSetters.curveControl(n.createDefaultCurveControl());o.set({left:e.x,top:e.y});const r=new t.fabric.Line([e.x,e.y,p.x,p.y],{stroke:"rgba(200, 200, 200, 0.8)",strokeWidth:2,strokeUniform:!0,visible:!1,evented:!1,selectable:!1,originX:"center",originY:"center"});this._styleSetters.line(r),s.add(r,o),a.push(r,o),C.subControls.push({attach:[f,u],object:o,line:r,index:c})}this._positionControlMap.set(x,C),l.set(C.majorControl,x)}))}))}))})),c(),this._positionControlMap.forEach((t=>{const{majorControl:r,subControls:n}=t;n.forEach((({attach:[t],object:n,line:s,index:i})=>{n.on("moving",(()=>{const a=e.curvePathMap.get(t),l=o.calcFabricRelativeCoord(n,a),f=t.points[i],u=l.x-f.x,d=l.y-f.y;n.set({angle:90+180*Math.atan2(n.top-r.top,n.left-r.left)/Math.PI}).setCoords(),t.points[i].x+=u,t.points[i].y+=d,s.set({x1:n.left,y1:n.top,x2:r.left,y2:r.top}),e.requestRender(!1,c,{withoutRecord:!0})}))})),r.on("selected",(()=>{s.getActiveObject()===r&&n.forEach((({object:t,line:e})=>{var o;t.set("visible",!0),e.set("visible",!0),null===(o=r.canvas)||void 0===o||o.requestRenderAll()}))})),r.on("deselected",(()=>{n.forEach((({object:t,line:e})=>{var o;t.set("visible",!1),e.set("visible",!1),null===(o=r.canvas)||void 0===o||o.requestRenderAll()}))})),n.forEach((({object:t})=>{t.on("selected",(()=>{n.forEach((({object:t,line:e})=>{var o;t.set("visible",!0),e.set("visible",!0),null===(o=t.canvas)||void 0===o||o.requestRenderAll()}))})),t.on("deselected",(()=>{n.forEach((({object:t,line:e})=>{var o;t.set("visible",!1),e.set("visible",!1),null===(o=t.canvas)||void 0===o||o.requestRenderAll()}))}))}))}));const{enableShiftConstraint:f,enableGridSplit:u}=this.options,d=[[f,()=>{let t=!1;const e=e=>{t=e.shiftKey},o=e=>{t=e.shiftKey},r=e=>{if(t&&e.target&&e.transform){const{left:t=0,top:o=0}=e.target,{left:r,top:n}=e.transform.original;Math.abs(t-r)>Math.abs(o-n)?e.target.set({top:n}).setCoords():e.target.set({left:r}).setCoords()}};return s.on("object:moving",r),window.addEventListener("keydown",e),window.addEventListener("keyup",o),()=>{s.off("object:moving",r),window.removeEventListener("keydown",e),window.removeEventListener("keyup",o)}}],[!0,()=>{const r=()=>{const r=s.getActiveObjects(),n=new Set;for(const t of r){const e=l.get(t);if(!e)continue;this._positionControlMap.get(e)&&n.add(t)}Array.from(this._positionControlMap.values()).forEach((r=>{if(!n.has(r.majorControl))return;const{curve:s,majorControl:i,rowIndex:a,colIndex:l,vertexType:c,vertexIndex:f,subControls:u}=r,d=e.curvePathMap.get(s),p=t.fabric.util.qrDecompose(i.calcTransformMatrix(!1)),h={left:p.translateX,top:p.translateY},b=o.calcFabricRelativeCoord(h,d),v=s.points[f],x=t.fabric.util.transformPoint(new t.fabric.Point(v.x-d.pathOffset.x,v.y-d.pathOffset.y),d.calcOwnMatrix()),C=b.x-v.x,y=b.y-v.y,m=h.left-x.x,O=h.top-x.y;e.texture.setVertexCoord(a,l,c,b,!1),u.forEach((({attach:t,object:e,line:o,index:r})=>{t[0].points[r].x+=C,t[0].points[r].y+=y,e.set({left:e.left+m,top:e.top+O}).setCoords(),o.set({x1:e.left,y1:e.top,x2:h.left,y2:h.top})}))})),n.size&&(e.requestRender(!1,c,{withoutRecord:!0}),n.clear())},n=t=>{const o=t.target;o&&"drag"===t.action&&("activeSelection"===o.type&&o.getObjects().some(this.controlObjects.includes.bind(this.controlObjects))||this.controlObjects.includes(o)||this.subControlObjects.includes(o))&&e.record()};return s.on("object:moving",r),s.on("object:modified",n),()=>{s.off("object:moving",r),s.off("object:modified",n)}}],[!0,()=>{const t=()=>{var t;const e=s.getActiveObjects(),o=new Set;for(const t of e){const e=l.get(t);if(!e)continue;this._positionControlMap.get(e)&&o.add(t)}Array.from(l.keys()).forEach((t=>{t.set({opacity:1,fill:o.has(t)?this.subThemeColor:this.themeColor})})),o.size&&(null===(t=s.getActiveObject())||void 0===t||t.set({perPixelTargetFind:!0,hasControls:!1,hasBorders:!1}),o.clear()),s.requestRenderAll()};return s.on("selection:created",t),s.on("selection:updated",t),s.on("selection:cleared",t),()=>{s.off("selection:created",t),s.off("selection:updated",t),s.off("selection:cleared",t)}}],[u,()=>{let r=null,n=null,i=null;const l=l=>{if(1!==l.e.buttons)return;const f=performance.now(),u=l.target===this._insertControlObject,d=l.target===e.textureObject;if(l.pointer&&this._insertControlObject&&(u?s.selection=!1:(r=null,n=null,i=null,s.remove(this._insertControlObject)),d)){const a=o.calcFabricCanvasCoord(s,l.pointer),c=o.calcFabricRelativeCoord({left:a.x,top:a.y},e.paths[0]);if(i=e.texture.containsPoint(c),i){const{before:e,after:o,clickPart:s}=i,l=((t,e)=>{const[o,r,n]=t,[s,i,a]=e,l=.1/Math.abs([...t,...e].reduce(((t,e)=>Math.min(t,e.x,e.y)),-1)),c=(t,e,o)=>{const[r,n,s,i]=t.map(Number),[a,l,c,f]=e.map(Number),[u,d,p,h]=o.map(Number),b=s-n*c/l,v=c-l*p/d,x=f-l*h/d,C=a-l*u/d,y=(b/v*x-(i-n*f/l))/(b/v*C-(r-n*a/l)),m=(x-C*y)/v;return{x:y,y:(i-r*y-s*m)/n,z:m}},f=[s.x+l,s.y+l,1,o.x+l],u=[i.x+l,i.y+l,1,r.x+l],d=[a.x+l,a.y+l,1,n.x+l],p=c(f,u,d);f[3]=o.y+l,u[3]=r.y+l,d[3]=n.y+l;const h=c(f,u,d),b=p.x,v=p.y,x=p.z;return[b,h.x,v,h.y,x,h.z]})([[o[0],o[1],o[3]],[o[2],o[1],o[3]]][s],[[e[0],e[1],e[3]],[e[2],e[1],e[3]]][s]);r=a,n=t.fabric.util.transformPoint(c,t.fabric.util.invertTransform(l))}}const p=r=>{var n;if(!r.pointer)return;if(s.selection)return;if(!this._insertControlObject)return;if(!u)return;const i=e.texture;if(!i)return;const l=o.calcFabricCanvasCoord(s,r.pointer),f={x:l.x-this._insertControlObject.left,y:l.y-this._insertControlObject.top},d=new WeakSet([]);i.getAreaBoundCoords(((o,r,n,s)=>{if(d.has(s))return s.points;d.add(s);const i=e.curvePathMap.get(s),a=t.fabric.util.transformPoint(new t.fabric.Point(f.x,f.y),t.fabric.util.invertTransform(i.calcOwnMatrix()),!0);return s.points.map((t=>(t.x+=a.x,t.y+=a.y,t)))})),[this._insertControlObject,e.textureObject,...null!==(n=e.paths)&&void 0!==n?n:[],...a].forEach((t=>{t.set({left:t.left+f.x,top:t.top+f.y}).setCoords()})),e.requestRender(!1,c,{withoutRecord:!0})},h=t=>{var o;performance.now()-f<200&&t.pointer&&this._insertControlObject&&(u?(s.remove(this._insertControlObject),null===(o=e.texture)||void 0===o||o.addSplitPoint(i.rowIndex,i.colIndex,n),e.render(!0)):r&&(this._insertControlObject.set({left:r.x,top:r.y}).setCoords(),s.add(this._insertControlObject),s.requestRenderAll())),u&&e.record(),s.selection=!0,s.off("mouse:up",h),s.off("mouse:move",p)};s.on("mouse:move",p),s.on("mouse:up",h)};return s.on("mouse:down",l),()=>{s.off("mouse:down",l)}}],[u,()=>{const t=t=>{var o;const r=[];for(const e of t){const t=l.get(e);if(!t)continue;const o=this._positionControlMap.get(t);o&&r.push(o)}r&&(null===(o=e.texture)||void 0===o||o.removeSplitPoints(r.map((t=>[t.splitDotRowIndex,t.splitDotColIndex]))),e.render(!0))},o=e=>{if(["Delete","Backspace"].includes(e.key)){const e=s.getActiveObjects();if(!e)return;t(e)}};return window.addEventListener("keydown",o),()=>{window.removeEventListener("keydown",o)}}]],p=d.map((([t,e])=>t&&e()));return()=>{p.forEach((t=>{"function"==typeof t&&t()})),this._insertControlObject&&s.remove(this._insertControlObject),s.remove(...a),this._positionControlMap.clear(),l.clear()}}}exports.default=n;
//# sourceMappingURL=warp.js.map