matchifang
matchifang

Reputation: 5450

Incorrect mouse position on HTML canvas when having a navigation bar

The position of mouse clicks on canvas is correct when I do not have a navigation bar. However, it shifted when I added a navigation bar at the top of the page. Here is my code:

    <div class="container-fluid">

      <div class="row" style="display:none">
        <div class="col-md-12">
          <nav class="navbar navbar-default" role="navigation" style="margin-bottom:0px; margin-top:5px;">...</nav>
      </div></div></div>

      <div class="row">
         <div class="col-md-6" style="background-color: #d6d9dc; height:700px;">
         <div id="myimg" name="myimg"></div>
             <div id="canvasContainer" style="height:600px;">
             <canvas id="canvas" style="position: absolute; background-color:#ecf0f1"></canvas>
             </div>
         </div>
      </div>
   </div>

Javascript for cursor position:

var canvas = document.getElementById('canvas');
var canvasContainer = document.getElementById("canvasContainer");
var context = canvas.getContext('2d');
var flag = false,
        prevX = 0,
        currX = 0,
        prevY = 0,
        currY = 0,
        dot_flag = false;

var x = "red",
    pixelSize = 2;

function make_base(image_url){
  image = new Image();
  image.src = image_url;

    canvas.width = 1000;
    canvas.height = 600;
  canvas.style.background = 'url('+image.src+')';

  image.onload = function(){

   console.log("onload "+image.width)
    canvas.width = image.width;
    canvas.height = image.height;

    canvas.addEventListener("mousemove", function (e) {
        findxy('move', e)
    }, false);
    canvas.addEventListener("mousedown", function (e) {
        findxy('down', e)
    }, false);
    canvas.addEventListener("mouseup", function (e) {
        findxy('up', e)
    }, false);
    canvas.addEventListener("mouseout", function (e) {
        findxy('out', e)
    }, false);
  }
}

function color(obj) {
  console.log(obj);
  if (obj === "white"){
    pixelSize = 16;
    x = "white";
  }else{
    x = obj.value;
    pixelSize = 2;
  }

}

function draw() {
  context.beginPath();
  context.moveTo(prevX, prevY);
  context.lineTo(currX, currY);
  context.strokeStyle = x;
  context.lineWidth = pixelSize;
  if(pixelSize == 16){
    context.clearRect(prevX, prevY, 14, 14);
  }else{
    context.stroke();
  }
  context.closePath();
}

function findxy(res, e) {
  if (res == 'down') {
      prevX = currX;
      prevY = currY;
      currX = e.clientX - canvas.offsetLeft;
      currY = e.clientY - canvas.offsetTop;

      flag = true;
      dot_flag = true;
      if (dot_flag) {
          context.beginPath();
          context.fillStyle = x;
          context.fillRect(currX, currY, 2, 2);
          context.closePath();
          dot_flag = false;
      }
  }
  if (res == 'up' || res == "out") {
      flag = false;
  }
  if (res == 'move') {
      if (flag) {
          prevX = currX;
          prevY = currY;
          currX = e.clientX - canvas.offsetLeft;
          currY = e.clientY - canvas.offsetTop;
          draw();
      }
  }
}

Any suggestion is greatly appreciated. Thank you.

Upvotes: 0

Views: 1839

Answers (1)

Blindman67
Blindman67

Reputation: 54026

Use the mouse event properties pageX, pageY they give you the position of the mouse relative to the top left of the page. You then get the position of the element you have the mouse events on with event.target.getBoundingClientRect. Then you need to remove the scroll offset the page may be at.

At this stage you have the mouse position to the top left of the element. You have one issue left and that is the element's border width. If you have the border width in pixels then subtract that as well from the mouse.x, mouse.y pos, if the border is using a different metric and or the top and left borders are different sizes you will have to make the appropriate adjustment.

var mouse = {x : 0, y : 0, events : "mousemove,mousedown,mouseup"};
function mouseEvent(e) {
    var bounds = e.target.getBoundingClientRect();
    mouse.x = e.pageX - bounds.left - scrollX;  // is window.scrollX same for Y
    mouse.y = e.pageY - bounds.top - scrollY;   // 
}

mouse.events    // chaining functions
    .split(",")
    .forEach((eName) => {
        canvas.addEventListener(eName,mouseEvent)
    });

For older browsers you will need to get the scroll position via.

// add this to the mouse event listeners.
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");

var currentScrollX = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
var currentScrollY = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;

From MDN web API scrollY

Upvotes: 1

Related Questions