Home > Enterprise >  JavaScript/Canvas/MouseEvent - Re-draw(scale) stopped at some point
JavaScript/Canvas/MouseEvent - Re-draw(scale) stopped at some point

Time:12-06

I have this example here which you can try on (please click "full page" on snippet, to see what's going on), for some, there might be no problem at first try. But please, try hover around, in and out many times. At some point, the "save icon" will stopped at big size when our mouse pointer is outside the range.

So, how to get around this?

const canvasHudSave = document.getElementById('hudSave');
const contextHudSave = canvasHudSave.getContext('2d');
hudSaveClicker();

function hudSaveClicker() {
  contextHudSave.clearRect(0, 0, canvasHudSave.width, canvasHudSave.height);
  const layer1 = 70;
  const x = canvasHudSave.width / 2;
  const y = canvasHudSave.height / 2;
  const saveButton = new Path2D();
  saveButton.roundRect(15, 5, 70, 70, 15);
  //contextHudSave.fillStyle = '#cc3300';
  //contextHudSave.fill(saveButton);

  contextHudSave.beginPath();
  contextHudSave.moveTo(x - (layer1 * Math.abs(0.23 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.23 - 0.5)), y - (layer1 * Math.abs(0.41 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.70 - 0.5)), y - (layer1 * Math.abs(0.42 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.70 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
  contextHudSave.closePath();
  contextHudSave.fillStyle = '#ffffff';
  contextHudSave.fill();
  contextHudSave.beginPath();
  contextHudSave.moveTo(x - (layer1 * Math.abs(0.09 - 0.5)), y - (layer1 * Math.abs(0.16 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.18 - 0.5)), y - (layer1 * Math.abs(0.08 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.24 - 0.5)), y - (layer1 * Math.abs(0.08 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.24 - 0.5)), y - (layer1 * Math.abs(0.36 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.28 - 0.5)), y - (layer1 * Math.abs(0.40 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.65 - 0.5)), y - (layer1 * Math.abs(0.40 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.67 - 0.5)), y - (layer1 * Math.abs(0.37 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.67 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.73 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.91 - 0.5)), y - (layer1 * Math.abs(0.39 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.91 - 0.5)), y   (layer1 * Math.abs(0.84 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.86 - 0.5)), y   (layer1 * Math.abs(0.91 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.15 - 0.5)), y   (layer1 * Math.abs(0.91 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.09 - 0.5)), y   (layer1 * Math.abs(0.85 - 0.5)));
  contextHudSave.closePath();
  contextHudSave.fillStyle = '#000000';
  contextHudSave.fill();
  contextHudSave.beginPath();
  contextHudSave.moveTo(x - (layer1 * Math.abs(0.30 - 0.5)), y - (layer1 * Math.abs(0.12 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.30 - 0.5)), y - (layer1 * Math.abs(0.27 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.41 - 0.5)), y - (layer1 * Math.abs(0.27 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.41 - 0.5)), y - (layer1 * Math.abs(0.12 - 0.5)));
  contextHudSave.closePath();
  contextHudSave.fillStyle = '#000000';
  contextHudSave.fill();
  contextHudSave.beginPath();
  contextHudSave.moveTo(x - (layer1 * Math.abs(0.15 - 0.5)), y - (layer1 * Math.abs(0.47 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.18 - 0.5)), y - (layer1 * Math.abs(0.45 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.82 - 0.5)), y - (layer1 * Math.abs(0.45 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.85 - 0.5)), y - (layer1 * Math.abs(0.47 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.85 - 0.5)), y   (layer1 * Math.abs(0.81 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.82 - 0.5)), y   (layer1 * Math.abs(0.84 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.18 - 0.5)), y   (layer1 * Math.abs(0.84 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.15 - 0.5)), y   (layer1 * Math.abs(0.81 - 0.5)));
  contextHudSave.closePath();
  contextHudSave.fillStyle = '#ffffff';
  contextHudSave.fill();
  contextHudSave.beginPath();
  contextHudSave.moveTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.54 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.58 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.58 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.54 - 0.5)));
  contextHudSave.closePath();
  contextHudSave.fillStyle = '#000000';
  contextHudSave.fill();
  contextHudSave.beginPath();
  contextHudSave.moveTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.69 - 0.5)));
  contextHudSave.lineTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.73 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.73 - 0.5)));
  contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.69 - 0.5)));
  contextHudSave.closePath();
  contextHudSave.fillStyle = '#000000';
  contextHudSave.fill();

  canvasHudSave.addEventListener('mousemove', (event) => {
    // Check whether point is inside circle
    const isPointInPath = contextHudSave.isPointInPath(saveButton, event.offsetX, event.offsetY);
    let layer1 = isPointInPath ? '110' : '70';
    contextHudSave.clearRect(0, 0, canvasHudSave.width, canvasHudSave.height);
    //saveButton.roundRect(15, 5, 70, 70, 15);  <-- omit this from listener
    contextHudSave.beginPath();
    contextHudSave.moveTo(x - (layer1 * Math.abs(0.23 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.23 - 0.5)), y - (layer1 * Math.abs(0.41 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.70 - 0.5)), y - (layer1 * Math.abs(0.42 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.70 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
    contextHudSave.closePath();
    contextHudSave.fillStyle = '#ffffff';
    contextHudSave.fill();
    contextHudSave.beginPath();
    contextHudSave.moveTo(x - (layer1 * Math.abs(0.09 - 0.5)), y - (layer1 * Math.abs(0.16 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.18 - 0.5)), y - (layer1 * Math.abs(0.08 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.24 - 0.5)), y - (layer1 * Math.abs(0.08 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.24 - 0.5)), y - (layer1 * Math.abs(0.36 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.28 - 0.5)), y - (layer1 * Math.abs(0.40 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.65 - 0.5)), y - (layer1 * Math.abs(0.40 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.67 - 0.5)), y - (layer1 * Math.abs(0.37 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.67 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.73 - 0.5)), y - (layer1 * Math.abs(0.09 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.91 - 0.5)), y - (layer1 * Math.abs(0.39 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.91 - 0.5)), y   (layer1 * Math.abs(0.84 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.86 - 0.5)), y   (layer1 * Math.abs(0.91 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.15 - 0.5)), y   (layer1 * Math.abs(0.91 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.09 - 0.5)), y   (layer1 * Math.abs(0.85 - 0.5)));
    contextHudSave.closePath();
    contextHudSave.fillStyle = '#000000';
    contextHudSave.fill();
    contextHudSave.beginPath();
    contextHudSave.moveTo(x - (layer1 * Math.abs(0.30 - 0.5)), y - (layer1 * Math.abs(0.12 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.30 - 0.5)), y - (layer1 * Math.abs(0.27 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.41 - 0.5)), y - (layer1 * Math.abs(0.27 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.41 - 0.5)), y - (layer1 * Math.abs(0.12 - 0.5)));
    contextHudSave.closePath();
    contextHudSave.fillStyle = '#000000';
    contextHudSave.fill();
    contextHudSave.beginPath();
    contextHudSave.moveTo(x - (layer1 * Math.abs(0.15 - 0.5)), y - (layer1 * Math.abs(0.47 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.18 - 0.5)), y - (layer1 * Math.abs(0.45 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.82 - 0.5)), y - (layer1 * Math.abs(0.45 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.85 - 0.5)), y - (layer1 * Math.abs(0.47 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.85 - 0.5)), y   (layer1 * Math.abs(0.81 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.82 - 0.5)), y   (layer1 * Math.abs(0.84 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.18 - 0.5)), y   (layer1 * Math.abs(0.84 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.15 - 0.5)), y   (layer1 * Math.abs(0.81 - 0.5)));
    contextHudSave.closePath();
    contextHudSave.fillStyle = '#ffffff';
    contextHudSave.fill();
    contextHudSave.beginPath();
    contextHudSave.moveTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.54 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.58 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.58 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.54 - 0.5)));
    contextHudSave.closePath();
    contextHudSave.fillStyle = '#000000';
    contextHudSave.fill();
    contextHudSave.beginPath();
    contextHudSave.moveTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.69 - 0.5)));
    contextHudSave.lineTo(x - (layer1 * Math.abs(0.21 - 0.5)), y   (layer1 * Math.abs(0.73 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.73 - 0.5)));
    contextHudSave.lineTo(x   (layer1 * Math.abs(0.79 - 0.5)), y   (layer1 * Math.abs(0.69 - 0.5)));
    contextHudSave.closePath();
    contextHudSave.fillStyle = '#000000';
    contextHudSave.fill();
  });
  /*canvasHudSave.addEventListener('click', function(event) {
    // Check whether point is inside circle
    if (contextHudSave.isPointInPath(saveButton, event.offsetX, event.offsetY)) {
        saveThisBuild();
    }
  });*/
}
  * {
  margin: 0;
  padding: 0;
}

