-2

I have one canvas element that when positioned with css, fails to register mouse clicks and move elements drawn within canvas. If you do not position the canvas the mouse clicks register and selected elements will get moved but I need to be able to position this canvas layer with left and top so I can put another canvas underneath yet retain my mouse click and move ability.

This is what I am using to get my x/y click coordinates

 var br = canvas.getBoundingClientRect(); //bounding rectangle
 var mousex = parseInt(e.clientX-br.left);
 var mousey = parseInt(e.clientY-br.top);

I have changed clientX and clientY to use pageX and pageY as others have suggested but the issue still remains, even if I place the canvas in another div and position accordingly. I've also subtracted the amount I'm moving the container over from mousex but without success. Even positioning with flex breaks the functionality.

Is this simply a limitation of canvas?

** Clarification, if it wasn't clear before, as detecting the mouse click is NOT the issue, the issue is when I position the canvas inside the DOM, the clicks are no longer registered. **

VanCoon
  • 422
  • 4
  • 20
  • Possible duplicate of [How do I get the coordinates of a mouse click on a canvas element?](https://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element) – zero298 Dec 13 '18 at 21:25
  • 1
    Can you create a reproducible example using a Stack Snippet in your question? It's difficult to understand what the issue is without a concrete example. – zero298 Dec 13 '18 at 21:30
  • I added an example below and more details. – VanCoon Dec 14 '18 at 10:11
  • Please don't add it below, add it in your actual question. You have posted an edit as an answer. – zero298 Dec 14 '18 at 15:05

2 Answers2

0

You can do it using offsetLeft and offsetTop. Here is a demo:

var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    targetPos = {x: 150, y: 50};

// Initial render
render();
// Whenever the user clicks on the canvas, update the position
canvas.addEventListener('click', updateTargetPos);

function updateTargetPos(e) {
  targetPos = {
    x: e.pageX - canvas.offsetLeft,
    y: e.pageY - canvas.offsetTop
  };
  render();
}

function render() {
  renderBackground();
  renderTarget();
}

function renderBackground() {
  ctx.fillStyle = "#333";
  ctx.fillRect(0, 0, 300, 200);
}

function renderTarget() {
  var size = 10;
  ctx.fillStyle = "#f00";
  ctx.fillRect(targetPos.x - size/2, targetPos.y - size/2, size, size);
}
body {
  font-family: Arial, Helvetica, sans-serif;
}
#canvas {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -50px;
  margin-left: -150px;
}
<p>Click on this absolutely positioned canvas:</p>
<canvas id="canvas" width="300" height="100"></canvas>
blex
  • 24,941
  • 5
  • 39
  • 72
0

I was editing this in devtools on the fly which was causing issues with canvas and being able to get the correct x/y of the mouse click. When I would adjust positioning in dev tools then attempt to move the square it would not work. Modifying my stylesheet prior to loading into the dom in this instance yielded the correct result as the calculations would need to be run again after manipulating the canvas positioning.

For those that needed a visual, here is some code. To replicate the problem you can try to add justify-content: center to the .flex class then attempt to move the green square to see that you can't move the square, or rather the spot that is defined to be clickable is not located over the box.

var canvas = document.getElementById("canvasArea");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctx2 = canvas2.getContext("2d");

var x = canvas.width/2;
var y = canvas.height-10;
 
var dx = 2;
var dy = -2;
 
var boundingRectangle = canvas.getBoundingClientRect();
var moveBox = false; 
var selectedBox;
 
function box(x, y) {
  this.color = "green";
  this.xPos = x;
  this.yPos = y;
  this.width = 50;
  this.height = 50;
}

box.prototype.drawBox = function() {
  ctx.fillStyle = this.color;
  ctx.fillRect(this.xPos, this.yPos, this.width, this.height);
};

var abox = new box(x, 30);


