Skip to content
Advertisement

Scrolling issue with Canvas style.left/top

I am making a magnifying glass for a canvas application but ive run into an issue with scrolling. Essentially the goal is to take a canvas and when an image is added (in this case a cgm image) and make a snapshot of it, scale it up and draw it on to a second smaller canvas that overlays it and follow the mouse (preferably a drag/mousedown and up, but i am using mousemove for testing purposes). I believe the issue is in the zoom.style.top & zoom.style.left NOTE on my main aplication I have a top margin of 70px so keep that in mind.

here is a quick example I wrote up

<!-- language: lang-js -->

var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var ox = canvas.width / 2;
var oy = canvas.height / 2;
ctx.font = "42px serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "blue";
ctx.fillRect(ox / 2, oy / 2, ox, oy);
function magnify() {
  var main = document.getElementById("canvas1");
  var ctx = main.getContext('2d')
  var base64 = main.toDataURL('image/png', 0);
  drawing = new Image();
  drawing.onload = () => {
    var zoom = document.getElementById("tCanvas");
    var zoomCtx = zoom.getContext('2d');
    zoomCtx.drawImage(drawing, 0, 0);
  }
  main.addEventListener("mousemove", function(e) {
    var zoom = document.getElementById("tCanvas");
    var zoomCtx = zoom.getContext('2d');

    zoomCtx.clearRect(0, 0, zoom.width, zoom.height);

    zoomCtx.drawImage(main, e.x, e.y, 200, 200, 0, 0, 300, 300);
    zoom.style.top = e.pageY - 70 + "px"
    zoom.style.left = e.pageX - 10 + "px"
    e.pageY = -150
    e.pageX = -150
    zoom.style.display = "block";
  });

  main.addEventListener("mouseleave", function() {
    var zoom = document.getElementById("tCanvas");
    zoom.style.display = "none";
  });
  drawing.src = base64;
};
<canvas id="tCanvas" class="cgm" height="100" width="100" style="background-color:white;  position: absolute; display: none; z- 
      index:1;border:1px solid red;">  </canvas>
<canvas tabindex=1 class="cgm" id="canvas1" style="position:relative;  background:white; 
      left:0;right:0;margin:auto;z-index:1;margin-top:70px;  "></canvas>
<p></p>
<button id="zoom" onclick="magnify();">Zoom</button>

Here’s a fiddle for reference (I fixed the height to display the scroll issue).

JSFiddle

Advertisement

Answer

I simplified a lot of the code on your JSFiddle.

See if this is the behavior you are looking for:

const canvas = document.getElementById("canvas1");
const ctx = canvas.getContext("2d");

const zoom = document.getElementById("tCanvas");
const zoomCtx = zoom.getContext('2d');

for (let i = 10; i < 20; i++)
  for (let j = -60; j < 800; j += 60)
    ctx.fillText(j + i, i * 20 - 180, i * 9 + j);

function getMousePos(evt) {
  var rect = canvas.getBoundingClientRect()
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  }
}

canvas.addEventListener("mousemove", function(e) {
  zoomCtx.clearRect(0, 0, zoom.width, zoom.height);
  let pos = getMousePos(e)
  zoomCtx.drawImage(canvas, pos.x, pos.y, 200, 200, 0, 0, 300, 300);
  zoom.style.top = e.pageY - 10 + "px"
  zoom.style.left = e.pageX - 10 + "px"
  zoom.style.display = "block";
});

canvas.addEventListener("mouseleave", function() {
  zoom.style.display = "none";
});
#tCanvas {
  border: 1px solid red;
  display: none;
  position: absolute;
  background-color: #808080;
  pointer-events: none;
}

#canvas1 {
  background-color: #808080;
}
<canvas id="tCanvas" width=100 height=100></canvas>
<canvas id="canvas1" width=240 height=800></canvas>

I think that your issue was with pointer-events: none; the top canvas was preventing the events from reaching the bottom canvas.

Also you don’t have to declare your document.getElementById(".. on every function, those should be global constants

For the issue with a long canvas we need to use canvas.getBoundingClientRect in the calculation to get the real position of the mouse in the canvas

Advertisement