0

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>
foopeen
  • 31
  • 5

2 Answers2

1

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.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Also note that not all browsers have implemented `roundRect()` yet, you may want to use a polyfill, if so [I've made one](https://github.com/Kaiido/roundRect/blob/main/roundRect.js). – Kaiido Dec 06 '22 at 09:58
  • Thank you very much for pointing that out, I appreciate it....I was actually experinting on that, but it doesn't matter if I used roundRect() or rect(), I was going to choose but I'll just let it be an rectangle event listener without having any graphics – foopeen Dec 06 '22 at 10:54
  • @foopeen to be clear, for your issue it doesn't matter that it's a roundRect or a rect, the problem is that you keep adding new path data to your Path2D object. – Kaiido Dec 06 '22 at 11:09
  • yes I got you, I deleted that line on my main project. – foopeen Dec 06 '22 at 11:16
0

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.

aptriangle
  • 1,395
  • 1
  • 9
  • 11
  • okay, I'll try and see – foopeen Dec 06 '22 at 09:22
  • cmiiw, after the `scale()`, we need to re-draw the content right? that's what I learned from w3school web – foopeen Dec 06 '22 at 11:19
  • Yes, instead of doing all of the math you are doing in all of your moveTo/lineTo operations, you can use scale and translate to move and change the size of the objects. That makes it a lot simpler to make changes later. – aptriangle Dec 06 '22 at 11:26