shithub: puzzles

Download patch

ref: 27f0dafcf0d78b286ccc7812c59fbc5d3e95ebe5
parent: 4feb5fdf0cc6c9612e2928f1e2a2335fbbd03a71
author: Ben Harris <bjh21@bjh21.me.uk>
date: Thu Oct 6 06:11:32 EDT 2022

js: Map mouse co-ordinates correctly even when CSS scales our canvas

Our system for mapping mouse coordinates to canvas coordinates assumed
that the puzzle canvas had the same dimensions in CSS as its own
internal width and height.  This is true in the current wrapper HTML,
but it's very easy to accidentally change and there are circumstances
where we might want to deliberately change it in future.

To fix this, we now inspect the CSS size of the canvas when processing
mouse events, and map the coordinates through the scaling and
translation necessary to convert CSS pixels into canvas pixels.

--- a/emccpre.js
+++ b/emccpre.js
@@ -166,6 +166,21 @@
             y: event.pageY - ecoords.y};
 }
 
+// Higher-level mouse helper function to specifically map mouse
+// coordinates into the coordinates on a canvas that appear under it.
+// This depends on the details of how a canvas gets scaled by CSS.
+function canvas_mouse_coords(event, element) {
+    var rcoords = relative_mouse_coords(event, element);
+    // Assume that the canvas is as large as possible within its CSS
+    // box without changing its aspect ratio.
+    var scale = Math.max(element.width / element.offsetWidth,
+			 element.height / element.offsetHeight);
+    var xoffset = (element.offsetWidth - element.width / scale) / 2;
+    var yoffset = (element.offsetHeight - element.height / scale) / 2;
+    return {x: (rcoords.x - xoffset) * scale,
+	    y: (rcoords.y - yoffset) * scale}
+}
+
 // Enable and disable items in the CSS menus.
 function disable_menu_item(item, disabledFlag) {
     if (disabledFlag)
@@ -255,7 +270,7 @@
         if (event.button >= 3)
             return;
 
-        var xy = relative_mouse_coords(event, onscreen_canvas);
+        var xy = canvas_mouse_coords(event, onscreen_canvas);
         var logbutton = event.button;
         if (event.shiftKey)
             logbutton = 1;   // Shift-click overrides to middle button
@@ -272,7 +287,7 @@
     onscreen_canvas.onmousemove = function(event) {
         var down = buttons_down();
         if (down) {
-            var xy = relative_mouse_coords(event, onscreen_canvas);
+            var xy = canvas_mouse_coords(event, onscreen_canvas);
             mousemove(xy.x, xy.y, down);
         }
     };
@@ -283,7 +298,7 @@
             return;
 
         if (button_phys2log[event.button] !== null) {
-            var xy = relative_mouse_coords(event, onscreen_canvas);
+            var xy = canvas_mouse_coords(event, onscreen_canvas);
             mouseup(xy.x, xy.y, button_phys2log[event.button]);
             button_phys2log[event.button] = null;
         }