FabricJS:如何自动调整图像大小以适合组或矩形对象?
FabricJS: How to auto-resize image to fit group or rectangle object?
目标: 我正在寻求将图像添加到 FabricJS 组或矩形对象,并使图像保持其原始纵横比并中心适合其父对象 width/height.
我不希望图像溢出显示,但在下面的示例中会将溢出显示为不太透明的绿色:
风景图片示例:
如果它是横向图像,它会缩放到最大高度,但随后会根据宽度放置自行居中:
由于我不是在寻找要显示的图像溢出,因此最终产品应如下所示:
肖像图像示例:
同样,如果图像是纵向的,图像将在宽度上缩放 100%,但在高度上居中:
然后取消溢出,这就是我要寻找的最终产品:
这是我到目前为止的 stackblitz:https://stackblitz.com/edit/angular-gpfkkw
基本情况代码如下:
this.canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
left: 100,
top: 50,
width: 450,
height: 200,
fill: '#e3e3e3',
});
var rectGroup = new fabric.Group([rect], {
name: 'Rectangle',
});
this.canvas.add(rectGroup);
fabric.Image.fromURL('https://placehold.it/888x500&text=16:9', (img) => {
let bounds = rectGroup.getBoundingRect();
const scaleFactor = Math.min(
Math.min(bounds.width / img.width),
Math.min(bounds.height / img.height)
);
img.scale(scaleFactor);
img.set({
top: bounds.top + Math.max(bounds.height - img.height * scaleFactor, 0)/2,
left: bounds.left + Math.max(bounds.width - img.width * scaleFactor, 0)/2,
});
rectGroup.addWithUpdate(img);
this.canvas.renderAll();
}
这显然不是正确的解决方案,而是一个开始。有什么建议吗?
我明白了,这是 Stackblitz:https://stackblitz.com/edit/angular-yoo8h5
首先,我通过一个if/else
语句来比较矩形纵横比是否与图像成正比,该语句决定是否将图像初始缩放到矩形width/height。
然后我将图像的top 或left 属性设置为矩形边界点。然后计算矩形的中心点并减去图像边界的一半,最后将矩形组对象的 clipPath
设置为矩形的 clipPath
,成功了!
fabric.Image.fromURL('https://placehold.it/888x500&text=16:9', (img) => {
let bounds = rectGroup.getBoundingRect();
if ((bounds.height / bounds.width) >= (img.height / img.width)) {
img.scaleToHeight(bounds.height);
img.set({
top: bounds.top,
left: (bounds.left + (bounds.width/2)) - (img.getBoundingRect().width/2)
});
}
else {
img.scaleToWidth(bounds.width);
img.set({
top: (bounds.top + (bounds.height/2)) - (img.getBoundingRect().height/2),
left: bounds.left
});
}
rectGroup.addWithUpdate(img);
rectGroup.clipPath = rect;
this.canvas.renderAll();
});
这里有点晚了,但如果这可能会有帮助,请补充一下。
您使用 Math.min
的方向是正确的,但您可以使用 Math.max
代替具有较大 group/image 比率的边,以缩放到边的全长.然后您可以将 x y 原点设置为 center
.
fabric.Image.fromURL('https://placehold.it/888x500&text=16:9', (img) => {
let bounds = rectGroup.getBoundingRect();
const scaleFactor = Math.max(bounds.width / img.width, bounds.height / img.height);
img.set({
originX: 'center',
originY: 'center',
scaleX: scaleFactor,
scaleY: scaleFactor
});
rectGroup.addWithUpdate(img);
this.canvas.renderAll();
}
目标: 我正在寻求将图像添加到 FabricJS 组或矩形对象,并使图像保持其原始纵横比并中心适合其父对象 width/height.
我不希望图像溢出显示,但在下面的示例中会将溢出显示为不太透明的绿色:
风景图片示例:
如果它是横向图像,它会缩放到最大高度,但随后会根据宽度放置自行居中:
由于我不是在寻找要显示的图像溢出,因此最终产品应如下所示:
肖像图像示例:
同样,如果图像是纵向的,图像将在宽度上缩放 100%,但在高度上居中:
然后取消溢出,这就是我要寻找的最终产品:
这是我到目前为止的 stackblitz:https://stackblitz.com/edit/angular-gpfkkw
基本情况代码如下:
this.canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
left: 100,
top: 50,
width: 450,
height: 200,
fill: '#e3e3e3',
});
var rectGroup = new fabric.Group([rect], {
name: 'Rectangle',
});
this.canvas.add(rectGroup);
fabric.Image.fromURL('https://placehold.it/888x500&text=16:9', (img) => {
let bounds = rectGroup.getBoundingRect();
const scaleFactor = Math.min(
Math.min(bounds.width / img.width),
Math.min(bounds.height / img.height)
);
img.scale(scaleFactor);
img.set({
top: bounds.top + Math.max(bounds.height - img.height * scaleFactor, 0)/2,
left: bounds.left + Math.max(bounds.width - img.width * scaleFactor, 0)/2,
});
rectGroup.addWithUpdate(img);
this.canvas.renderAll();
}
这显然不是正确的解决方案,而是一个开始。有什么建议吗?
我明白了,这是 Stackblitz:https://stackblitz.com/edit/angular-yoo8h5
首先,我通过一个if/else
语句来比较矩形纵横比是否与图像成正比,该语句决定是否将图像初始缩放到矩形width/height。
然后我将图像的top 或left 属性设置为矩形边界点。然后计算矩形的中心点并减去图像边界的一半,最后将矩形组对象的 clipPath
设置为矩形的 clipPath
,成功了!
fabric.Image.fromURL('https://placehold.it/888x500&text=16:9', (img) => {
let bounds = rectGroup.getBoundingRect();
if ((bounds.height / bounds.width) >= (img.height / img.width)) {
img.scaleToHeight(bounds.height);
img.set({
top: bounds.top,
left: (bounds.left + (bounds.width/2)) - (img.getBoundingRect().width/2)
});
}
else {
img.scaleToWidth(bounds.width);
img.set({
top: (bounds.top + (bounds.height/2)) - (img.getBoundingRect().height/2),
left: bounds.left
});
}
rectGroup.addWithUpdate(img);
rectGroup.clipPath = rect;
this.canvas.renderAll();
});
这里有点晚了,但如果这可能会有帮助,请补充一下。
您使用 Math.min
的方向是正确的,但您可以使用 Math.max
代替具有较大 group/image 比率的边,以缩放到边的全长.然后您可以将 x y 原点设置为 center
.
fabric.Image.fromURL('https://placehold.it/888x500&text=16:9', (img) => {
let bounds = rectGroup.getBoundingRect();
const scaleFactor = Math.max(bounds.width / img.width, bounds.height / img.height);
img.set({
originX: 'center',
originY: 'center',
scaleX: scaleFactor,
scaleY: scaleFactor
});
rectGroup.addWithUpdate(img);
this.canvas.renderAll();
}