UNPKG

fabric-texture

Version:

This JavaScript library enables fast and efficient image distortion transformations using Canvas 2D.

3 lines (2 loc) 10.8 kB
import{fabric as t}from"fabric";import{B as e,d as o,T as r,S as n}from"./base.class-G1Hpx_TY.js";import{c as s,a as i}from"./calc-fabric-relative-coord--qdng7YE.js";var l;!function(t){t.TOP_LEFT="tl",t.TOP_RIGHT="tr",t.BOTTOM_LEFT="bl",t.BOTTOM_RIGHT="br"}(l||(l={}));class a extends e{constructor(t=r,e=n,s={}){super(t,e),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=o(s,this.options)}static createDefaultControl(e){return new t.Circle({radius:7,fill:e,stroke:"#ffffff",paintFirst:"fill",strokeWidth:2,originX:"center",originY:"center",hasControls:!1,hasBorders:!1})}static createDefaultCurveControl(){return new t.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.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:l}=t.mesh[r][o];for(let t=0;t<l.length;t++)for(let e=0;e<i.length;e++){const o=i[e].get(t/(l.length-1)),r=l[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 a.execute(t)}dirtyRender(e){var o;const r=e.canvas;if(!r)return;const n=null===(o=e.texture)||void 0===o?void 0:o.areaBoundCurves;if(!n)return;const c=[],u=new Map;this._insertControlObject=this._styleSetters.insertControl(a.createDefaultInsertControl(this.themeColor));const f=()=>{var t,e;r.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),r.renderOnAddRemove=!0,r.requestRenderAll()};n.forEach(((o,n)=>{o.forEach(((o,s)=>{const i=o;Object.entries(i).forEach((([o])=>{const f=i[o],d=e.curvePathMap.get(f),h=f.points.map((e=>t.util.transformPoint(new t.Point(e.x-d.pathOffset.x,e.y-d.pathOffset.y),d.calcOwnMatrix())));h.forEach(((e,i)=>{if(0===i||3===i)return;const d=[0,0,3,3][i],p=h[d],v={top:[l.TOP_LEFT,l.TOP_RIGHT],bottom:[l.BOTTOM_LEFT,l.BOTTOM_RIGHT],right:[l.TOP_RIGHT,l.BOTTOM_RIGHT],left:[l.TOP_LEFT,l.BOTTOM_LEFT]}[o][Math.sign(d)],b=n+(v.startsWith("b")?1:0),C=s+(v.endsWith("r")?1:0),m=`${b}-${C}`;let x=this._positionControlMap.get(m);if(!x){const t=this._styleSetters.control(a.createDefaultControl(this.themeColor));t.set({left:p.x,top:p.y}),r.add(t),c.push(t),x={majorControl:t,curve:f,rowIndex:n,colIndex:s,splitDotRowIndex:b,splitDotColIndex:C,vertexIndex:d,vertexType:v,subControls:[]}}if(!x.subControls.find((t=>t.attach[0]===f&&t.attach[1]===d))){const o=this._styleSetters.curveControl(a.createDefaultCurveControl());o.set({left:e.x,top:e.y});const n=new t.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(n),r.add(n,o),c.push(n,o),x.subControls.push({attach:[f,d],object:o,line:n,index:i})}this._positionControlMap.set(m,x),u.set(x.majorControl,m)}))}))}))})),f(),this._positionControlMap.forEach((t=>{const{majorControl:o,subControls:n}=t;n.forEach((({attach:[t],object:r,line:n,index:i})=>{r.on("moving",(()=>{const l=e.curvePathMap.get(t),a=s(r,l),c=t.points[i],u=a.x-c.x,d=a.y-c.y;r.set({angle:90+180*Math.atan2(r.top-o.top,r.left-o.left)/Math.PI}).setCoords(),t.points[i].x+=u,t.points[i].y+=d,n.set({x1:r.left,y1:r.top,x2:o.left,y2:o.top}),e.requestRender(!1,f,{withoutRecord:!0})}))})),o.on("selected",(()=>{r.getActiveObject()===o&&n.forEach((({object:t,line:e})=>{var r;t.set("visible",!0),e.set("visible",!0),null===(r=o.canvas)||void 0===r||r.requestRenderAll()}))})),o.on("deselected",(()=>{n.forEach((({object:t,line:e})=>{var r;t.set("visible",!1),e.set("visible",!1),null===(r=o.canvas)||void 0===r||r.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:d,enableGridSplit:h}=this.options,p=[[d,()=>{let t=!1;const e=e=>{t=e.shiftKey},o=e=>{t=e.shiftKey},n=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 r.on("object:moving",n),window.addEventListener("keydown",e),window.addEventListener("keyup",o),()=>{r.off("object:moving",n),window.removeEventListener("keydown",e),window.removeEventListener("keyup",o)}}],[!0,()=>{const o=()=>{const o=r.getActiveObjects(),n=new Set;for(const t of o){const e=u.get(t);if(!e)continue;this._positionControlMap.get(e)&&n.add(t)}Array.from(this._positionControlMap.values()).forEach((o=>{if(!n.has(o.majorControl))return;const{curve:r,majorControl:i,rowIndex:l,colIndex:a,vertexType:c,vertexIndex:u,subControls:f}=o,d=e.curvePathMap.get(r),h=t.util.qrDecompose(i.calcTransformMatrix(!1)),p={left:h.translateX,top:h.translateY},v=s(p,d),b=r.points[u],C=t.util.transformPoint(new t.Point(b.x-d.pathOffset.x,b.y-d.pathOffset.y),d.calcOwnMatrix()),m=v.x-b.x,x=v.y-b.y,y=p.left-C.x,g=p.top-C.y;e.texture.setVertexCoord(l,a,c,v,!1),f.forEach((({attach:t,object:e,line:o,index:r})=>{t[0].points[r].x+=m,t[0].points[r].y+=x,e.set({left:e.left+y,top:e.top+g}).setCoords(),o.set({x1:e.left,y1:e.top,x2:p.left,y2:p.top})}))})),n.size&&(e.requestRender(!1,f,{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 r.on("object:moving",o),r.on("object:modified",n),()=>{r.off("object:moving",o),r.off("object:modified",n)}}],[!0,()=>{const t=()=>{var t;const e=r.getActiveObjects(),o=new Set;for(const t of e){const e=u.get(t);if(!e)continue;this._positionControlMap.get(e)&&o.add(t)}Array.from(u.keys()).forEach((t=>{t.set({opacity:1,fill:o.has(t)?this.subThemeColor:this.themeColor})})),o.size&&(null===(t=r.getActiveObject())||void 0===t||t.set({perPixelTargetFind:!0,hasControls:!1,hasBorders:!1}),o.clear()),r.requestRenderAll()};return r.on("selection:created",t),r.on("selection:updated",t),r.on("selection:cleared",t),()=>{r.off("selection:created",t),r.off("selection:updated",t),r.off("selection:cleared",t)}}],[h,()=>{let o=null,n=null,l=null;const a=a=>{if(1!==a.e.buttons)return;const u=performance.now(),d=a.target===this._insertControlObject,h=a.target===e.textureObject;if(a.pointer&&this._insertControlObject&&(d?r.selection=!1:(o=null,n=null,l=null,r.remove(this._insertControlObject)),h)){const c=i(r,a.pointer),u=s({left:c.x,top:c.y},e.paths[0]);if(l=e.texture.containsPoint(u),l){const{before:e,after:r,clickPart:s}=l,i=((t,e)=>{const[o,r,n]=t,[s,i,l]=e,a=.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),[l,a,c,u]=e.map(Number),[f,d,h,p]=o.map(Number),v=s-n*c/a,b=c-a*h/d,C=u-a*p/d,m=l-a*f/d,x=(v/b*C-(i-n*u/a))/(v/b*m-(r-n*l/a)),y=(C-m*x)/b;return{x:x,y:(i-r*x-s*y)/n,z:y}},u=[s.x+a,s.y+a,1,o.x+a],f=[i.x+a,i.y+a,1,r.x+a],d=[l.x+a,l.y+a,1,n.x+a],h=c(u,f,d);u[3]=o.y+a,f[3]=r.y+a,d[3]=n.y+a;const p=c(u,f,d),v=h.x,b=h.y,C=h.z;return[v,p.x,b,p.y,C,p.z]})([[r[0],r[1],r[3]],[r[2],r[1],r[3]]][s],[[e[0],e[1],e[3]],[e[2],e[1],e[3]]][s]);o=c,n=t.util.transformPoint(u,t.util.invertTransform(i))}}const p=o=>{var n;if(!o.pointer)return;if(r.selection)return;if(!this._insertControlObject)return;if(!d)return;const s=e.texture;if(!s)return;const l=i(r,o.pointer),a={x:l.x-this._insertControlObject.left,y:l.y-this._insertControlObject.top},u=new WeakSet([]);s.getAreaBoundCoords(((o,r,n,s)=>{if(u.has(s))return s.points;u.add(s);const i=e.curvePathMap.get(s),l=t.util.transformPoint(new t.Point(a.x,a.y),t.util.invertTransform(i.calcOwnMatrix()),!0);return s.points.map((t=>(t.x+=l.x,t.y+=l.y,t)))})),[this._insertControlObject,e.textureObject,...null!==(n=e.paths)&&void 0!==n?n:[],...c].forEach((t=>{t.set({left:t.left+a.x,top:t.top+a.y}).setCoords()})),e.requestRender(!1,f,{withoutRecord:!0})},v=t=>{var s;performance.now()-u<200&&t.pointer&&this._insertControlObject&&(d?(r.remove(this._insertControlObject),null===(s=e.texture)||void 0===s||s.addSplitPoint(l.rowIndex,l.colIndex,n),e.render(!0)):o&&(this._insertControlObject.set({left:o.x,top:o.y}).setCoords(),r.add(this._insertControlObject),r.requestRenderAll())),d&&e.record(),r.selection=!0,r.off("mouse:up",v),r.off("mouse:move",p)};r.on("mouse:move",p),r.on("mouse:up",v)};return r.on("mouse:down",a),()=>{r.off("mouse:down",a)}}],[h,()=>{const t=t=>{var o;const r=[];for(const e of t){const t=u.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=r.getActiveObjects();if(!e)return;t(e)}};return window.addEventListener("keydown",o),()=>{window.removeEventListener("keydown",o)}}]],v=p.map((([t,e])=>t&&e()));return()=>{v.forEach((t=>{"function"==typeof t&&t()})),this._insertControlObject&&r.remove(this._insertControlObject),r.remove(...c),this._positionControlMap.clear(),u.clear()}}}export{l as VertexType,a as default}; //# sourceMappingURL=warp.esm.js.map