【问题标题】:fabricjs placement of images on canvas inconsistentfabricjs在画布上的图像放置不一致
【发布时间】:2020-08-26 20:44:56
【问题描述】:

我有一系列 4 张图像,我试图将它们放置在 fabricjs 中的指定坐标处,但有时在页面加载时它们的放置不一致。刷新一次或两次通常会给出正确的布局。试图阻止这种情况发生。

有人知道如何解决这个问题吗?这是我的代码:

var objects = [
    { type: "image", filename : "tv.png" , x: 688, y: 184, angle: 0, zIndex: 10 },
    { type: "image", filename : "polaroid.jpg" , x: 347, y: 515 },
    { type: "image", filename : "polaroid.jpg" , x: 138, y: 643 },
    { type: "image", filename : "polaroid.jpg" , x: 429, y: 803 },
    { type: "text", text: "Your favorite band", x: 1168, y: 1163, angle: -17, canvasRef: null,zIndex: 50 }
];

for (var i=0; i<objects.length;i++){

    var objRef = objects[i];

    switch(objRef.type){
        case 'image':
            var url = "img/" + objRef.filename;

            fabric.Image.fromURL(url, function(img) {
                var objRef = objects[curObject];
                img.set({
                    left: objRef.x,
                    top: objRef.y,
                    angle: objRef.angle,
                    hasBorders: false,
                    hasControls: false,
                    hasRotatingPoint: false,
                    lockMovementX: true,
                    lockMovementY: true
                });
                canvas.add(img).renderAll();
                img.moveTo(objRef.zIndex);
                curObject++;
                //canvas.setActiveObject(img);
            });

            break;

        case 'text':
            var text = objRef.text;
            var fabricText = new fabric.Text(text, {
                left: objRef.x,
                top: objRef.y,
                angle: objRef.angle,
                hasBorders: false,
                hasControls: false,
                hasRotatingPoint: false,
                lockMovementX: true,
                lockMovementY: true
            });
            objRef.canvasRef = fabricText;
            addTextListeners(fabricText);
            canvas.add(fabricText);
            break;
    }

}

我还应该提到,在 window.ready 之后,并且在使用 imagesloaded 插件预加载了 fabric 尝试加载到画布的所有图像之后,这些代码都不会发生。

我还应该提到,我尝试在每次加载(而不是循环)之间使用 setTimeout 延迟加载每个连续图像,并将 canvas.renderAll() 保存到循环之后,但没有成功。甚至尝试运行循环以在将项目放置在屏幕上后重新定位它们。下面是问题的图片 - 分别是正确的和不正确的。

【问题讨论】:

    标签: javascript canvas fabricjs


    【解决方案1】:

    从以不同顺序加载的图像来看,您似乎存在竞争条件。

    fabric.Image.fromURL() 方法使用回调函数,该函数在图像加载后触发,因此不能保证内部函数会按照调用顺序触发。但是您每次调用函数时都使用curObject 向上递增,这假设它们是按顺序调用的。并且 objRef 可以在图像加载时重新分配给新对象,这就是 x/y/rotate 值关闭的原因(使用数组中其他对象的值)。

    所以,不要在图像加载后使用img.set(),而是使用Image.fromURL() 方法的第三个参数来传递您的属性:

    for (var i=0; i<objects.length;i++){
      var objRef = objects[i];
      switch(objRef.type){
        case 'image':
          var url = "img/" + objRef.filename;
          fabric.Image.fromURL(url, function(img) {
            canvas.add(img).renderAll();
          }, {
            left: objRef.x,
            top: objRef.y,
            angle: objRef.angle,
            hasBorders: false,
            hasControls: false,
            hasRotatingPoint: false,
            lockMovementX: true,
            lockMovementY: true
          });
          break;
    
        case 'text':
          // ...
          break;
      }
    }
    

    【讨论】:

      【解决方案2】:

      所以答案的关键是异步回调。只需检查警报消息何时发出即可。

      fabric.Image.fromURL('hulk.png', function (img) {
          alert('came1');
          canvas.add(img).renderAll();
          }, {
              id: 'hulkid',
              num: 1,
              left: 10,
              top: 10,
              angle: 0
          });
      
      fabric.Image.fromURL('hulk.png', function (img) {
          alert('came2');
          canvas.add(img).renderAll();
      }, {
          id: 'hulkid',
          num: 2,
          left: 25,
          top: 25,
          angle: 0
      });
      alert('came Last');
      

      【讨论】:

        【解决方案3】:

        我找到了 setTimeout 函数的方法。

        我用MidnightLightning的样本测试过

        但canvas中的图像z-index仍然存在一些问题(所有设置都很好)。我认为有时fabric.Image.fromURL回调函数正在等待图像加载,所以在绘制图像的队列中会出现一些错误。

        所以我添加了一些超时功能,就像那样。

        var count_layer=0;
        var image_src_list_array=['1.jpg', '2.jpg'];
        
        function paint_layer(){
            console.log(image_src_list_array[count_layer]);
        
            if(image_src_list_array[count_layer]!=''){
                            
                fabric.Image.fromURL(
                      image_src_list_array[count_layer],
                      function(img){
                           console.log('rendering');
                           fabric_canvas.add(img).renderAll();
                      }, {
                           id: count_layer+1,
                           left: ...,
                           top: ...,
                           angle: ...,}
        
                ); 
        
                count_layer++;
                setTimeout(paint_layer,3000);
            }
            
        }
        

        那么控制台日志结果是:

        1.jpg
        rendering
        2.jpg
        rendering
        

        输出之前

        1.jpg
        2.jpg
        rendering
        rendering
        

        【讨论】:

          猜你喜欢
          • 2015-11-07
          • 1970-01-01
          • 2018-12-25
          • 2015-05-05
          • 2021-06-13
          • 1970-01-01
          • 2017-08-23
          • 1970-01-01
          相关资源
          最近更新 更多