写这篇文章的时候我就要说一下了,这个遮罩和裁剪耗费了我真的是九牛二虎之力react
裁剪的插件不少,不管你用原生JS,JQuery, Vue仍是React.总能找到一款裁剪插件。今天我要说的是本身写一个截图功能,直接就在操做的画布中操做须要裁剪的图片,而不是跳一个新页面裁剪后再挪过来。Fabricjs 提供了不少方式的裁剪,最多见的是Object属性的上的clipTo,然而有弊端.canvas
好比google一下比较好的一个demo: http://jsfiddle.net/hellomaya/kNEaX/1/svg
这个时候发现官方demo有个其余方式的遮罩。 http://fabricjs.com/patterns fabric.Pattern 这个捏,文档写的却是挺含含糊糊,网上的例子也是不多,不过功能是很强大,不管字体,形状,图片都通通能够给你遮罩上去。可是离咱们最后要实现的功能仍是有点距离post
首先理清一下思路,字体
是否是我直接能够贴代码了,里面主要涉及了如何移动,放大缩小的逻辑。吼吼。。。google
首先是触发裁剪遮罩。这里只是随意定义了一个react 矩形的遮罩形状,后面你能够本身自定义。url
clipImage(state) { let activeObject = state.canvas.getActiveObject(); state.isClipping = true if (activeObject.type === 'image') { let clipBox = new fabric.Rect({ left: activeObject.left, top: activeObject.top, width: activeObject.width, height: activeObject.height, stroke: '#F5A623', strokeWidth: 1, fill: 'rgba(255, 255, 255, 0)', objectCaching: false, scaleX: activeObject.scaleX, scaleY: activeObject.scaleY, selectionBackgroundColor: 'rgba(255, 255, 255, 0)', padding: 0, angle: activeObject.angle }); state.clipBox = clipBox state.clipActiveObj = activeObject; // 区分是svg的img仍是普通img let url = activeObject.src ? activeObject.src : activeObject['xlink:href'] fabric.util.loadImage(url, function(img) { clipBox.fill = new fabric.Pattern({ source: img, repeat: 'no-repeat', offsetX: 0, offsetY: 0, }); state.canvas.add(clipBox); activeObject.set({ selectable: false, hoverCursor: 'default', evented: false, hasControls: false, perPixelTargetFind: false, }) activeObject.clone(function (clonedObj) { state.canvas.discardActiveObject(); clonedObj.set({ left: clonedObj.left, top: clonedObj.top, evented: false, opacity: 0.8 }); clipBox.clipClone = clonedObj; state.canvas.add(clonedObj); }); activeObject.visible = false; state.canvas.renderAll(); state.clipBox.on({ 'moving': () => { if (!state.isClipping) { clipBox.clipClone.left = clipBox.left - state.clipLeft clipBox.clipClone.top = clipBox.top - state.clipTop state.canvas.renderAll() return } let left =clipBox.left - clipBox.clipClone.left; let top = clipBox.top - clipBox.clipClone.top; state.clipLeft = left state.clipTop = top clipBox.fill.offsetX = -left / clipBox.clipClone.scaleX clipBox.fill.offsetY = -top / clipBox.clipClone.scaleY state.canvas.renderAll(); }, 'scaling': () => { if (!state.isClipping) { clipBox.clipClone.left = clipBox.left - state.clipLeft clipBox.clipClone.top = clipBox.top - state.clipTop clipBox.clipClone.scaleX = clipBox.scaleX clipBox.clipClone.scaleY = clipBox.scaleY state.canvas.renderAll() return } // let _width = clipBox.width / clipBox. let _width = clipBox.width * clipBox.scaleX / clipBox.clipClone.scaleX let _height = clipBox.height * clipBox.scaleY / clipBox.clipClone.scaleY let left =clipBox.left - clipBox.clipClone.left; let top = clipBox.top - clipBox.clipClone.top; state.clipLeft = clipBox.left state.clipTop = clipBox.top clipBox.fill.offsetX = -left / clipBox.clipClone.scaleX clipBox.fill.offsetY = -top / clipBox.clipClone.scaleX clipBox.scaleX = clipBox.clipClone.scaleX clipBox.scaleY = clipBox.clipClone.scaleY clipBox.width = _width clipBox.height = _height state.canvas.renderAll(); } }) setTimeout(() => { state.canvas.setActiveObject(state.clipBox); state.canvas.renderAll(); }, 300) }) } else { activeObject.clipClone.visible = true; state.canvas.renderAll(); } }
接着是肯定裁剪.net
let activeObject = state.canvas.getActiveObject(); state.isClipping = false activeObject.clipClone.visible = false state.canvas.remove(state.clipActiveObj);
这样你差很少也能明白个差很少了,让你单独本身写个裁剪插件适应其余项目也是没问题了。插件