前端 canvas 使用 fabric.js 如何做出遮住的效果?

请问 canvas 如何做出像如上图片的效果,图片中的手机壳摄像头是会遮住那个心的图案的,其它位置则不会,大概思路是怎么样的呢?这里就是有两个图层,一个作为背景图,一个是遮罩图,如下图

阅读 4.1k
2 个回答

感谢康定的回复,对于本题的具体解决方法如下:
对于图片其实有个 clippath 的属性,我们只需要用那个黑色镂空的图作为 clippath 就好了。


// mask 就是那个黑色图层
// 下面图片的属性只需要关注 absolutePositioned 和 clipPath 即可

fabric.Image.fromURL(mask.imgUrl, (hollowImg) => {
  hollowImg.set({
      top: bgHeight / 2 - this.globalBgSize / 2,
      left: bgWidth / 2 - this.globalBgSize / 2,
      scaleX: this.globalBgSize / originWidth,
      scaleY: this.globalBgSize / originHeight,
      selectable: false,
      globalCompositeOperation: 'destination-in',
      customMask: true,
      absolutePositioned: true, // 注意这个属性,是相对于图片上一级的
  })
  this.imgClipPath = hollowImg;
  }, {
  crossOrigin: 'anonymous'
});

fabric.Image.fromURL(img.path, (oImg) => {
    oImg.set({
        top: this.canvasHeight / 2 - oImg.height * 0.2 / 2,
        left: this.canvasWidth / 2 - oImg.width * 0.2 / 2,
        scaleX: 0.2,
        scaleY: 0.2,
        globalCompositeOperation: 'source-atop',
        customType: '',
        clipPath: this.imgClipPath
    })
}, {
    crossOrigin: 'anonymous'
});

如果你想要在 fabric.js 中实现遮住的效果,有两种常见的方式:

使用遮罩(Mask)
fabric.js 中提供了mask属性来实现遮罩的效果,可以将一个固定大小的遮罩图形应用到另一个对象上,从而实现遮罩的效果。

具体实现步骤如下:

创建一个遮罩对象:可以是任何一个固定大小的 fabric 对象,比如一个矩形或圆形;
创建需要被遮罩的对象;
将遮罩对象的objectCaching属性设置为false;
设置被遮罩的对象的mask属性为遮罩对象。
示例代码:

// 创建一个矩形做遮罩
var maskRect = new fabric.Rect({
  width: 200,
  height: 200,
  left: 0,
  top: 0,
  fill: 'black',
  opacity: 0.5,
  selectable: false,
  evented: false
});
// 创建需要被遮罩的文本对象
var text = new fabric.Text('Hello World', {
  left: 50,
  top: 50,
  fill: 'white'
});

// 将遮罩对象的 objectCaching 属性设置为 false,否则遮罩无法生效
maskRect.objectCaching = false;
// 将文本对象的 mask 属性设置为遮罩对象
text.mask = maskRect;

// 添加到 canvas 中查看效果
canvas.add(maskRect);
canvas.add(text);

2使用裁剪(Clip)

具体实现步骤如下:

在需要裁剪的对象上设置clipTo属性为一个函数;
在clipTo函数内部实现裁剪的逻辑;
在渲染时,fabric.js 会自动调用clipTo函数来裁剪对象。
示例代码:

// 创建一个矩形做裁剪区域
var clipRect = new fabric.Rect({
  width: 200,
  height: 200,
  left: 0,
  top: 0,
  selectable: false,
  evented: false
});

// 创建需要被裁剪的文本对象
var text = new fabric.Text('Hello World', {
  left: 50,
  top: 50,
  fill: 'white'
});

// 在文本对象上设置 clipTo 属性
// 渲染时,裁剪区域 clipRect 会被作为参数传入
text.clipTo = function(ctx) {
  // 绘制裁剪区域
  clipRect.render(ctx);
};

// 添加到 canvas 中查看效果
canvas.add(clipRect);
canvas.add(text);
fabric.js 中也提供了clipTo属性来实现裁剪的效果,可以将对象在渲染时裁剪成指定的形状。

这两种方式的区别在于:

遮罩(Mask)通常用于将一个对象根据遮罩图形进行隔离和遮盖,遮罩对象不会被裁剪;
裁剪(Clip)通常用于将对象裁剪成指定的形状,被裁剪对象的形状会发生改变。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题