Firing Mouseout Event depends on Window Size

858 Views Asked by At

I want to draw on a 3D-transformed canvas, but have some weird problems with the mouseout event in Chrome.

When I set the JSFiddle window size to 2100px, the mouseout event works as excepted.

enter image description here

However, when I set the window size to 1900px, the mouse event triggers approximately at the red line.

enter image description here

This is really weird, since the JSFiddle window size determines if the mouse out event is triggered correctly.

Until here the mouse out event is triggered correctly in Firefox and Edge, but doesn't work correctly in Chrome! In addition, we saw some weird behaviour when playing around with the scrolling position (e.g. by adding some <br>'s and scrolling affects the mouse out event position), window sizes (see images above) or the width of the canvas (e.g. setting the canvas width to 200 triggers the mouse out event correctly).

Is there anyone who can help me solving this bug, such that the browser fires the mouseout event correctly independent of the window size or scroll position?

Code: JSFiddle

Demo: YouTube

Snippet of code in fiddle:

$(".dynamic-drawing-canvas").on("mouseout", function(e) {
  console.log(e.clientX, e.clientY)
})
#container {
  pointer-events: none;
  margin-left: 400px;
}

.dynamic-drawing-canvas {
  pointer-events: auto;
  background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
  <canvas class="dynamic-drawing-canvas" width="1200" height="300" style="
    transform: matrix3d(1.0303, 0.00317459, 0, 2.13211e-05, -0.68458, -0.165542, 0, -0.00111181, 0, 0, 1, 0, -34.7412, 264.118, 0, 1);
    transform-origin: left top;
"></canvas>
</div>

1

There are 1 best solutions below

2
Mark Schultheiss On

It looks like you are running into an issue with the container of the canvas.

Some notes on what is happening: The canvas is generated at 1200px and 300px for width/height using the properties in the markup: width="1200" height="300" You can override this in the <canvas> tag directly or with JavaScript. Why CSS resize has issues: What the CSS does is to resize the existing canvas to a new size. When a typical/most HTML component is resized the browser handles this fine. The difference is <canvas> is a collection of pixels. When you change with CSS these pixels become altered (stretched out or shrink down) and the image on the canvas gets a different look. Note also that the blank canvas is also stretched so drawing to it has challenges and might/does not work as expected.

Here I adjust your canvas to fit the container using JavaScript on these properties but really only for an example - your size will vary.

I added some borders so you can see things - I put some logs in place to show where it changes and the mouseout fires since it now fits inside the container - I scaled it to fit using the 1.1 and moved the style to the CSS so I could add comments from before to after.

console.clear();
let canvas = document.getElementById("c");

let width = canvas.width;
let height = canvas.height;
console.log("CW:", width, "CH:", height);
let rect = canvas.parentNode.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;

width = canvas.width;
height = canvas.height;
let r = canvas.getBoundingClientRect();
let ctop = r.top;
let cleft = r.left;
console.log("T:", ctop, "L:", cleft, "W:", width, "H:", height);
$(".dynamic-drawing-canvas")
  .on("mouseout", function(e) {
    // console.log(e.clientX, e.clientY);
    console.log("Screen X/Y:", e.screenX, e.screenY, "Client X/Y:", e.clientX, e.clientY);
    console.log("X:", e.screenX - e.clientX);
    console.log("Y:", e.screenY - e.clientY);
  });
#container {
  pointer-events: none;
  position: absolute;
  top: 0;
  left: 0;
  margin-left: 0px;
  width: 90%;
  height: 100%;
  border: solid red 3px;
}

.dynamic-drawing-canvas {
  pointer-events: auto;
  background-color: blue;
  object-fit: none;
  object-position: top left;
  transform-origin: left top;
  /* pulled out of markup, alter for 2.13211e-5 */
  /*
  transform: matrix3d(
  1.0303, 0.00317459, 0, 0.0000213211,
  -0.68458, -0.165542, 0, -0.00111181,
  0, 0, 1, 0,
  -34.7412, 264.118, 0, 1
  ); 
  THEN adjusted the 
      following transformations:
         0, 30, 0, 1.1
        Translates every X point by 0px
        Translates every Y point by 30px
        Translates every Z point by 0
        Scales down by 10%
*/
  transform: matrix3d(1.0303, 0.00317459, 0, 0.0000213211, 0.68458, 0.165542, 0, 0.00111181, 0, 0, 1, 0, 0, 30, 0, 1.1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
  <canvas id="c" class="dynamic-drawing-canvas" width="1200" height="300"></canvas>
</div>