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

Posted

技术标签:

【中文标题】Fabric.js:裁剪图像后的选择框【英文标题】:Fabric.js: selection box after cropping image 【发布时间】:2017-11-22 18:29:34 【问题描述】:

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

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

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

【问题讨论】:

请附上您目前完成的工作。 【参考方案1】:

fabricjs中其实没有cropTo方法。

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

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

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

【讨论】:

谢谢!并道歉 - 我写的是“cropTo”而不是“clipTo”;我显然是指第二个。我已经编辑了我的问题以反映这一点。【参考方案2】:

以 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.

【讨论】:

this._findMargins 不是函数 请记住,这是我为 fabric.js 1.7.3 编写的一个函数,当我写这个问题时,它是最新的或至少是最近的一个。 _findMargins() 函数出现在这个版本的库中 - 事实上,对它的调用是在我什至没有更改的代码部分中! 它对我不起作用,它仍然在图像周围提供额外的透明空间。

以上是关于Fabric.js:裁剪图像后的选择框的主要内容,如果未能解决你的问题,请参考以下文章

使用固定大小的可拖动图片框裁剪图像

UIImagePickerController 裁剪图像高于用户选择

canvas裁剪图片,蒙版选择框

Fabric.js 动态裁剪区域对图像和 SVG/形状的影响不同

裁剪 Sprite 与单个图像的 Fabric.js 效率

使用 System.Drawing 制作选择工具,并在 vb.net 中裁剪图像