#hudSave {
  position: fixed;
  opacity: 1;
  background: transparent;
  top: 680px;
  left: 10px;
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>TEST</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <canvas id="hudSave" width="100" height="100"></canvas>
</body>

</html>
<script src="main.js"></script>

CodePudding user response:

In your mousemove event listener you are calling saveButton.roundRect(...). This will add a new roundRect() to your Path2D object, making it more complex every time this event will fire (i.e very often).

For instance, using a simpler rect() command and SVG notation, let's say at the first iteration your Path2D contained the path M30,30 H60 V60 H30 Z, at the second it will contain M30,30 H60 V60 H30 Z M30,30 H60 V60 H30 Z after a few thousands of mousemove event I let you get what it will look like.
Manipulating such a complex Path2D object becomes slow, so does hit-testing it. This is what you actually experience.

Remove that line and you should be fine.

CodePudding user response:

The reason you are seeing this problem is that you are only updating the image on the mousemove event. If the mouse is moved fast enough that the mouse movement event is not triggered while the cursor is outside your path, but still above the canvas, it will not get smaller again. There are a few ways to fix this, but you could use mouseout, like in this fiddle. Which causes your code to be called when the mouse moves over the canvas and when the mouse leaves the canvas.

  canvasHudSave.addEventListener('mousemove', mouseEvent);
  canvasHudSave.addEventListener('mouseout', mouseEvent);

On a side note, you may find it easier to use the contextHudSave.scale, which can make your image bigger or smaller, than duplicating all of the drawing code.

CodePudding user response:

Given that canvas is a canvas element or an OffscreenCanvas object, use clearRect:

const context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);
  • Related