【问题标题】:HTML5 Canvas - For loop to place elements in gridHTML5 Canvas - 用于在网格中放置元素的 For 循环
【发布时间】:2015-11-02 18:29:12
【问题描述】:

我正在 HTML5 画布中构建一个简单的关卡放置脚本,但我在实际放置每个元素时遇到了麻烦。我编写了一个创建网格的 for 循环,然后我尝试创建一个新循环,该循环遍历我的“级别”数组中的每个语句以设置每个图像的位置。我以前没有用 Canvas 做过很多事情。因此,我不确定在放置这些图像方面我做错了什么;我在 jQuery 中写了一些与此非常相似的东西,效果很好 - 事实上,我复制并粘贴了代码以开始,但它似乎在 Canvas 中不起作用。任何帮助将不胜感激!

这是代码的 sn-p;请原谅过度评论,这只是当我无法理解为什么某些事情不起作用时我会做的事情。这就像一个内嵌的橡皮鸭。

var $levelArray = [
  [0, 0, 0, "blue", "blue"], 
  [0, "gray", 0, 0, 0], 
  ["blue", "blue", "green", 0, "blue"], 
  ["blue", 0, "yellow", 0, 0], 
  [0, 0, 0, "gray", 0], 
  ["red", 0, 0, 0, 0]];

var border = 5, // set grid details
    spaceWidth = 80, 
    spaceAmount = 5;

    // create a tiled image
function makeTile(imageUrl, horizontalPosition, verticalPosition) {
  var tile = new Image();

  tile.onload = function() {
    context.drawImage(tile, horizontalPosition, verticalPosition);
  }
  tile.src = imageUrl;
}

    // place the image tiles on the board
for (var i=0; i < ($levelArray.length - 1); i++) {
  var row = $levelArray[i]; // set each row's iterative position
  var rowHeight = 5;

  for (var j=0; j < row[j].length; j++) {
    var rowPosition = 5; // set the left margin of each element

    if (row[j] == 0) {
      rowPosition += (spaceWidth + 5); // if an element does not exist, jump forwards to the next space
    } else {
      //if one DOES exist, place an image in this space
      makeTile("http://lorempixel.com/80/80", rowPosition, rowHeight);
      rowPosition += (spaceWidth + 5); // then move to the next space
    };
  };
  rowHeight += (spaceWidth + 5); // once a row is complete, drop to the next row's positions
};

我在这里的代码笔中有这个:http://codepen.io/sarsparillo/pen/vNrWQG