canvas.addEventListener("mousedown", function(e) {
 e.preventDefault();
 e.stopPropagation();
 
 var mousex = parseInt(e.clientX-boundingRectangle.left);
  var mousey = parseInt(e.clientY-boundingRectangle.top);
 
 if(mousex > abox.xPos && mousex < abox.xPos + abox.width && mousey > abox.yPos && mousey < abox.yPos + abox.height) {
  moveBox = true;
  selectedBox = "abox"
 }

}, true);



canvas.addEventListener("mousemove", function(e) {
 e.preventDefault();
 e.stopPropagation();
  if(moveBox) {
   if(selectedBox == "abox") {
   abox.xPos = e.offsetX;
   abox.yPos = e.offsetY;
  } 
 }
})


canvas.addEventListener("mouseup", function(e) {
 e.preventDefault();
 e.stopPropagation();
 moveBox = false;
})
 

function bg(ctx2) {
      var alpha = ctx2.globalAlpha;
     
        ctx2.save();
      ctx2.beginPath();
      ctx2.moveTo(142.5, 23.7);
      ctx2.lineTo(85.9, 0.0);
      ctx2.lineTo(0.0, 204.8);
      ctx2.lineTo(56.6, 228.5);
      ctx2.lineTo(142.5, 23.7);
      ctx2.closePath();
      ctx2.fillStyle = "rgb(31, 155, 215)";
      ctx2.fill();

     
      ctx2.beginPath();
      ctx2.moveTo(235.1, 23.7);
      ctx2.lineTo(178.5, 0.0);
      ctx2.lineTo(92.6, 204.8);
      ctx2.lineTo(149.2, 228.5);
      ctx2.lineTo(235.1, 23.7);
      ctx2.closePath();
      ctx2.fillStyle = "rgb(77, 75, 159)";
      ctx2.fill();

  
      ctx2.beginPath();
      ctx2.moveTo(330.5, 23.7);
      ctx2.lineTo(273.9, 0.0);
      ctx2.lineTo(188.0, 204.8);
      ctx2.lineTo(244.6, 228.5);
      ctx2.lineTo(330.5, 23.7);
      ctx2.closePath();
      ctx2.fillStyle = "rgb(176, 67, 152)";
      ctx2.fill();

      ctx2.beginPath();
      ctx2.moveTo(435.4, 23.7);
      ctx2.lineTo(378.8, 0.0);
      ctx2.lineTo(292.9, 204.8);
      ctx2.lineTo(349.5, 228.5);
      ctx2.lineTo(435.4, 23.7);
      ctx2.closePath();
      ctx2.fillStyle = "rgb(69, 174, 77)";
      ctx2.fill();


      ctx2.beginPath();
      ctx2.moveTo(541.4, 23.7);
      ctx2.lineTo(484.7, 0.0);
      ctx2.lineTo(398.9, 204.8);
      ctx2.lineTo(455.5, 228.5);
      ctx2.lineTo(541.4, 23.7);
      ctx2.closePath();
      ctx2.fillStyle = "rgb(237, 127, 34)";
      ctx2.fill();
      ctx2.restore();
}


function render() {
 requestAnimationFrame(render);
 ctx.clearRect(0, 0, canvas.width, canvas.height);
  abox.drawBox();
}
render(); 
bg(ctx2)
.flex {
    width: 100%;
    height: 100%;
    display: flex;
}
canvas#canvasArea {
  position: absolute;
  display: inline-block;
}
.container {
  position: relative;
  left: 150px;
 top: -20px;
 z-index: 999999;
}
 
.container {
  position: relative;
}
.canvasbg {
  position: absolute;
  width: 200px;
  height: 150px;
  margin: 20px 0;
  border: none;
  background: #000000;
}
<div class="flex">
<div class="container">
  <div class="canvasbg">
      <canvas id="canvasArea" width="220" height="150">
    Your browser does not support HTML5 canvas.
  </canvas>    
  </div>
</div>
<canvas id="canvas2" width="540" height="177"></canvas>
VanCoon
  • 422
  • 4
  • 20