UNPKG

fabric-warpvas

Version:

This JavaScript library helps you efficiently build image warping tools on Fabric.js

3 lines (2 loc) 10.4 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("fabric"),e=require("./base.class-QKOkESKk.js"),o=require("./register-limit-move-event-R3khX-xX.js");const{calcMatrix:r}=e.I;var n;exports.VertexType=void 0,(n=exports.VertexType||(exports.VertexType={})).TOP_LEFT="tl",n.TOP_RIGHT="tr",n.BOTTOM_LEFT="bl",n.BOTTOM_RIGHT="br";class s extends e.BaseMode{constructor(t={}){super(t),this.name="warp",this.options={themeColor:e.THEME_COLOR,subThemeColor:e.SUB_THEME_COLOR,enableConstraintKey:"None",enableGridSplit:!0},this._styleSetters={image:()=>{},path:()=>{},control:t=>t,curveControl:t=>t,insertControl:t=>t,line:t=>{}},this._positionControlMap=new Map([]),this._insertControlObject=null,this.options=e.defaults(t,this.options)}static execute(t){if(!t.regionCurves)return[];const e=[];return t.regionBoundaryCurves.forEach(((o,r)=>{const n=[];o.forEach(((e,o)=>{const s=[],{vertical:i,horizontal:l}=t.regionCurves[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 s.execute(t)}dirtyRender(e){var n;const s=e.canvas;if(!s)return;const i=null===(n=e.warpvas)||void 0===n?void 0:n.regionBoundaryCurves;if(!i)return;const l=[],a=new Map;this._insertControlObject=this._styleSetters.insertControl(this._createDefaultInsertControl(this.options.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,n)=>{const i=o;Object.entries(i).forEach((([o])=>{const c=i[o],p=e.curvePathMap.get(c),f=c.points.map((e=>t.fabric.util.transformPoint(new t.fabric.Point(e.x-p.pathOffset.x,e.y-p.pathOffset.y),p.calcOwnMatrix())));f.forEach(((e,i)=>{if(0===i||3===i)return;const p=[0,0,3,3][i],u=f[p],d={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(p)],h=r+(d.startsWith("b")?1:0),v=n+(d.endsWith("r")?1:0),b=`${h}-${v}`;let C=this._positionControlMap.get(b);if(!C){const t=this._styleSetters.control(this._createDefaultControl(this.options.themeColor));t.set({left:u.x,top:u.y}),s.add(t),l.push(t),C={majorControl:t,curve:c,rowIndex:r,colIndex:n,splitDotRowIndex:h,splitDotColIndex:v,vertexIndex:p,vertexType:d,subControls:[]}}if(!C.subControls.find((t=>t.attach[0]===c&&t.attach[1]===p))){const o=this._styleSetters.curveControl(this._createDefaultCurveControl());o.set({left:e.x,top:e.y});const r=new t.fabric.Line([e.x,e.y,u.x,u.y],{stroke:"rgba(200, 200, 200, 0.8)",strokeWidth:1,strokeUniform:!0,visible:!1,evented:!1,selectable:!1,originX:"center",originY:"center"});this._styleSetters.line(r),s.add(r,o),l.push(r,o),C.subControls.push({attach:[c,p],object:o,line:r,index:i})}this._positionControlMap.set(b,C),a.set(C.majorControl,b)}))}))}))})),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 l=e.curvePathMap.get(t),a=o.calcFabricRelativeCoord(n,l),p=t.points[i],f=a.x-p.x,u=a.y-p.y;n.set({angle:90+180*Math.atan2(n.top-r.top,n.left-r.left)/Math.PI}).setCoords(),t.points[i].x+=f,t.points[i].y+=u,s.set({x1:n.left,y1:n.top,x2:r.left,y2:r.top}),e.requestRender(!1,c,{skipHistoryRecording:!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{enableConstraintKey:p,enableGridSplit:f}=this.options,u=[["NONE"!==p.toUpperCase(),o.registerLimitMoveEvent(s,p)],[!0,()=>{const r=()=>{const r=s.getActiveObjects(),n=new Set;for(const t of r){const e=a.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:l,colIndex:a,vertexType:c,vertexIndex:p,subControls:f}=r,u=e.curvePathMap.get(s),d=t.fabric.util.qrDecompose(i.calcTransformMatrix(!1)),h={left:d.translateX,top:d.translateY},v=o.calcFabricRelativeCoord(h,u),b=s.points[p],C=t.fabric.util.transformPoint(new t.fabric.Point(b.x-u.pathOffset.x,b.y-u.pathOffset.y),u.calcOwnMatrix()),x=v.x-b.x,y=v.y-b.y,g=h.left-C.x,m=h.top-C.y;e.warpvas.updateVertexCoord(l,a,c,v,!1),f.forEach((({attach:t,object:e,line:o,index:r})=>{t[0].points[r].x+=x,t[0].points[r].y+=y,e.set({left:e.left+g,top:e.top+m}).setCoords(),o.set({x1:e.left,y1:e.top,x2:h.left,y2:h.top})}))})),n.size&&(e.requestRender(!1,c,{skipHistoryRecording:!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=a.get(t);if(!e)continue;this._positionControlMap.get(e)&&o.add(t)}Array.from(a.keys()).forEach((t=>{t.set({opacity:1,fill:o.has(t)?this.options.subThemeColor:this.options.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)}}],[f,()=>{let n=null,i=null,a=null;const p=p=>{if(1!==p.e.buttons)return;const f=performance.now(),u=p.target===this._insertControlObject,d=p.target===e.warpvasObject;if(p.pointer&&this._insertControlObject&&(u?s.selection=!1:(n=null,i=null,a=null,s.remove(this._insertControlObject)),d)){const l=o.calcFabricCanvasCoord(s,p.pointer),c=o.calcFabricRelativeCoord({left:l.x,top:l.y},e.paths[0]);if(a=e.warpvas.getHitInfo(c),a){const{before:e,after:o,clickPart:s}=a,p=r([[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]);n=l,i=t.fabric.util.transformPoint(c,t.fabric.util.invertTransform(p))}}const h=r=>{var n;if(!r.pointer)return;if(s.selection)return;if(!this._insertControlObject)return;if(!u)return;const i=e.warpvas;if(!i)return;const a=o.calcFabricCanvasCoord(s,r.pointer),p={x:a.x-this._insertControlObject.left,y:a.y-this._insertControlObject.top},f=new WeakSet([]);i.forEachRegionBoundCoords(((o,r,n,s)=>{if(f.has(s))return s.points;f.add(s);const i=e.curvePathMap.get(s),l=t.fabric.util.transformPoint(new t.fabric.Point(p.x,p.y),t.fabric.util.invertTransform(i.calcOwnMatrix()),!0);return s.points.map((t=>(t.x+=l.x,t.y+=l.y,t)))})),[this._insertControlObject,e.warpvasObject,...null!==(n=e.paths)&&void 0!==n?n:[],...l].forEach((t=>{t.set({left:t.left+p.x,top:t.top+p.y}).setCoords()})),e.requestRender(!1,c,{skipHistoryRecording:!0})},v=t=>{var o;performance.now()-f<200&&t.pointer&&this._insertControlObject&&(u?(s.remove(this._insertControlObject),null===(o=e.warpvas)||void 0===o||o.splitRegionByPoint(a.rowIndex,a.colIndex,i),e.render(!0)):n&&(this._insertControlObject.set({left:n.x,top:n.y}).setCoords(),s.add(this._insertControlObject),s.requestRenderAll())),u&&e.record(),s.selection=!0,s.off("mouse:up",v),s.off("mouse:move",h)};s.on("mouse:move",h),s.on("mouse:up",v)};return s.on("mouse:down",p),()=>{s.off("mouse:down",p)}}],[f,()=>{const t=t=>{var o;const r=[];for(const e of t){const t=a.get(e);if(!t)continue;const o=this._positionControlMap.get(t);o&&r.push(o)}r&&(null===(o=e.warpvas)||void 0===o||o.removeRegion(...r.map((t=>({row:t.splitDotRowIndex,column: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)}}]],d=u.map((([t,e])=>t&&e()));return()=>{d.forEach((t=>{"function"==typeof t&&t()})),this._insertControlObject&&s.remove(this._insertControlObject),s.remove(...l),this._positionControlMap.clear(),a.clear()}}_createDefaultControl(e){return new t.fabric.Circle({radius:4,fill:e,stroke:"#ffffff",paintFirst:"fill",strokeWidth:1,originX:"center",originY:"center",hasControls:!1,hasBorders:!1})}_createDefaultCurveControl(){return new t.fabric.Rect({width:6,height:6,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"})}_createDefaultInsertControl(e){return new t.fabric.Circle({radius:4,fill:"rgba(255, 255, 255, 0.2)",stroke:e,strokeWidth:1,originX:"center",originY:"center",selectable:!1,hasControls:!1,hasBorders:!1})}}exports.default=s; //# sourceMappingURL=warp.js.map