Vishwa Iyer
Vishwa Iyer

Reputation: 861

Render grid on HTML5 Canvas

I am trying to render a grid on a HTML5 canvas, but I want anything that the user draws on the canvas to be placed behind the grid. I tried to recreate this by having 2 canvas: one with the grid, and the other the one that the user draws on. The one with the grid is placing on top of the canvas the user draws on, and the canvas should be transparent but it's not showing anything the user draws. If I place the canvas the user draws on at the top, then you can see what the user draws, but the drawing is in front of the grid, and i want the drawing behind the grid.

You can view what I have tried here: http://codepen.io/vishiswoz/pen/grqMyG

function buildGrids(gridPixelSize, color, gap, div) {
  var canvas = $('#' + div + '').get(0);
  var ctx = canvas.getContext("2d");
  //ctx.fillStyle="rgba(255, 255, 255, 0)";
  //ctx.fillRect(0, 0, 500, 300);
  ctx.lineWidth = 0.5;
  ctx.strokeStyle = color;

  // horizontal grid lines
  for (var i = 0; i <= canvas.height; i = i + gridPixelSize) {
    ctx.beginPath();
    ctx.moveTo(0, i);
    ctx.lineTo(canvas.width, i);
    if (i % parseInt(gap) == 0) {
      ctx.lineWidth = 0.5;
    } else {
      ctx.lineWidth = 0.5;
    }
    ctx.closePath();
    ctx.stroke();
  }

  // vertical grid lines
  for (var j = 0; j <= canvas.width; j = j + gridPixelSize) {
    ctx.beginPath();
    ctx.moveTo(j, 0);
    ctx.lineTo(j, canvas.height);
    if (j % parseInt(gap) == 0) {
      ctx.lineWidth = 0.5;
    } else {
      ctx.lineWidth = 0.5;
    }
    ctx.closePath();
    ctx.stroke();
  }
  
  for(var ii = 0; ii <=canvas.width; ii+=2) {
    for(var jj=0; jj <=canvas.height; jj+=2) {
      ctx.clearRect(ii,jj,1,1);
    }
  }
}
buildGrids(5, "grey", 2, "test");

var el = document.getElementById('c');
var ctx = el.getContext('2d');
ctx.strokeStyle = "black";
var isDrawing;

el.onmousedown = function(e) {
  isDrawing = true;
  ctx.lineWidth = 10;
  ctx.lineJoin = ctx.lineCap = 'round';
  ctx.moveTo(e.clientX, e.clientY);
};
el.onmousemove = function(e) {
  if (isDrawing) {
    ctx.lineTo(e.clientX, e.clientY);
    ctx.stroke();
  }
};
el.onmouseup = function() {
  isDrawing = false;
};
canvas { 
    position: absolute;
    top: 0;
    left: 0;
}

#c {
  
}
<canvas id="c" width="500" height="300"></canvas>
<canvas id="test" width="500" height="300"></canvas>

Thanks in advance.

Upvotes: 0

Views: 1899

Answers (1)

markE
markE

Reputation: 105035

Drawing on a bottom canvas covered by a top grid canvas

enter image description here

Just listen for mouse events on the top grid-canvas but draw on the drawing canvas.

var gridCanvas=document.getElementById('test');

gridCanvas.onmousedown = function(e) {
  isDrawing = true;
  ctx.lineWidth = 10;
  ctx.lineJoin = ctx.lineCap = 'round';
  ctx.moveTo(e.clientX, e.clientY);
};

A couple of other issues

  • A matter of style: On mousemove, draw a complete line segment rather than just continuing an "open" path. You can do this by remembering the lastX,lastY and drawing a segment between that last point and the current mouse position.
  • If the mouse goes out of the canvas you should end the drawing operation. Otherwise you will end up with a "sticky" drawing where the user can't easily stop the drawing.

Here's your code slightly refactored to include the above ideas:

var gridCanvas = document.getElementById('grid');
var el = document.getElementById('drawing');

        function reOffset(){
            var BB=el.getBoundingClientRect();
            offsetX=BB.left;
            offsetY=BB.top;        
        }
        var offsetX,offsetY;
        reOffset();
        window.onscroll=function(e){ reOffset(); }
        window.onresize=function(e){ reOffset(); }

buildGrids(5, "grey", 2, "test");

var ctx = el.getContext('2d');
ctx.strokeStyle = "orange";
var isDrawing,lastX,lastY;

gridCanvas.onmousedown = function(e) {
  lastX=e.clientX;
  lastY=e.clientY;
  ctx.lineWidth = 10;
  ctx.lineJoin = ctx.lineCap = 'round';
  isDrawing = true;
};
gridCanvas.onmousemove = function(e) {
  if (isDrawing) {
    ctx.beginPath();
    ctx.moveTo(lastX,lastY);
    ctx.lineTo(e.clientX, e.clientY);
    ctx.stroke();
    lastX=e.clientX;
    lastY=e.clientY;
  }
};
gridCanvas.onmouseup = function() {
  isDrawing = false;
};gridCanvas.onmouseout = function() {
  isDrawing = false;
};


function buildGrids(gridPixelSize, color, gap, div) {
  var ctx = gridCanvas.getContext("2d");
  //ctx.fillStyle="rgba(255, 255, 255, 0)";
  //ctx.fillRect(0, 0, 500, 300);
  ctx.lineWidth = 0.5;
  ctx.strokeStyle = color;

  // horizontal grid lines
  for (var i = 0; i <= gridCanvas.height; i = i + gridPixelSize) {
    ctx.beginPath();
    ctx.moveTo(0, i);
    ctx.lineTo(gridCanvas.width, i);
    if (i % parseInt(gap) == 0) {
      ctx.lineWidth = 0.5;
    } else {
      ctx.lineWidth = 0.5;
    }
    ctx.closePath();
    ctx.stroke();
  }

  // vertical grid lines
  for (var j = 0; j <= gridCanvas.width; j = j + gridPixelSize) {
    ctx.beginPath();
    ctx.moveTo(j, 0);
    ctx.lineTo(j, gridCanvas.height);
    if (j % parseInt(gap) == 0) {
      ctx.lineWidth = 0.5;
    } else {
      ctx.lineWidth = 0.5;
    }
    ctx.closePath();
    ctx.stroke();
  }
  
  for(var ii = 0; ii <=gridCanvas.width; ii+=2) {
    for(var jj=0; jj <=gridCanvas.height; jj+=2) {
      ctx.clearRect(ii,jj,1,1);
    }
  }
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
canvas{ position: absolute; top: 0; left: 0;}
<canvas id="drawing" width="500" height="300"></canvas>
<canvas id="grid" width="500" height="300"></canvas>

Upvotes: 3

Related Questions