我不确定为什么它一次只加载一张图片并将其放在我网格上的 0,0 空间中;在 jQuery 中使用非常相似的代码(当前代码,到处都是,有点不干净,在这里 - http://codepen.io/sarsparillo/pen/GpdjYY)将元素放在正确的位置就好了。

更多,当我在那些 for 循环中添加一个 console.log 语句时,我真的无法弄清楚它到底从哪里获取数据。就像,一次迭代给了我“绿色绿色黄色”作为 row[j] 中的项目,另一个“蓝灰色蓝色” - Canvas 在遍历数组时做了一些绝对奇怪的事情吗?我看不出它是怎么做到的,因为这只是 Javascript,但是......?

有没有人知道为什么会发生这种情况,或者我可以如何解决这个问题的任何提示?从理论上讲,它应该只是将空间宽度+边距宽度添加到每个“正方形”的起点,所以我不确定为什么它只是......不是。

【问题讨论】:

    标签: javascript html canvas grid iteration


    【解决方案1】:

    jsFiddle : https://jsfiddle.net/CanvasCode/4gr9apqm/

    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    
    var border = 5, // set grid details
        spaceWidth = 80,
        spaceAmount = 5;
    
    var $levelArray = [
        ["blue", 0, 0, "blue", "blue"],
        [0, "gray", 0, 0, 0],
        ["blue", "blue", "green", 0, "blue"],
        ["blue", 0, "yellow", 0, 0],
        [0, 0, 0, "gray", 0],
        ["red", 0, 0, 0, 0]
    ];
    
    canvas.width = (spaceWidth * spaceAmount) + (5 * spaceAmount) + 5; // and here's the canvas size
    canvas.height = (spaceWidth * spaceAmount) + (5 * spaceAmount) + 5;
    
    // make a rounded corner square; using a sizing hack to make sure that strokes don't effect the full size of the item
    function square(originX, originY, size, corner, fill) {
        var startFromX = originX + (corner / 2);
        var startFromY = originY + (corner / 2);
        var extentsX = startFromX + (size - corner);
        var extentsY = startFromY + (size - corner);
        context.lineJoin = "round";
        context.lineWidth = corner;
        context.fillStyle = "#513574";
        context.strokeStyle = fill;
    
        context.beginPath();
        context.moveTo(startFromX, startFromY);
        context.lineTo(startFromX, extentsY);
        context.lineTo(extentsX, extentsY);
        context.lineTo(extentsX, startFromY);
        context.closePath();
        context.stroke();
        context.fill();
    }
    
    // build a grid of said squares
    function squareGrid(spacing, size, corner, color, amount) {
        for (var x = 0; x < amount; x++) {
            // build rows
            for (var y = 0; y < amount; y++) {
                // build column spacing in each row
                square(5 + (size * x) + (spacing * x), 5 + (size * y) + (spacing * y), size, corner, color);
                // build each square
            }
        };
    };
    
    // actually parse the arguments for said square
    squareGrid(border, spaceWidth, (border * 2), "#f13574", spaceAmount);
    
    // create a tiled image
    function makeTile(tile, horizontalPosition, verticalPosition) {
        switch (tile) {
            case "blue":
                context.fillStyle = "#00F";
                context.fillRect(horizontalPosition, verticalPosition, 80, 80);
                break;
            case "green":
                context.fillStyle = "#0F0";
                context.fillRect(horizontalPosition, verticalPosition, 80, 80);
                break;
            case "red":
                context.fillStyle = "#F00";
                context.fillRect(horizontalPosition, verticalPosition, 80, 80);
                break;
            case "gray":
                context.fillStyle = "#999";
                context.fillRect(horizontalPosition, verticalPosition, 80, 80);
                break;
            case "yellow":
                context.fillStyle = "#FF0";
                context.fillRect(horizontalPosition, verticalPosition, 80, 80);
                break;
        }
    };
    
    var gapHeight = 5;
    var gapWidth = 5;
    
    for (var y = 0; y < $levelArray.length - 1; y++) {
        var row = $levelArray[y];
    
        for (var x = 0; x < row.length; x++) {
            var newXPos = (gapWidth * (x + 1)) + (80 * x);
            var newYPos = (gapHeight * (y + 1)) + (80 * y)
    
            makeTile($levelArray[y][x], newXPos, newYPos);
        }
    }
    

    我所改变的基本上是你如何访问你的二维数组和位置计算。基本上,您首先访问的是您的 Y 位置,然后从您的 Y 位置查看该行上的所有块。所以我们首先找到“在我的情况下”blue, 0, 0, blue, blue。所以所有这些都将有 y 位置 0,然后它将从 0、80、160 等开始。但是,因为您想要块之间的间隙,您还必须将间隙乘以当时的 x 和 y 值:)

    【讨论】:

    • 谢谢!我不太喜欢编写 switch 语句(我更喜欢键控方法查找),但这对我来说似乎是一个很好的开始;最后一个元素将只在其顶部添加一个文本分隔符,因为每个空格都被列为“蓝色左侧”“红色向下”等。除了易于显示之外,您是否有任何理由使用 fillRect 而不是使用图像发生了什么?基本上,将图像加载到这些空间会导致一个不存在的问题,如果你只是去 'fillRect' 或者在画布上放置图像的最终结果与绘制矩形几乎相同?
    • 使用 80 x 80 的图像最终会得到相同的结果,我只是为了方便而使用了 fillRect :)
    猜你喜欢
    • 2019-12-12
    • 2020-12-12
    • 2016-07-12
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    相关资源
    最近更新 更多