Html5 canvas correctly draw cube

I am just testing HTML5 canvas and I am trying to draw an isometric cube correctly

Here's my current code for drawing an isometric cube:

function drawCube(x, y, wx, wy, h, color) {
    // left face
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x - wx, y - wx * 0.5);
    ctx.lineTo(x - wx, y - h - wx * 0.5);
    ctx.lineTo(x, y - h * 1);
    ctx.closePath();
    ctx.fillStyle = "#838357"
    ctx.strokeStyle = "#7a7a51";
    ctx.stroke();
    ctx.fill();

    // right face
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x + wy, y - wy * 0.5);
    ctx.lineTo(x + wy, y - h - wy * 0.5);
    ctx.lineTo(x, y - h * 1);
    ctx.closePath();
    ctx.fillStyle = "#6f6f49";
    ctx.strokeStyle = "#676744";
    ctx.stroke();
    ctx.fill();

    // center face
    ctx.beginPath();
    ctx.moveTo(x, y - h);
    ctx.lineTo(x - wx, y - h - wx * 0.5);
    ctx.lineTo(x - wx + wy, y - h - (wx * 0.5 + wy * 0.5));
    ctx.lineTo(x + wy, y - h - wy * 0.5);
    ctx.closePath();
    ctx.fillStyle = "#989865";
    ctx.strokeStyle = "#8e8e5e";
    ctx.stroke();
    ctx.fill();
}

      

I have two problems:

First edition


There's some pixel issues / faces overlapping, which you can see when you scale the canvas:

Image of the wrong cube

var canvas = document.createElement("canvas");
var ctx    = canvas.getContext('2d');

canvas.width  = 800;
canvas.height = 800;

document.body.appendChild(canvas);

 
function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  var sizeX = 32;
  var sizeY = 32;
  var sizeZ = 8; 
   
  ctx.scale(5, 5);
 
  drawCube(50, 50, sizeX, sizeY, sizeZ);
}

requestAnimationFrame(draw);


function drawCube(x, y, wx, wy, h, color) {
    // left face
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x - wx, y - wx * 0.5);
    ctx.lineTo(x - wx, y - h - wx * 0.5);
    ctx.lineTo(x, y - h * 1);
    ctx.closePath();
    ctx.fillStyle = "#838357"
    ctx.strokeStyle = "#7a7a51";
    ctx.stroke();
    ctx.fill();

    // right face
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x + wy, y - wy * 0.5);
    ctx.lineTo(x + wy, y - h - wy * 0.5);
    ctx.lineTo(x, y - h * 1);
    ctx.closePath();
    ctx.fillStyle = "#6f6f49";
    ctx.strokeStyle = "#676744";
    ctx.stroke();
    ctx.fill();

    // center face
    ctx.beginPath();
    ctx.moveTo(x, y - h);
    ctx.lineTo(x - wx, y - h - wx * 0.5);
    ctx.lineTo(x - wx + wy, y - h - (wx * 0.5 + wy * 0.5));
    ctx.lineTo(x + wy, y - h - wy * 0.5);
    ctx.closePath();
    ctx.fillStyle = "#989865";
    ctx.strokeStyle = "#8e8e5e";
    ctx.stroke();
    ctx.fill();
}
      

Run code



Second edition


How can I determine the required canvas width / height to draw the entire cube and then set the cube to the beginning of the canvas? (x and y = 0)



What am I doing wrong for the first problem? What about the second one? Can I get an example / snippet with the issues fixed?

+3


source to share


1 answer


It has to do with the miter mode for string concatenation and the miter limit.

You can solve these two ways, as before calling fill()

/ stroke()

:

Or lower the miter limit (note that the miter limit cannot be 0):

ctx.miterLimit = 1;

      

or use another line mode:



ctx.lineJoin = "round";

      

var canvas = document.createElement("canvas");
var ctx    = canvas.getContext('2d');

canvas.width  = 800;
canvas.height = 800;

document.body.appendChild(canvas);

 
function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  var sizeX = 32;
  var sizeY = 32;
  var sizeZ = 8; 
   
  ctx.scale(5, 5);
 
  drawCube(50, 50, sizeX, sizeY, sizeZ);
}

requestAnimationFrame(draw);


function drawCube(x, y, wx, wy, h, color) {

    // LINE MODE
    ctx.lineJoin = "round";
    
    // left face
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x - wx, y - wx * 0.5);
    ctx.lineTo(x - wx, y - h - wx * 0.5);
    ctx.lineTo(x, y - h * 1);
    ctx.closePath();
    ctx.fillStyle = "#838357"
    ctx.strokeStyle = "#7a7a51";
    ctx.stroke();
    ctx.fill();

    // right face
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x + wy, y - wy * 0.5);
    ctx.lineTo(x + wy, y - h - wy * 0.5);
    ctx.lineTo(x, y - h * 1);
    ctx.closePath();
    ctx.fillStyle = "#6f6f49";
    ctx.strokeStyle = "#676744";
    ctx.stroke();
    ctx.fill();

    // center face
    ctx.beginPath();
    ctx.moveTo(x, y - h);
    ctx.lineTo(x - wx, y - h - wx * 0.5);
    ctx.lineTo(x - wx + wy, y - h - (wx * 0.5 + wy * 0.5));
    ctx.lineTo(x + wy, y - h - wy * 0.5);
    ctx.closePath();
    ctx.fillStyle = "#989865";
    ctx.strokeStyle = "#8e8e5e";
    ctx.stroke();
    ctx.fill();
}
      

Run code


In the second problem, you can pre-compute all the values ​​for the cube and store them in an array or object, etc.

Then run min-max on all values ​​for each axis. The maximum value (minus minus) will be the width / height of the canvas. Place the canvas on -minX, -minY (or translate using the same).

+1


source







All Articles