Search code examples
javascripthtml5-canvas

Eraser completely makes the Canvas white


main.js:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let isDrawing = false;
let lastX = 0;
let lastY = 0;
const AXIS_LENGTH = 50; // Length of the axis lines
let mouseX;
let mouseY;

// history so we can always redraw
var points = []
var allPoints = []
var invertedX, invertedY

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

function startDrawing(e) {
  isDrawing = true;
  [lastX, lastY] = [canvas.width - (e.pageX - canvas.offsetLeft), canvas.height - (e.pageY - canvas.offsetTop)];
  points = []
  allPoints.push(points)
  points.push([lastX, lastY])


}

function draw(e) {
  if (!isDrawing) return;

  const x = canvas.width - (e.pageX - canvas.offsetLeft);
  const y = canvas.height - (e.pageY - canvas.offsetTop);

  [lastX, lastY] = [x, y];
  points.push([lastX, lastY])

}

function stopDrawing() {
  isDrawing = false;
}


function clearCanvas() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}

function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}

function drawAllPoints() {
  allPoints.forEach(drawPoints)

}

function drawPoints(points) {

  if (points.length) {
    ctx.save()
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 5;
    ctx.lineCap = 'round';
    ctx.beginPath();
    ctx.moveTo(points[0][0], points[0][1]);
    for (var i = 1; i < points.length; i++) {
      ctx.lineTo(points[i][0], points[i][1]);
      ctx.stroke();

    }
    ctx.restore()
  }
}

function drawEverything() {
  clearCanvas()
  drawAxis();
  drawAllPoints()

}

function drawAxis() {

  mouseX = invertedX
  mouseY = invertedY
  // Draw vertical axis line
  ctx.save()
  ctx.beginPath();
  ctx.moveTo(mouseX, mouseY - AXIS_LENGTH / 2);
  ctx.lineTo(mouseX, mouseY + AXIS_LENGTH / 2);
  ctx.stroke();

  // Draw horizontal axis line
  ctx.beginPath();
  ctx.moveTo(mouseX - AXIS_LENGTH / 2, mouseY);
  ctx.lineTo(mouseX + AXIS_LENGTH / 2, mouseY);
  ctx.stroke();
  ctx.restore()
}


canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
canvas.addEventListener('touchstart', (e) => {
  e.preventDefault();
  startDrawing(e.touches[0]);
});
canvas.addEventListener('touchmove', (e) => {
  e.preventDefault();
  draw(e.touches[0]);
});
canvas.addEventListener('touchend', stopDrawing);
window.addEventListener('resize', resizeCanvas);
document.addEventListener("mousemove", function(event) {
  const mouseX = event.clientX;
  const mouseY = event.clientY;

  invertedX = window.innerWidth - mouseX;
  invertedY = window.innerHeight - mouseY;

  drawEverything()
});

When I tried to erase the canvas by clicking the erase button, the every stroke in the canvas becomes white. I also have a cross hair thing that shows where the stroke is to be drawn. The controls are inverted. I used if else for the draw and erase. I used white color for the stroke which makes as the eraser tool. But when I click the btn and tried to drag, everything turns white but again clicking the btn makes evrything turns black.


Solution

  • Hey it's me again from Merging two canvas file

    Remember that canvas is being redrawn from the memory variable allPoints. So we will add colors to that variable. BTW, this will make it easier to save and restore the drawing since it is already represented as variable.

    Also, we were redrawing the canvas on mousemove. Lets make it right and use requestAnimationFrame

    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    
    let isDrawing = false;
    let lastX = 0;
    let lastY = 0;
    const AXIS_LENGTH = 50; // Length of the axis lines
    let mouseX;
    let mouseY;
    
    
    // history so we can always redraw
    var points = []
    var stroke = {}
    var allPoints = []
    var invertedX, invertedY
    var chosenColor = "black"
    
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    
    function startDrawing(e) {
      isDrawing = true;
      [lastX, lastY] = [canvas.width - (e.pageX - canvas.offsetLeft), canvas.height - (e.pageY - canvas.offsetTop)];
      points = []
      stroke = {
        points: points,
        color: chosenColor
      }
      allPoints.push(stroke)
      points.push([lastX, lastY])
    }
    
    
    function drawColorButtons() {
      document.querySelectorAll(".toolbar .btn").forEach(function(btn) {
        var color = btn.getAttribute("data-color")
        btn.style.backgroundColor = color
        btn.addEventListener('click', function() {
          chosenColor = color
        })
      })
    }
    drawColorButtons()
    
    function draw(e) {
      if (!isDrawing) return;
    
      const x = canvas.width - (e.pageX - canvas.offsetLeft);
      const y = canvas.height - (e.pageY - canvas.offsetTop);
    
      [lastX, lastY] = [x, y];
      points.push([lastX, lastY])
    
    }
    
    function stopDrawing() {
      isDrawing = false;
    }
    
    
    function clearCanvas() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
    
    function resizeCanvas() {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    }
    
    function drawAllPoints() {
      allPoints.forEach(drawStroke)
    
    }
    
    function drawStroke(stroke) {
      drawPoints(stroke.points, stroke.color)
    }
    
    function drawPoints(points, color) {
      if (points.length) {
        ctx.save()
        ctx.strokeStyle = color;
        ctx.lineWidth = 5;
        ctx.lineCap = 'round';
        ctx.beginPath();
        ctx.moveTo(points[0][0], points[0][1]);
        for (var i = 1; i < points.length; i++) {
          ctx.lineTo(points[i][0], points[i][1]);
          ctx.stroke();
        }
        ctx.restore()
      }
    }
    
    function drawEverything() {
      clearCanvas()
      drawAllPoints()
      drawAxis();
      requestAnimationFrame(drawEverything)
    }
    drawEverything()
    
    
    function drawAxis() {
    
      mouseX = invertedX
      mouseY = invertedY
      // Draw vertical axis line
      ctx.save()
      ctx.strokeStyle = chosenColor;
    
      ctx.beginPath();
      ctx.moveTo(mouseX, mouseY - AXIS_LENGTH / 2);
      ctx.lineTo(mouseX, mouseY + AXIS_LENGTH / 2);
      ctx.stroke();
    
      // Draw horizontal axis line
      ctx.beginPath();
      ctx.moveTo(mouseX - AXIS_LENGTH / 2, mouseY);
      ctx.lineTo(mouseX + AXIS_LENGTH / 2, mouseY);
      ctx.stroke();
      ctx.restore()
    }
    
    
    canvas.addEventListener('mousedown', startDrawing);
    canvas.addEventListener('mousemove', draw);
    canvas.addEventListener('mouseup', stopDrawing);
    canvas.addEventListener('mouseout', stopDrawing);
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault();
      startDrawing(e.touches[0]);
    });
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault();
      draw(e.touches[0]);
    });
    canvas.addEventListener('touchend', stopDrawing);
    window.addEventListener('resize', resizeCanvas);
    document.addEventListener("mousemove", function(event) {
      const mouseX = event.clientX;
      const mouseY = event.clientY;
    
      invertedX = window.innerWidth - mouseX;
      invertedY = window.innerHeight - mouseY;
    
    });
    body {
      padding: 0;
      margin: 0;
      overflow: hidden;
    }
    
    canvas {
      background: gray;
      display: block;
    }
    
    .toolbar {
      position: absolute;
      z-index: 1;
      top: 20px;
      left: 20px;
      display: flex;
    }
    
    .btn {
      width: 20px;
      height: 20px;
      border: 1px solid black;
      margin-right: 2px;
      cursor: pointer;
    }
    <canvas id="canvas"></canvas>
    <div class="toolbar">
      <div class="btn" data-color="black"></div>
      <div class="btn" data-color="white"></div>
      <div class="btn" data-color="gray"></div>
      <div class="btn" data-color="red"></div>
      <div class="btn" data-color="green"></div>
      <div class="btn" data-color="yellow"></div>
      <div class="btn" data-color="blue"></div>
    </div>