seanomomom
seanomomom

Reputation: 33

Mouse/touch coordinates in wrong location HTML canvas

I'm having trouble with my HTML canvas, was working fine in its experimental stage however once I brought it into my proper development the mouse coordinates have become completely wonky, It does draw, however not in the correct position i.e. I click and drag to draw a line, that line is the draw further down within the canvas. I'm just looking to fix the coordinates in so the mouse cursor draws exactly where it should be.

Below is my code, In order to get a sense of what Im talking about be sure to resize the browser window as the website is mobile specific. Thank you any help would be much appreciated

Ive tried using getXY functions but I already have a variable name after that but it didn't work. I also tried various styling techniques but to no avail

function init() {
  // Get the specific canvas element from the HTML document
  canvas = document.getElementById('c');
}

function midPointBtw(p1, p2) {
  return {
    x: p1.x + (p2.x - p1.x) / 2,
    y: p1.y + (p2.y - p1.y) / 2
  };
}

function getPattern() {
  return ctx.createPattern(img, 'repeat');
}

var el = document.getElementById('c');
var ctx = el.getContext('2d');

ctx.lineWidth = 15;
ctx.lineJoin = ctx.lineCap = 'round';

var img = new Image;

img.onload = function() {
  ctx.strokeStyle = getPattern();
};

img.src = "https://i.postimg.cc/rF2R0GRY/dick2.png";
var isDrawing, points = [];

var getXY = function(e) {
  var source = e.touches ? e.touches[0] : e;

  return {
    x: source.clientX,
    y: source.clientY
  };
};

var startDrawing = function(e) {
  isDrawing = true;
  points.push(getXY(e));
  e.preventDefault();
};


var keepDrawing = function(e) {
  if (!isDrawing) return;

  points.push(getXY(e));
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

  var p1 = points[0];
  var p2 = points[1];

  ctx.moveTo(p1.x, p1.y);

  for (var i = 1, len = points.length; i < len; i++) {
    var midPoint = midPointBtw(p1, p2);
    ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);
    p1 = points[i];
    p2 = points[i + 1];
  }

  ctx.lineTo(p1.x, p1.y);
  ctx.stroke();
  e.preventDefault();
};

var stopDrawing = function() {
  isDrawing = false;
  points = [];
};

el.addEventListener('touchstart', startDrawing);
el.addEventListener('mousedown', startDrawing);

el.addEventListener('touchmove', keepDrawing);
el.addEventListener('mousemove', keepDrawing);

el.addEventListener('touchend', stopDrawing);
el.addEventListener('mouseup', stopDrawing);

function clearCanvas(canvas, ctx) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath()
}

init();
@font-face {
  font-family: Geoma Regular Demo;
  src: url(Geoma Regular Demo.otf);
}

@font-face {
  font-family: Geoma Demo;
  src: url(Geoma Light demo.otf);
}

@media screen and (max-width: 425px) {
  html,
  body {
    overflow-x: hidden;
    width: 100%;
    margin: 0;
  }
}

canvas {
  border: 3px solid #0BF446;
  border-radius: 15px 0px 15px 0px;
  display: block;
  margin: 0 auto;
  margin-top: 35px;
}

#clearbutton {
  background-color: #04A12B;
  border-radius: 0 15px 0 15px;
  padding: 20px;
  margin: 0 auto;
  display: block;
  font-size: 14px;
  color: white;
  font-family: Geoma Demo;
  margin-top: 35px;
}

#footer1 {
  background-color: #00671A;
  border-radius: 30px 30px 0px 0px;
  text-align: center;
  padding: 30px;
  margin-top: 35px;
}

#about {
  color: white;
  font-size: 16px;
  font-family: Geoma Demo;
}
<canvas id="c" width="350" height="500"></canvas>
<input type="submit" value="Clear Sketchpad" id="clearbutton" onclick="clearCanvas(canvas,ctx);">
<footer id="footer1">
  <a href="" id="about">About Elemental</a>
</footer>

Upvotes: 1

Views: 1535

Answers (1)

zero298
zero298

Reputation: 26920

You will need to localize your click event to be relative to the canvas element. You can do this by getting the top and left out of el.getBoundingClientRect() and using them to adjust the x and y value of your click event. See below, most of the work was done in the getXY function.

function init() {
  // Get the specific canvas element from the HTML document
  canvas = document.getElementById('c');
}

function midPointBtw(p1, p2) {
  return {
    x: p1.x + (p2.x - p1.x) / 2,
    y: p1.y + (p2.y - p1.y) / 2
  };
}

function getPattern() {
  return ctx.createPattern(img, 'repeat');
}

var el = document.getElementById('c');
var ctx = el.getContext('2d');

ctx.lineWidth = 15;
ctx.lineJoin = ctx.lineCap = 'round';

var img = new Image;

img.onload = function() {
  ctx.strokeStyle = getPattern();
};

img.src = "https://i.postimg.cc/rF2R0GRY/dick2.png";
var isDrawing, points = [];

var getXY = function(e) {
  var source = e.touches ? e.touches[0] : e;
  const {
    clientX,
    clientY
  } = source;
  const {
    left,
    top
  } = el.getBoundingClientRect();

  const x = clientX - left;
  const y = clientY - top;

  return {
    x,
    y
  };
};

var startDrawing = function(e) {
  isDrawing = true;
  points.push(getXY(e));
  e.preventDefault();
};


var keepDrawing = function(e) {
  if (!isDrawing) return;

  points.push(getXY(e));
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

  var p1 = points[0];
  var p2 = points[1];

  ctx.moveTo(p1.x, p1.y);

  for (var i = 1, len = points.length; i < len; i++) {
    var midPoint = midPointBtw(p1, p2);
    ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);
    p1 = points[i];
    p2 = points[i + 1];
  }

  ctx.lineTo(p1.x, p1.y);
  ctx.stroke();
  e.preventDefault();
};

var stopDrawing = function() {
  isDrawing = false;
  points = [];
};

el.addEventListener('touchstart', startDrawing);
el.addEventListener('mousedown', startDrawing);

el.addEventListener('touchmove', keepDrawing);
el.addEventListener('mousemove', keepDrawing);

el.addEventListener('touchend', stopDrawing);
el.addEventListener('mouseup', stopDrawing);

function clearCanvas(canvas, ctx) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath()
}

init();
@font-face {
  font-family: Geoma Regular Demo;
  src: url(Geoma Regular Demo.otf);
}

@font-face {
  font-family: Geoma Demo;
  src: url(Geoma Light demo.otf);
}

@media screen and (max-width: 425px) {
  html,
  body {
    overflow-x: hidden;
    width: 100%;
    margin: 0;
  }
}

canvas {
  border: 3px solid #0BF446;
  border-radius: 15px 0px 15px 0px;
  display: block;
  margin: 0 auto;
  margin-top: 35px;
}

#clearbutton {
  background-color: #04A12B;
  border-radius: 0 15px 0 15px;
  padding: 20px;
  margin: 0 auto;
  display: block;
  font-size: 14px;
  color: white;
  font-family: Geoma Demo;
  margin-top: 35px;
}

#footer1 {
  background-color: #00671A;
  border-radius: 30px 30px 0px 0px;
  text-align: center;
  padding: 30px;
  margin-top: 35px;
}

#about {
  color: white;
  font-size: 16px;
  font-family: Geoma Demo;
}
<canvas id="c" width="350" height="500"></canvas>
<input type="submit" value="Clear Sketchpad" id="clearbutton" onclick="clearCanvas(canvas,ctx);">
<footer id="footer1">
  <a href="" id="about">About Elemental</a>
</footer>

Upvotes: 5

Related Questions