Fabric JS 2.4.1 ClipPath Crop 不适用于动态创建的矩形蒙版
Posted
技术标签:
【中文标题】Fabric JS 2.4.1 ClipPath Crop 不适用于动态创建的矩形蒙版【英文标题】:Fabric JS 2.4.1 ClipPath Crop Not Working with a Dynamically Created rect Mask 【发布时间】:2019-03-07 18:54:23 【问题描述】:我正在使用fabric js 2.4.1 制作一个编辑器,并且已经完成了除动态图像裁剪之外的所有功能。该功能包括用鼠标在图像上创建一个矩形并单击裁剪按钮。
我已经成功完成了一个矩形的概念验证,该矩形是静态创建的,但无法让它在我的动态代码中呈现。我认为问题与动态创建的矩形无关,但我似乎无法隔离问题。它必须是我忽略的一些简单的东西,我认为问题可能出在我的裁剪按钮代码中。
document.getElementById("crop").addEventListener("click", function()
if (target !== null && mask !== null)
mask.setCoords();
target.clipPath = mask; // THIS LINE IS NOT WORKING!!!
//target.selectable = true;
target.setCoords();
console.log(target);
canvas.renderAll();
//canvas.remove(mask);
);
这是有问题的动态代码的一个小提琴: https://jsfiddle.net/Larry_Robertson/mqrv5fnt/
这是我从中获得概念证明的静态代码的一个小技巧: https://jsfiddle.net/Larry_Robertson/f34q67op/
动态版源码:
HTML
<canvas id="c" style="border:1px solid #ccc"></canvas>
<button id="crop">Crop</button>
JS
var canvas = new fabric.Canvas('c',
selection: true
);
var rect, isDown, origX, origY, done, object, mask, target;
var src = "http://fabricjs.com/lib/pug.jpg";
fabric.Image.fromURL(src, function(img)
img.selectable = false;
img.id = 'image';
object = img;
canvas.add(img);
);
canvas.on('object:added', function(e)
target = null;
mask = null;
canvas.forEachObject(function(obj)
//alert(obj.get('id'));
var id = obj.get('id');
if (id === 'image')
target = obj;
if (id === 'mask')
//alert('mask');
mask = obj;
);
);
document.getElementById("crop").addEventListener("click", function()
if (target !== null && mask !== null)
mask.setCoords();
target.clipPath = mask; // THIS LINE IS NOT WORKING!!!
//target.selectable = true;
target.setCoords();
console.log(target);
canvas.renderAll();
//canvas.remove(mask);
);
canvas.on('mouse:down', function(o)
if (done)
canvas.renderAll();
return;
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
rect = new fabric.Rect(
left: origX,
top: origY,
//originX: 'left',
//originY: 'top',
width: pointer.x - origX,
height: pointer.y - origY,
//angle: 0,
fill: 'rgba(255,0,0,0.3)',
transparentCorners: false,
//selectable: true,
id: 'mask'
);
canvas.add(rect);
canvas.renderAll();
);
canvas.on('mouse:move', function(o)
if (done)
canvas.renderAll();
return;
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x)
rect.set(
left: Math.abs(pointer.x)
);
if (origY > pointer.y)
rect.set(
top: Math.abs(pointer.y)
);
rect.set(
width: Math.abs(origX - pointer.x)
);
rect.set(
height: Math.abs(origY - pointer.y)
);
canvas.renderAll();
);
canvas.on('mouse:up', function(o)
if (done)
canvas.renderAll();
return;
isDown = false;
//rect.selectable = true;
rect.set(
selectable: true
);
rect.setCoords();
canvas.setActiveObject(rect);
canvas.bringToFront(rect);
canvas.renderAll();
//alert(rect);
rect.setCoords();
object.clipPath = rect;
object.selectable = true;
object.setCoords();
canvas.renderAll();
//canvas.remove(rect);
done = true;
);
【问题讨论】:
【参考方案1】:您需要将图像上的脏参数设置为true,以便在下次渲染调用时重新渲染对象的缓存。 这是小提琴: https://jsfiddle.net/mqrv5fnt/115/
var canvas = new fabric.Canvas('c',
selection: true
);
var rect, isDown, origX, origY, done, object, mask, target;
var src = "http://fabricjs.com/lib/pug.jpg";
fabric.Image.fromURL(src, function(img)
img.selectable = false;
img.id = 'image';
object = img;
canvas.add(img);
);
canvas.on('object:added', function(e)
target = null;
mask = null;
canvas.forEachObject(function(obj)
//alert(obj.get('id'));
var id = obj.get('id');
if (id === 'image')
target = obj;
if (id === 'mask')
//alert('mask');
mask = obj;
);
);
document.getElementById("crop").addEventListener("click", function()
if (target !== null && mask !== null)
mask.setCoords();
target.clipPath = mask; // THIS LINE IS NOT WORKING!!!
target.dirty=true;
//target.selectable = true;
target.setCoords();
canvas.remove(mask);
canvas.renderAll();
//canvas.remove(mask);
);
canvas.on('mouse:down', function(o)
if (done)
canvas.renderAll();
return;
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
rect = new fabric.Rect(
left: origX,
top: origY,
//originX: 'left',
//originY: 'top',
width: pointer.x - origX,
height: pointer.y - origY,
//angle: 0,
fill: 'rgba(255,0,0,0.3)',
transparentCorners: false,
//selectable: true,
id: 'mask'
);
canvas.add(rect);
canvas.renderAll();
);
canvas.on('mouse:move', function(o)
if (done)
canvas.renderAll();
return;
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x)
rect.set(
left: Math.abs(pointer.x)
);
if (origY > pointer.y)
rect.set(
top: Math.abs(pointer.y)
);
rect.set(
width: Math.abs(origX - pointer.x)
);
rect.set(
height: Math.abs(origY - pointer.y)
);
canvas.renderAll();
);
canvas.on('mouse:up', function(o)
if (done)
canvas.renderAll();
return;
isDown = false;
//rect.selectable = true;
rect.set(
selectable: true
);
rect.setCoords();
canvas.setActiveObject(rect);
canvas.bringToFront(rect);
canvas.renderAll();
//alert(rect);
rect.setCoords();
object.clipPath = rect;
object.selectable = true;
object.setCoords();
canvas.renderAll();
//canvas.remove(rect);
done = true;
);
【讨论】:
非常感谢马吕斯!这对我行得通。我仍然有一些定位问题,但我很确定我能解决这个问题。 这是我的小提琴,它也解决了定位问题。谢谢大家。 jsfiddle.net/Larry_Robertson/vocufy2q 我不确定这是否应该作为第二个问题提交,如果应该,请告诉我,我将删除它。尽管修复效果很好,但我注意到最终剪辑的图像仍然保留了原始图像的高度和宽度。有没有办法在不改变纵横比的情况下修剪剩余的空白或调整大小? 这与基本问题无关。需要查看官方文档。fabricjs.com/docs/fabric.Image.html。你需要使用cropX、cropY、width和height。以上是关于Fabric JS 2.4.1 ClipPath Crop 不适用于动态创建的矩形蒙版的主要内容,如果未能解决你的问题,请参考以下文章
Fabric JS clipPath:裁剪后如何使图像适合画布?
带有 clipPath 的 div 的单击事件在 angular.js 中不起作用