应用clipTo在fabric.js图像路径不正确重新定位图像
问题描述:
请看看这个小提琴:应用clipTo在fabric.js图像路径不正确重新定位图像
http://jsfiddle.net/2ktvyk4e/5/
var imgUrl, snapshotCanvas;
imgUrl = 'http://cdn-development.wecora.com/boards/backgrounds/000/001/388/cover/ocean-background.jpg';
snapshotCanvas = new fabric.StaticCanvas('snapshotCanvas', {
backgroundColor: '#e0e0e0',
width: 1000,
height: 1500
});
fabric.Image.fromURL(imgUrl, function(img) {
img.set({
width: 1000,
left: 0,
top: 0,
clipTo: function(ctx) {
return ctx.rect(0, 0, 1000, 400);
}
});
return snapshotCanvas.add(img).renderAll();
}, {
crossOrigin: 'Anonymous'
});
这很简单。我正在加载一张图片,然后试图剪裁它,以便画布的整个宽度被剪切掉,所以只显示前400个像素。出于某种原因,clipTo导致图像移动莫名其妙地调整:
正如你可以看到,当剪切路径应用莫名其妙地重新定位在画布上的图像。如果我删除clipTo,那么图像加载完整的画布宽度没有问题(当然它也是完整的高度,这是我们不想要的)。
我不知道这里发生了什么,或者为什么这是发生所以任何帮助表示赞赏。
答
确保在画布和图像上有originX
和originY
左边的top
和left
。另外 - 你并不需要将任何东西夹在画布上。我发现clipTo的唯一真正用途是将拼贴图像剪裁成其边界形状。如果你想限制从400像素以上被拖动的图像,我会建议呈现在其下方的矩形(evented = false
,selectable = false
),然后裁剪到矩形。
我把这个在一起,没有clipTo
(和改变了一些号码,我没有横向滚动)。它将图像呈现在画布下方一半。
http://jsfiddle.net/2ktvyk4e/6/
编辑:
我通过一些源代码,挖找clipByName
方法和寻找的东西两个辅助方法。我用它来记录拼贴图像和它们的边界直形(“图像”和“剪辑”)。我将它们存储在一个对象:
imageObjects: {
'collage_0': http://some.tld/to/image.ext,
'collage_1': http://some.tld/to/image2.ext
}
用于找到任一的片段或图像的辅助方法:
findClipByClipName: function (clipName) {
var clip = _(canvas.getObjects()).where({ clipFor: clipName }).first();
return clip;
},
findImageByClipFor: function (clipFor) {
var image = _(canvas.getObjects()).where({ clipName: clipFor }).first();
return image;
},
实际裁剪方法:
clipByName: function (ctx) {
this.setCoords();
var clipRect, scaleXTo1, scaleYTo1;
clipRect = collage.findClipByClipName(this.clipName);
scaleXTo1 = (1/this.scaleX);
scaleYTo1 = (1/this.scaleY);
ctx.save();
var ctxLeft, ctxTop;
ctxLeft = -(this.width/2) + clipRect.strokeWidth;
ctxTop = -(this.height/2) + clipRect.strokeWidth;
ctx.translate(ctxLeft, ctxTop);
ctx.rotate(degToRad(this.angle * -1));
ctx.scale(scaleXTo1, scaleYTo1);
ctx.beginPath();
ctx.rect(
clipRect.left - this.oCoords.tl.x,
clipRect.top - this.oCoords.tl.y,
clipRect.width,
clipRect.height
);
ctx.closePath();
ctx.restore();
function degToRad(degrees) {
return degrees * (Math.PI/180);
}
},
最后将图像添加到帆布,其中所有这样走到一起:
var clipName, clip, image;
clipName = helpers.findKeyByValue(url, this.imageObjects);
clip = this.findClipByClipName(clipName);
image = new Image();
image.onload = function() {
var collageImage = new fabric.Image(image, $.extend({}, collage.commonImageProps, {
left: clip.left,
top: clip.top,
clipName: clipName,
clipTo: function (ctx) {
return _.bind(collage.clipByName, collageImage)(ctx);
}
}));
collage.scaleImagesToClip(collageImage);
canvas.add(collageImage);
};
临屋但我不认为你完全理解了用例。这是一个HEADER映像(请参阅http://staging.wecora.com/boards/_Mwn5zsfpo1XB7RQpyPa)。我希望标题图像是画布宽度,但只有顶部300像素是可见的。我试图在画布和图像上的offsetX/Y没有效果。另外,你的其他解决方案似乎是这样的矫枉过正。这看起来像一个fabricjs错误,但不知道如何解决。 – JoshL
@JoshL从这个网站,它看起来不像你需要使用画布。 – Brian
使用HTML画布创建页面的缩略图图像,这就是为什么我们需要此功能。 – JoshL