如何使用 fabricjs 检查 canvas 上是否存在具有特定 id 的对象

How to check if an object with specific id exists on a canvas with fabricjs

我有一个功能,可以在单击 canvas 中的圆圈时在鼠标按下时添加图像。现在,每次我单击圆圈时,都会添加一个新图像,这不是我想要的。我想要某种切换功能,以便它在第二次单击时删除图像并在第三次添加新图像,依此类推。

我现在的功能是这样的:

cirkel1.on('mousedown', ()=>{
  var imgURL = 'https://i1.wp.com/nypost.com/wp-content/uploads/sites/2/2020/04/pugs-coronavirus.jpg';
  var pugImg = new Image();
  pugImg.onload = function (img) {
    var pug = new fabric.Image(pugImg, {
    width: 350,
    height: 100,
    left: 250,
    top: 70,
    scaleX: .25,
    scaleY: .25
    id: 'testimg'
    });
    canvas.add(pug);
  };
  pugImg.src = imgURL;
});

我想如果我检查 canvas 上是否存在 pug 对象,我可以将其删除,并且只在不存在 pug 对象时添加一个新对象。

所以我尝试了这个:

cirkel1.on('mousedown', ()=>{
  var imgURL = 'https://printzelf.nl/new/assets/images/logo_gewoon.png';
  var pugImg = new Image();
  pugImg.onload = function (img) {
    var pug = new fabric.Image(pugImg, {
    width: 350,
    height: 100,
    left: 250,
    top: 70,
    scaleX: .25,
    scaleY: .25
    id: 'testimg'
    });
    canvas.add(pug);
    if(pug > 0){
      console.log('pug exists');
    }else{
      console.log('pug doesnt exist');
    }
  };
  pugImg.src = imgURL;

});

但这总是转到这部分 console.log('pug doesnt exist'); 即使 canvas 上有多个哈巴狗。

那么正确的检查方法是什么?

完整代码:

https://codepen.io/twan2020/pen/MWbmgqE

如果你想切换图像可见性那么你只需要改变它的布尔值 visible 属性.

我们不会对每个热点圈进行硬编码,而是使用一个可以扩展以在将来添加更多内容的容器。

const hotspots = [
  {
    top: 140,
    left: 230,
    radius: 10,
    fill: '#009fe3',
    id: 'cirkel1',
    hoverCursor: 'pointer',
    selectable: false,
    imgUrl: 'https://i1.wp.com/nypost.com/wp-content/uploads/sites/2/2020/04/pugs-coronavirus.jpg' 
  }
];

由于单击热点时会加载图像,因此我们需要跟踪已激活的热点。

const loadedImages = [];

现在我们准备填充 canvas。

for (let [idx, props] of hotspots.entries()) {
  let c = new fabric.Circle(props);
  c.class = 'hotspot';
  c.name = 'hotspot-' + idx;
  canvas.add(c);
}

这段代码没有什么神奇之处,我们只是在将热点圈添加到 canvas 之前将两个属性 classname 添加到热点圈中。 class 属性 将允许我们过滤 canvas 上的对象,以便我们只将 mousedown 处理程序添加到热点圈。完成此操作后,我们现在可以添加处理程序了。

for (const ho of canvas.getObjects()) {
  // check for 'hotspot' class
  if (ho.class && ho.class === 'hotspot') {
    ho.on('mousedown', () => {
      // check if image was previously loaded
      if (loadedImages.indexOf(ho.name) < 0) {
        // image is not in the array
        // so it needs to be loaded
        // prepare the image properties
        let imgProps = {
          width: 850,
          height: 800,
          left: (ho.left + 30),
          top: (ho.top - 30),
          scaleX: .25,
          scaleY: .25,
          id: 'img-' + ho.name
        };
        var pugImg = new Image();
        pugImg.onload = function (img) {
          var pug = new fabric.Image(pugImg, imgProps);
          canvas.add(pug);
        };
        pugImg.src = ho.imgUrl;
        // update the `loadedImages` array
        loadedImages.push(ho.name);
      } else {
        // image was previously loaded
        for (const o of canvas.getObjects()) {
          // find the correct image on the canvas
          if (o.id && o.id === 'img-' + ho.name) {
            // toggle the visible property
            o.visible = !o.visible;
            break;
          }
        }
      }
    });
  }
}

mousedown 处理程序有两个可能的执行路径。如果以前没有点击过热点,则不会加载图像。我们通过在 loadedImages 数组中搜索热点的 name 属性 的值来确定这一点。如果找不到名称,则加载图像并将名称添加到数组中。热点 name 用于在将图像添加到 canvas 之前设置图像的 id。如果热点存在于数组中,那么我们找到带有图像 id 的 canvas 对象并切换 visible 属性.

代码笔:https://codepen.io/danag/pen/MWbvWbo