【问题标题】:How to deal with fabric JS image mask?如何处理fabric JS图像蒙版?
【发布时间】:2017-12-11 07:59:21
【问题描述】:

我正在尝试实现图像掩码,如下例所示:

此处的示例图片: https://s3-ap-northeast-1.amazonaws.com/utonly/demo/demo.jpg

我尝试了很多方法,花了很多时间,但仍然找不到一个好的解决方案。 图像必须能够在蒙版内调整大小和旋转,或从另一个视图进行编辑,然后将结果应用回图像。

我在这里找到了类似的例子 http://jsfiddle.net/tbqrn/68/ ,但我不希望图像相互通过。那可能吗?还是我有机会尝试其他方法来做到这一点?

var img01URL = 'http://fabricjs.com/assets/printio.png';
var img02URL = 'http://fabricjs.com/lib/pug.jpg';
var img03URL = 'http://fabricjs.com/assets/ladybug.png';
var img03URL = 'http://fabricjs.com/assets/ladybug.png';

var canvas = new fabric.Canvas('c');

var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.rect(10,10,150,150);
    ctx.rect(170,10,200,200);
    ctx.rect(10,170,150,150);
    ctx.closePath();
    ctx.stroke();
    ctx.clip();

fabric.Image.fromURL(img01URL, function(oImg) {
    oImg.scale(.25);
    oImg.left = 10;
    oImg.top = 10;
    canvas.add(oImg);
    canvas.renderAll();
});

fabric.Image.fromURL(img02URL, function(oImg) {
    oImg.scale(.40);
    oImg.left = 180;
    oImg.top = 0;
    canvas.add(oImg);
    canvas.renderAll();
});

fabric.Image.fromURL(img03URL, function(oImg) {
    oImg.left = 10;
    oImg.top = 170;
    canvas.add(oImg);
    canvas.renderAll();
});

感谢您的帮助。

【问题讨论】:

  • 首先阅读github.com/kangax/fabric.js 的文档和安装过程,如果有任何错误,请返回此处并发布有关相同的问题。
  • 对不起,我不太明白你的意思。我猜您正在谈论示例图像的链接。我已经修改了链接。谢谢。
  • 请检查:stackoverflow.com/a/44574678/7132835 它也有小提琴示例
  • @Observer 这个帖子很有帮助,谢谢。

标签: jquery svg fabricjs


【解决方案1】:

为了更好地解释这个答案: 此代码不在fabricJS 中,clipPath 不是fabricJS 属性(即使我希望它很快出现)。 此解决方案比使用 clipTo 函数(在 fabric 2.0 中已弃用)要好一些,因为它允许您使用标准织物形状进行剪裁。 这个想法是将标准形状附加到另一个定义为clipPath的形状。然后可以固定clipPath(就像它附加到画布上一样)或随图像移动。 这个想法还需要进一步探索。

有很多方法可以做到这一点。这些不是单一的班轮解决方案,需要自定义编码。 这是使用附加到图像的 clipPath 的解决方案。 需要修改主Image_render方法。

var img01URL = 'http://fabricjs.com/assets/printio.png';
var img02URL = 'http://fabricjs.com/lib/pug.jpg';
var img03URL = 'http://fabricjs.com/assets/ladybug.png';
var img03URL = 'http://fabricjs.com/assets/ladybug.png';



    fabric.Image.prototype._render = function(ctx) {
      // custom clip code
      if (this.clipPath) {
        ctx.save();
        if (this.clipPath.fixed) {
          var retina = this.canvas.getRetinaScaling();
          ctx.setTransform(retina, 0, 0, retina, 0, 0);
          // to handle zoom
          ctx.transform.apply(ctx, this.canvas.viewportTransform);
          //
          this.clipPath.transform(ctx);
        }
        this.clipPath._render(ctx);
        ctx.restore();
        ctx.clip();
      }
      
      // end custom clip code
    
    
      var x = -this.width / 2, y = -this.height / 2, elementToDraw;

      if (this.isMoving === false && this.resizeFilter && this._needsResize()) {
        this._lastScaleX = this.scaleX;
        this._lastScaleY = this.scaleY;
        this.applyResizeFilters();
      }
      elementToDraw = this._element;
      elementToDraw && ctx.drawImage(elementToDraw,
                                     0, 0, this.width, this.height,
                                     x, y, this.width, this.height);
      this._stroke(ctx);
      this._renderStroke(ctx);
    };

