Monday, 14 September 2020

Canvas HTML5: Display rect coordinates on mousemove

I'm currently developing an image editor with HTML5 Canvas, and I'm having a problem detecting the image coordinates when mousing over the canvas.

I have replicated the problem in a code snipped with a rectangle:

Example

When:

  • The red part is the border of the canvas. The canvas size is 400x400 pixels.
  • The green part is a rectangle simulating the image. The rect size is 200x200 pixels.
  • On the mousemove event, is displaying at the bottom coordinates of the canvas.
  • The blue text, is what I want (right now the coordinates are not those, are of the canvas)

What I want and I don't know how to do it:

  • On mousemove, I want to display coordinates of the rect instead of the canvas coordinates. ie the (0, 0) of the canvas will become negative. And the displayed (0, 0) on the bottom should correspond with the blue text.
  • It should work also after changing the ZOOM property. The ZOOM in the example is 1, but after changing to 0.5 or 1.5 should work in the same way.

Code

Here below I share the code snipped to see if anyone can help me with that because I'm a little frustrated and I'm sure it's silly. Thanks a lot!

const RECT_SIZE = 200
const ZOOM = 1
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
const svgPoint = svg.createSVGPoint()
const xform = svg.createSVGMatrix()
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const res = document.querySelector('.res')
const pt = transformedPoint(canvas.width / 2, canvas.height / 2)
const X = canvas.width / 2 - RECT_SIZE / 2
const Y = canvas.height / 2 - RECT_SIZE / 2

function transformedPoint(x, y) {
  svgPoint.x = x
  svgPoint.y = y
  return svgPoint.matrixTransform(xform.inverse())
}

function mousemove(e) {
  const { left, top } = canvas.getBoundingClientRect()
  res.textContent = `X: ${e.clientX - left} - Y: ${e.clientY - top}`
}

// SCALING CANVAS
ctx.translate(pt.x, pt.y)
ctx.scale(ZOOM, ZOOM)
ctx.translate(-pt.x, -pt.y)

// SETTING SOME DEFAULTS
ctx.lineWidth = 1
ctx.strokeStyle = 'green'
ctx.fillStyle = 'blue'

// DRAWING A REACTANGLE
ctx.beginPath()
ctx.strokeRect(X, Y, RECT_SIZE,  RECT_SIZE)

ctx.font = "12px Arial";
ctx.fillText("0,0", X - 5, Y-10);
ctx.fillText("200,200", X + RECT_SIZE - 15, Y + RECT_SIZE + 15);

ctx.closePath()
canvas {
  border: 1px solid red;
}
<canvas width="400" height="400" onmousemove="mousemove(event)"}></canvas>
<div class="res" />

Changing the line:

res.textContent = `X: ${e.clientX - left} - Y: ${e.clientY - top}`

to

res.textContent = `X: ${e.clientX - left - X} - Y: ${e.clientY - top - Y}`

Is displaying the correct coordinates when ZOOM = 1. However, is not displaying the correct coordinates after change the zoom.



from Canvas HTML5: Display rect coordinates on mousemove

No comments:

Post a Comment