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();
}