Fabric.js:图片裁剪后的选择框

Fabric.js: selection box after cropping image

在使用 Fabric.js 1.7.3 时,我注意到在裁剪图像时有一个奇怪的行为。本质上,我在图像中设置了 clipTo 方法以仅在图像中心显示一个小方块:

但是,问题是图像的选择框仍然占据原始尺寸,而不是裁剪后的尺寸。单击图像时,我希望角紧挨着图片的边缘;同样,只有当我点击裁剪后的图片时,选择才会被激活。

一个可能的解决方案是将图像的裁剪部分导出为 base64,删除旧图像并添加裁剪版本。然而,这是相当不切实际的,感觉有点矫枉过正。有没有一种方法可以简单地调整选择框以符合裁剪后的尺寸?

fabricjs中其实没有cropTo方法

有一个 clipTo 方法的行为与您描述的一样。

裁剪还不是 fabricjs 的基本功能。 2.0 版本可能会更容易,但目前获得它的唯一方法是继承 render 方法并完全自己完成。

  • 使用 ctx.drawImage(this._element, sx, sy, sw, sh, dx, dy, dw, dh) 公式。
  • 维护您自己的作物信息由 sx、sy、sw、sh 表示

基于 AndreaBogazzi 的回答,这是我的完整解决方案,我在其中重写了 _render 方法。每当我创建一个图像时,我都会向它添加一个 "sizeMode" 属性,它告诉 _render 如何准确地绘制它:

fabric.Image.prototype._render = function(ctx, noTransform) {
    /* This is the default behavior. I haven't modified anything in this part. */
    let x, y, imageMargins = this._findMargins(), elementToDraw;

    x = (noTransform ? this.left : -this.width / 2);
    y = (noTransform ? this.top : -this.height / 2);

    if (this.meetOrSlice === 'slice') {
        ctx.beginPath();
        ctx.rect(x, y, this.width, this.height);
        ctx.clip();
    }

    if (this.isMoving === false && this.resizeFilters.length && this._needsResize()) {
        this._lastScaleX = this.scaleX;
        this._lastScaleY = this.scaleY;
        elementToDraw = this.applyFilters(null, this.resizeFilters, this._filteredEl
            || this._originalElement, true);
    }
    else {
        elementToDraw = this._element;
    }

    /* My changes begin here. */
    if (elementToDraw && elementToDraw.naturalHeight > 0) {
        if (this.sizeMode === BadgingImageSizeMode.CenterImage) {
            drawCenterImage.apply(this, [ctx, elementToDraw, imageMargins, x, y]);
        } else {
            // Default _render behavior
            ctx.drawImage(elementToDraw,
                x + imageMargins.marginX,
                y + imageMargins.marginY,
                imageMargins.width,
                imageMargins.height);
        }
    }

    /* And they finish here. */
    this._stroke(ctx);
    this._renderStroke(ctx);
};

我定义的 drawCenterImage 函数在这里:

const drawCenterImage = function(ctx, elementToDraw, imageMargins, x, y) {
    const sx = (elementToDraw.naturalWidth - this.width) / 2;
    const sy = (elementToDraw.naturalHeight - this.height) / 2;
    ctx.drawImage(elementToDraw,
        sx,
        sy,
        imageMargins.width,
        imageMargins.height,
        x + imageMargins.marginX,
        y + imageMargins.marginY,
        imageMargins.width,
        imageMargins.height);
};

虽然这适用于居中图像(正如我最初的问题),但对 ctx.drawImage 的不同调用会产生不同的效果。 Here is the documentation for the drawImage method.