var canvas = new fabric.Canvas('c');
canvas.setZoom(0.5)
fabric.Image.fromURL(img01URL, function(oImg) {
    oImg.scale(.25);
    oImg.left = 10;
    oImg.top = 10;
    oImg.clipPath = new fabric.Circle({radius: 40, top: 50, left: 50, fixed: true, fill: '', stroke: '' });
    canvas.add(oImg);
    canvas.renderAll();
});

fabric.Image.fromURL(img02URL, function(oImg) {
    oImg.scale(.40);
    oImg.left = 180;
    oImg.top = 0;
    oImg.clipPath = new fabric.Path('M85.6,606.2c-13.2,54.5-3.9,95.7,23.3,130.7c27.2,35-3.1,55.2-25.7,66.1C60.7,814,52.2,821,50.6,836.5c-1.6,15.6,19.5,76.3,29.6,86.4c10.1,10.1,32.7,31.9,47.5,54.5c14.8,22.6,34.2,7.8,34.2,7.8c14,10.9,28,0,28,0c24.9,11.7,39.7-4.7,39.7-4.7c12.4-14.8-14-30.3-14-30.3c-16.3-28.8-28.8-5.4-33.5-11.7s-8.6-7-33.5-35.8c-24.9-28.8,39.7-19.5,62.2-24.9c22.6-5.4,65.4-34.2,65.4-34.2c0,34.2,11.7,28.8,28.8,46.7c17.1,17.9,24.9,29.6,47.5,38.9c22.6,9.3,33.5,7.8,53.7,21c20.2,13.2,62.2,10.9,62.2,10.9c18.7,6.2,36.6,0,36.6,0c45.1,0,26.5-15.6,10.1-36.6c-16.3-21-49-3.1-63.8-13.2c-14.8-10.1-51.4-25.7-70-36.6c-18.7-10.9,0-30.3,0-48.2c0-17.9,14-31.9,14-31.9h72.4c0,0,56-3.9,70.8,26.5c14.8,30.3,37.3,36.6,38.1,52.9c0.8,16.3-13.2,17.9-13.2,17.9c-31.1-8.6-31.9,41.2-31.9,41.2c38.1,50.6,112-21,112-21c85.6-7.8,79.4-133.8,79.4-133.8c17.1-12.4,44.4-45.1,62.2-74.7c17.9-29.6,68.5-52.1,113.6-30.3c45.1,21.8,52.9-14.8,52.9-14.8c15.6,2.3,20.2-17.9,20.2-17.9c20.2-22.6-15.6-28-16.3-84c-0.8-56-47.5-66.1-45.1-82.5c2.3-16.3,49.8-68.5,38.1-63.8c-10.2,4.1-53,25.3-63.7,30.7c-0.4-1.4-1.1-3.4-2.5-6.6c-6.2-14-74.7,30.3-74.7,30.3s-108.5,64.2-129.6,68.9c-21,4.7-18.7-9.3-44.3-7c-25.7,2.3-38.5,4.7-154.1-44.4c-115.6-49-326,29.8-326,29.8s-168.1-267.9-28-383.4C265.8,13,78.4-83.3,32.9,168.8C-12.6,420.9,98.9,551.7,85.6,606.2z',{top: 0, left: 180, fixed: true, fill: '', stroke: '', scaleX: 0.2, scaleY: 0.2 });
    canvas.add(oImg);
    canvas.renderAll();
});
#c {
    border:1px solid #ccc;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.16/fabric.min.js"></script>
<canvas id="c" width="400" height="400"></canvas>

【讨论】:

  • 这太棒了!!你给了很多这样做的人希望。您能否解释一下“自定义剪辑代码”?我不明白。
  • 与您在clipByName 示例中找到的代码相同(我认为它们不好),并以更好的方式打包,使您能够将clipShape 附加到图片。也许有一天它会成为一个fabricJS的特性。肯定不是这个月或下个月。
  • 好的,非常感谢。我刚刚发现这不适用于 setZoom。这有可能解决吗?这是 svg 编辑器项目的一个非常重要的特性。在这里演示:jsfiddle.net/cxhe03v8
  • 您的代码运行良好。但是,当我使用 canvas.toSVG() 时,剪辑数据会丢失。有解决办法吗?
  • 也许是的,我应该从头开始编写代码。可能需要一个适当的问题,也许这个 sn-p 复制在
猜你喜欢
  • 2014-05-14
  • 2013-01-07
  • 1970-01-01
  • 2021-03-04
  • 1970-01-01
  • 2012-02-12
  • 2013-10-23
  • 1970-01-01
  • 2020-05-13
相关资源
最近更新 更多