FabricJS: How to auto-resize image to fit group or rectangle object?

。_饼干妹妹 提交于 2019-12-11 17:01:50

问题


Goal: I'm seeking to add an image to a FabricJS group or rectangle object, and for the image to maintain it's original aspect ratio and center fit it's parent width/height.

I don't want the image overflow to show, but will show the overflow as a less opaque green in the examples below:


Landscape Image Example:

If it was a landscape oriented image, it would scale to max height, but then center itself with regards to width placement:

Since I'm not looking for the image overflow to show, the final product should look like this:


Portrait Image Example:

Similarly, if the image was portrait oriented, the image would scale 100% in width, but center itself in height:

And then negating the overflow, this is what I'm looking for as a final product:


Here's my stackblitz so far: https://stackblitz.com/edit/angular-gpfkkw

With the base-case code as follows:

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

This is obviously not the right solution, but a start. Any advice?


回答1:


I figured it out, here's the Stackblitz: https://stackblitz.com/edit/angular-yoo8h5

First, I compared whether or not the rectangle aspect ratio is proportional to the image through an if/else statement which decides whether or not to initially scale the image to the rectangle width/height.

Then I set either the top or the left attribute of the image to the rectangle boundary point. Then calculating the center point of the rectangle and subtracting half of the image's boundary and lastly, setting the rectangle group object's clipPath to that of the rectangle, it worked!


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


来源:https://stackoverflow.com/questions/58826290/fabricjs-how-to-auto-resize-image-to-fit-group-or-rectangle-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!