Dalomo
Dalomo

Reputation: 33

drawing 2d objects using coordinates in a grid JavaScript

I have 2 functions, the first function draws a lined empty grid (28x16) and the second function draws a square box that fills a selected grid location with a colour, each box is 25X25. the 2nd function allows me to draw a box anywhere in the canvas using the grid location. hence, to draw a box I created another function that calls the grid locations and draw it there, for example to draw a box in the grid location where x=5 and y=4 this line must be entered drawWalls(5,4); this line can be used again and again to draw different boxes, so I can draw the boxes and the function works perfect, now I want to create more than 1 square box at the same time (for example a line of boxes), the problem is, I have never created a loop like this or a loop that has more than 1 variable, please help, also I am getting a little confused with arrays, I want to know if these boxes are stored in an array and how can I call them again, say for example I click on a box and it gets deleted, this is not important but if you have any ideas on the first problem then please help, thank you for your time.

draw grid

function drawGrid() {
    ctxBg.beginPath();
    for (var i = 0; i <= canvasWidth-25; i+= 25) {
        ctxBg.moveTo(-25 + i,55);
        ctxBg.lineTo(-25 + i, canvasHeight - 55);
    }
    for (var i = 25; i <= canvasHeight -75; i+= 25) {
        ctxBg.moveTo(55,25 + i);
        ctxBg.lineTo(canvasWidth-55, 25 + i);
    }
    ctxBg.stroke();
}

function ClearBg() {
    ctxBg.clearRect(0,0,canvasWidth,canvasHeight);
}    

Draw the wall

function Wall(row, col) {
  this.row = row;
  this.col = col;
  this.color = "#000";

  this.width = 25
  this.height = 25
  this.leftX = this.row;
  this.rightX = this.row + this.width;
  this.topY = this.col;
  this.bottomY = this.col + this.height;
}
function drawWalls(x,y) {
  walls.push( new Wall(x, y));

  for (var b = 0; b < walls.length; b++) {
    ctxWall.fillStyle = walls[b].color;
    ctxWall.fillRect(walls[b].row * gridSize, walls[b].col * gridSize, walls[b].width, walls[b].height);
  }
}

function createWalls() {
  drawWalls(9,9);
  drawWalls(8,8); 
  drawWalls(7,7);
}

I am trying to make the function createWalls in a loop to draw them all together, unfortunately I still haven't created the mouse click event, but I will soon

Upvotes: 1

Views: 2122

Answers (2)

Muhammad Umer
Muhammad Umer

Reputation: 18097

This was a fun thing to do: http://jsfiddle.net/techsin/rcjouqkf/

To get any 'box/cell' coordinates all you have to do is this:

  1. get x position of the click divide it by size of a box so you know
  2. which box you are at the round it to next whole number, which
  3. represent the box you are at. then times that number with the box size. this gives you box's right edge repeat for y to get bottom edge.

    to get top and left just subtract the size from edges.

    var can = getById('can'),
        boxes = 20,
        size = 20,
        ctx = can.getContext('2d'),
        clearBtn = getById('clearBtn');
    
    drawGrid();
    
    function drawGrid() {
        var len = can.height = can.width = boxes * size;
        for (var i = 0; i < boxes; i++) {
            ctx.beginPath();
            ctx.moveTo(size + size * i - .5, 0);
            ctx.lineTo(size + size * i - .5, len);
            ctx.moveTo(0, size + size * i - .5);
            ctx.lineTo(len, size + size * i - .5);
            ctx.stroke();
        }
    }
    
    
    can.addEventListener('mousemove', function (evt) {
        var mousePos = getMousePos(can, evt);
        var sx = (Math.ceil(mousePos.x/size)-1)*size,
            sy =  (Math.ceil(mousePos.y/size)-1)*size;
        console.log(sx,sy,sx+size,sy+size);
        ctx.fillRect(sx,sy,size,size);
    }, false);
    
    clearBtn.addEventListener('click', function (evt) {
        ctx.clearRect(0,0,can.width,can.height);
        drawGrid();
    });
    
    
    function getMousePos(canvas, evt) {
        var rect = can.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };
    }
    
    function getById(x) {
        return document.getElementById(x);
    }
    

Upvotes: 5

markE
markE

Reputation: 105015

Put the definitions of your walls in javascript objects and store those wall-objects in an array. Then use the array to draw your walls as necessary.

Each wall-object holds the information required to draw one wall:

var walls=[
    {direction:'horizontal',startX:4,endX:6,Y:3,fill:'skyblue'},
    {direction:'vertical',startY:2,endY:6,X:1,fill:'lightgreen'}
];

Then you can loop through the array and draw each wall based on each wall-object:

var cellSize=25;

function drawAllWalls(walls){
    for(var i=0;i<walls.length;i++){
        var w=walls[i];
        ctxWall.fillStyle=w.fill;
        if(w.direction=='horizontal'){
            for(var x=w.startX;x<=w.endX;x++){
                ctxWall.fillRect(x*cellSize,w.Y*cellSize,cellSize,cellSize)
            }
        }else{
            for(var y=w.startY;y<=w.endY;y++){
                ctxWall.fillRect(w.X*cellSize,y*cellSize,cellSize,cellSize)
            }
        }
    }
}

If you later want to delete a particular wall you can:

  • Delete that wall from the walls-array.
  • Clear the canvas,
  • Redraw all remaining walls in the array (the deleted wall will not be redrawn).

If you later want to delete just 1 box from a wall, you can:

  • Delete that wall from the walls-array.
  • Add back the part(s) of the wall that still exist to the walls array,
  • Clear the canvas,
  • Redraw all walls in the array (the deleted box will not be redrawn).

Here's example code and a Demo:

enter image description here

var canvas=document.getElementById("canvas");
var ctxBg=canvas.getContext("2d");
var ctxWall=canvas.getContext("2d");
var canvasWidth=canvas.width;
var canvasHeight=canvas.height;

var colCount=8;
var rowCount=8;
var cellSize=25;

var walls=[
  {direction:'horizontal',startX:4,endX:6,Y:3,fill:'skyblue'},
  {direction:'vertical',startY:2,endY:6,X:1,fill:'lightgreen'}
];

drawGrid();
drawAllWalls(walls);

function drawAllWalls(walls){
  for(var i=0;i<walls.length;i++){
    var w=walls[i];
    ctxWall.fillStyle=w.fill;
    if(w.direction=='horizontal'){
      for(var x=w.startX;x<=w.endX;x++){
        ctxWall.fillRect(x*cellSize,w.Y*cellSize,cellSize,cellSize)
      }
    }else{
      for(var y=w.startY;y<=w.endY;y++){
        ctxWall.fillRect(w.X*cellSize,y*cellSize,cellSize,cellSize)
      }
    }
  }
}

function drawGrid(){
  ctxBg.beginPath();
  for(var x=0;x<colCount+1;x++){
    ctxBg.moveTo(x*cellSize,0);
    ctxBg.lineTo(x*cellSize,rowCount*cellSize);
  }
  for(var y=0;y<rowCount+1;y++){
    ctxBg.moveTo(0,y*cellSize,0);
    ctxBg.lineTo(colCount*cellSize,y*cellSize);
  }
  ctxBg.stroke();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>

Upvotes: 3

Related Questions