如何使用fabricjs检查画布上是否存在具有特定ID的对象

问题描述

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

我现在的函数是这样的:

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;
});

我想如果我检查画布上是否存在 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,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'); 部分。

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

完整代码

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 = [];

现在我们已准备好填充画布。

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

这段代码没有什么神奇之处,我们只是在将热点圆圈添加到画布之前,向热点圆圈添加了两个属性 classnameclass 属性将允许我们过滤画布上的对象,以便我们只将 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 用于在将图像添加到画布之前设置图像的 id。如果数组中存在热点,那么我们会找到带有图像 id 的画布对象并切换 visible 属性。

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