简体   繁体   English

HTML5 Canvas-用于将元素放置在网格中的循环

[英]HTML5 Canvas - For loop to place elements in grid

I'm in the process of building a simple level placement script in HTML5 canvas, and I'm having trouble actually placing each element down. 我正在用HTML5 canvas构建一个简单的关卡放置脚本,而实际上将每个元素放下都遇到了麻烦。 I've written a for loop that creates a grid, then I'm trying to create a new loop that iterates through each statement in my 'level' array to set positions for each image. 我编写了一个用于创建网格的for循环,然后尝试创建一个新的循环,该循环遍历“级别”数组中的每个语句以设置每个图像的位置。 I haven't done a lot with Canvas before; 我以前对Canvas并没有做很多事情; as such, I'm not sure what I'm doing wrong in regards to placing these images; 因此,我不确定在放置这些图片方面做错了什么; I've written something very similar to this in jQuery that works just fine - in fact, I copied and pasted the code to start with, but it doesn't seem to work in Canvas. 我已经在jQuery中编写了与之非常相似的东西,效果很好-实际上,我复制并粘贴了开始的代码,但是在Canvas中似乎不起作用。 Any help would be appreciated! 任何帮助,将不胜感激!

Here's a snippet of the code; 这是代码片段; forgive the over-commenting, this is just a thing I do when I'm having trouble understanding why something doesn't work. 原谅过多的评论,这只是我在无法理解为什么某些功能无效时要做的一件事。 It's like an inline Rubber Duck. 就像内嵌的橡皮鸭。

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

I have this in a codepen here: http://codepen.io/sarsparillo/pen/vNrWQG 我在一个codepen中有这个: http ://codepen.io/sarsparillo/pen/vNrWQG

I'm not sure why it's only loading one image at a time and putting it in the 0,0 space on my grid; 我不确定为什么为什么一次只加载一张图像并将其放在网格的0,0空间中; using very similar code in jQuery (current code, which is pretty all over the place and sort of unclean, is here - http://codepen.io/sarsparillo/pen/GpdjYY ) puts elements in the right place just fine. 在jQuery中使用非常相似的代码(当前代码,到处都是,有点不干净,在这里-http://codepen.io/sarsparillo/pen/GpdjYY )将元素放在正确的位置就可以了。

More, when I added a console.log statement to those for loops, I honestly can't work out where the hell it's getting data from. 而且,当我在for循环中添加console.log语句时,老实说,我无法弄清楚从哪里获取数据。 Like, one iteration gave me 'green green yellow' as the items in row[j], another 'blue gray blue' - does Canvas do something absolutely bizarre with iterating through an array? 就像,一次迭代给我“绿色绿色黄色”作为行[j]中的项目,另一次给我“蓝色灰色蓝色”-Canvas在遍历数组时做的事情绝对奇怪吗? I can't see how it could, seeing as this is just Javascript, but...? 我看不到它怎么可能,因为这只是Javascript,但是...?

Does anyone have any idea why this is happening, or any tips as to how I can resolve this? 有谁知道为什么会这样,或者有什么技巧可以解决这个问题? In theory, it should just be adding the space width + the margin width to the start point of each 'square', so I'm not sure why it just... isn't. 从理论上讲,它应该只是将空格宽度+边距宽度添加到每个“正方形”的起点,因此我不确定为什么……不是。

jsFiddle : https://jsfiddle.net/CanvasCode/4gr9apqm/ 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);
    }
}

All I have changed is basically how you access your 2D array and the position calculation. 我所做的更改基本上就是您访问2D数组和位置计算的方式。 Basically the first thing you access is your Y position, then from your Y position you look at all the blocks on that row. 基本上,首先要访问的是Y位置,然后从Y位置查看该行上的所有块。 So we first find "in my case" blue, 0, 0, blue, blue . 因此,我们首先找到“以我为例” blue, 0, 0, blue, blue so all of these will have y position 0, and then it will go from 0, 80, 160 and etc. However because you wanted a gap in between the blocks you also have to multiple the gap by the x and y value at that time :) 因此所有这些元素的y位置都将为0,然后从0、80、160等开始。但是,由于您想要在块之间添加一个间隙,因此您还必须将间隙乘以x和y值。 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM