0

I want an HTML canvas that displays mouse position on its JS grid on mouse move, but I can't seem to clear my canvas, I tried using ctx.clearRect(0,0 canvas.width, canvas.height) and clearing with a click, but it somehow remembers the previous draw it had. I want only one black square to be displayed on canvas at a time depending on the mouse position. Heres demo on code pen and some code

<canvas id="myMap" style="width: 300px;height: 300px;background-color: beige;"></canvas>
<script>
  var findDivisible = (x, scale) => {
    while (x % scale !== 0 && x > 0) {
      x = x - 1;
    };
    return x
  };

  var map = document.getElementById("myMap");
  map.width = 300;
  map.height = 300;
  var mapContext = document.getElementById("myMap").getContext("2d");
  map.addEventListener("mousemove", function(e) {
    mapContext.clearRect(0, 0, map.width, map.height);
    mapContext.rect(findDivisible(e.clientX - map.offsetLeft, 50), findDivisible(e.pageY - map.offsetTop, 50), 50, 50);
    mapContext.stroke();

  });
  map.addEventListener("click", function() {
    mapContext.clearRect(0, 0, 500, 500);
  })
</script>
Nazim Kerimbekov
  • 4,712
  • 8
  • 34
  • 58
Sanchez Panza
  • 381
  • 1
  • 11

2 Answers2

2

You're not starting a new stroke for each rectangle, but "piling them up" so they get re-re-redrawn with .stroke().

Use .beginPath():

function findDivisible(x, scale) {
  while (x % scale !== 0 && x > 0) {
    x = x - 1;
  }
  return x;
}

var map = document.getElementById("myMap");
map.width = 300;
map.height = 300;
var mapContext = map.getContext("2d");
map.addEventListener("mousemove", function(e) {
  mapContext.clearRect(0, 0, map.width, map.height);
  mapContext.beginPath();
  mapContext.rect(
    findDivisible(e.clientX - map.offsetLeft, 50),
    findDivisible(e.pageY - map.offsetTop, 50),
    50,
    50,
  );
  mapContext.stroke();
});
map.addEventListener("click", function() {
  mapContext.clearRect(0, 0, 500, 500);
});
<canvas id="myMap" style="width: 300px;height: 300px;background-color: beige;"></canvas>
AKX
  • 152,115
  • 15
  • 115
  • 172
1

You can try this:

map.addEventListener("mousemove", function(e){              
  map.width = map.width;
  mapContext.rect(findDivisible(e.clientX-map.offsetLeft,50) , findDivisible(e.pageY - map.offsetTop,50), 50, 50);
  mapContext.stroke();              
});

map.addEventListener("click", function(){
  map.width = map.width;
});

One of the ways that is implicitly endorsed in the spec and often used in people’s apps to clear a canvas https://dzone.com/articles/how-you-clear-your-html5

ontimond
  • 376
  • 1
  • 2
  • 6
  • 1
    If `ctx.clearRect` doesn't work, it's unlikely an old method of doing the same thing (re-setting the width) will make any difference. – DBS May 07 '19 at 14:20
  • @DBS and still, that would. This does reset the whole context, including the current sub-path declaration along with **all** the context's settable options, and its underlying ImageData (i.e a lot of garbage to collect). That's why one should never use this hack. – Kaiido May 07 '19 at 23:31