New Drawbox with Canvas

by Spencer Smith

HTML

<div class="artboard">
	<canvas height="600" width="600"></canvas>
	<div class="overlay"></div>
</div>

CSS

* {
  margin: 0;
}

body {
  background-color: #282828;
  text-align: center;
}

canvas {
  height: 600px;
  width: 600px;
  background-color: whitesmoke;
  margin: 0 auto;
  display: block;
  margin-top: calc(50vh - 300px);
  cursor: crosshair;
}
.overlay {
    height: 100%;
    width: 100%;
    margin-top: -600px;
    //background-color: lightgreen;
    position: absolute;
    left: calc(50vw - 300px);
}
.overlay div{
	width: calc(100% / 20);
	height: calc(100% / 20);
	float: left;
	box-sizing: border-box;
}
.overlay div:hover{
	border: 4px solid lightgray;
}

JavaScript

// Make a container and have the canvas and the overlay inside
// It might help the pixel glitch if the width and height are 100%

var canvas = document.getElementsByTagName("canvas")[0];
var $canvas = $(canvas);
var ctx = canvas.getContext('2d');

var w = 30;
var h = w;

var state = [];
for (var i = 0; i < (20 * 20); i++) {
  state.push(0);
}

// Create hover overlay grid
var $overlay = $(".overlay");
for(var i = 0; i < 400; i++){
	$overlay.append("<div></div>");
}

function mouseIndex(e) {
  var rect = canvas.getBoundingClientRect();
  var pos = {
    x: e.clientX - rect.left,
    y: e.clientY - rect.top
  };
  pos.x = Math.ceil(pos.x / 30) - 1;
  pos.y = Math.ceil(pos.y / 30) - 1;
  var index = (pos.y * 20) + pos.x;
  return index;
}

function toggleState(index) {
  var current = state[index];
  switch (current) {
    case 0:
      state[index] = 1;
      break;
    case 1:
      state[index] = 2;
      break;
    default:
      state[index] = 0;
  }
  //console.log(state);
  redraw();
}

function redraw() {
  for (var i = 0; i < state.length; i++) {
    var pos = getPosition(i);
    var currentState = state[i];
    switch (currentState) {
      case 1:
        ctx.fillStyle = "black";
        ctx.rect(pos.x, pos.y, w, h);
        ctx.fill();
        break;
      case 2:
        ctx.fillStyle = "crimson";
        ctx.rect(pos.x, pos.y, w, h);
        ctx.fill();
        break;
      default:
        ctx.clearRect(pos.x, pos.y, w, h);
        ctx.fill();
        break;
    }
    ctx.closePath();
    ctx.beginPath();
  }
}

function getPosition(index) {
  var x = index % 20 * 30;
  var y = (Math.ceil((index + 1) / 20) - 1) * 30;
  return {
    x: x,
    y: y
  }
}

$('.artboard').click(function(e) {
  var index = mouseIndex(e);
  console.log(index);
  toggleState(index);
});