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

Javascript Fabric.js:裁剪图像后的选择框,javascript,image,fabricjs,crop,Javascript,Image,Fabricjs,Crop,在使用Fabric.js 1.7.3时,我注意到剪切图像时有一种奇怪的行为。基本上,我已将图像中的clipTo方法设置为仅在图像中心显示一个小正方形: 但是,问题是图像的选择框仍然采用原始大小,而不是裁剪大小。当点击图片时,我希望角落就在图片边缘的旁边;类似地,仅当我单击裁剪的图片时,才应激活选择 一个可能的解决方案是将图像的裁剪部分导出为base64,删除旧图像并添加裁剪版本。然而,这是相当不切实际的,感觉有点过分了。有没有一种方法可以简单地调整选择框以适应裁剪的大小?fabricjs中实际

在使用Fabric.js 1.7.3时,我注意到剪切图像时有一种奇怪的行为。基本上,我已将图像中的clipTo方法设置为仅在图像中心显示一个小正方形:

但是,问题是图像的选择框仍然采用原始大小,而不是裁剪大小。当点击图片时,我希望角落就在图片边缘的旁边;类似地,仅当我单击裁剪的图片时,才应激活选择


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

fabricjs中实际上没有cropTo方法

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

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

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

    • 在fabricjs中实际上没有cropTo方法

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

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

      • 使用ctx.drawImage(这个._元素,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的不同调用将产生不同的效果

      以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的不同调用将产生不同的效果

      请包括你到目前为止所完成的。请包括你到目前为止所完成的。谢谢!道歉——我写的是“cropTo”而不是“clipTo”;我显然是指第二个。我已经编辑了我的问题以反映这一点。谢谢!道歉——我写的是“cropTo”而不是“clipTo”;我显然是指第二个。我已经编辑了我的问题以反映这一点。这是一个函数。请记住,这是我为fabric.js 1.7.3编写的函数,它是我编写此问题时最新的或至少是最新的函数之一。这个版本的库中有_findMargins()函数-事实上,对它的调用在我甚至没有更改的代码部分!它对我不起作用,它仍然在图像周围提供额外的透明空间。这是一个函数。请记住,这是我为fabric.js 1.7.3编写的函数,它是我写这个问题时最新的或至少是最近的一个函数。这个版本的库中有_findMargins()函数-事实上,对它的调用在我甚至没有更改的代码部分!它不适合我,它仍然在图像周围提供额外的透明空间。