fabricjs 中的循环元素

loop elements in fabricjs

我尝试从 canvas 上的数组中绘制各种产品。现在我在一定程度上成功了。但是如果我想输出变量“articleNumber”,产品图片“oImg”会改变,但文本不会。此文本可能会被每张新绘图覆盖,最后所有文本都与数组中的最后一个相同。它可能与“var text”有关。你们中的任何人都可以帮助我轻松解决这个问题吗?我对这个主题比较陌生,所以不知道该找什么。

for (var i = 0; i < allproducts.length; i++) {
  // Product image
  var articleNumber = allproducts[i];

  fabric.Image.fromURL('img/products/' + articleNumber + '.png', function(oImg) {
      oImg.scaleToHeight(fullHeight/10)
          .set('originX', 'center')
          .set('left', Math.floor(Math.random() * fullWidth))
          .set('top', Math.floor(Math.random() * (fullHeight - 200)))

    // Article Number
    var text = new fabric.Text('  '+ allproducts[i] + '  ', {
        left: oImg.left,
        top: oImg.top + fullHeight/10 + 2,
        originX: 'center', 
        fontSize: 9,
        fontFamily: 'Helvetica',
        textAlign: 'center',
        backgroundColor: 'white'
    });

    // Grouped Article number and Product Image
    var product = new fabric.Group([oImg, text], {
        hasControls: false,
    });

    // Add Product to Canvas
    canvas.add(product);
});
}

此致, 雷登G.

有一个非常简单的方法可以解决您的问题,那就是使用 let 而不是 varfor 语句中声明 i

for (let i = 0; i < allproducts.length; i++) {  
  // ...
}

问题在于,在您对 fromURL 的所有回调中,i 的值停留在 for 循环完成时的最后一个值。这是因为当您使用 var 声明 i 变量时,它的范围不仅在 for 循环内,而且在整个包含函数中。因此只有一个 i 变量由所有回调共享,并且由于它们在循环完成后都 运行,因此它们获得 i 的最后一个值。如果您在回调中放置 console.log,您会发现情况就是如此。

另一方面,当您使用 let 时,for 循环的每次迭代都会创建一个新的 i 变量。这是因为 let 具有 块作用域 并且 for 循环是一个块。因此每个回调都有自己独特且正确的值 i.

有人讨论 letvar here

之间的区别

这是您的代码的工作版本:

const allproducts = [1, 2, 3, 4];

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

for (let i = 0; i < allproducts.length; i++) {
  // Product image
  var articleNumber = allproducts[i];

  const fullHeight = 1000;
  const fullWidth = 500;

  const imageUrl = 'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcRlkStdmho9qfM4ofmV4lSVRV_MPmrxPu1f1Q&usqp=CAU';

  fabric.Image.fromURL(imageUrl, function(oImg) {

    oImg.scaleToHeight(fullHeight / 10)
      .set('originX', 'center')
      .set('left', Math.floor(Math.random() * fullWidth))
      .set('top', Math.floor(Math.random() * (fullHeight - 200)))

    // Article Number
    var text = new fabric.Text('  ' + allproducts[i] + '  ', {
      left: oImg.left,
      top: oImg.top + fullHeight / 10 + 2,
      originX: 'center',
      fontSize: 9,
      fontFamily: 'Helvetica',
      textAlign: 'center',
      backgroundColor: 'white'
    });

    // Grouped Article number and Product Image
    var product = new fabric.Group([oImg, text], {
      hasControls: false,
    });

    // Add Product to Canvas
    canvas.add(product);
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
<canvas id="foo" width="1200" height="1200"></canvas>