I have a canvas in a react app which I can zoom in image and move it right/left/up/down. I want to be able to calculate image overflow size so that I can limit the left/right/up/down actions when there's no more room too go.
Here's the working app: https://codesandbox.io/s/reverent-mestorf-9gd1t?file=/src/App.js
As you can see when you zoom out the image will no longer be filled inside canvas. I want to be able to disable zoom out button when image is going to be smaller than canvas.
I also want to be able to disable move right/left/up/down buttons when there's no more room in the image to move.
current behavior just shows empty spots inside canvas.
Here's the canvas code inside my useEffect, whenever src, x, y and scale changes we'll render the canvas.
useEffect(() => {
if (src) {
const canvas = canvasRef.current
const canvasContext = canvas?.getContext('2d')
const imageObj = new Image()
imageObj.onload = () => {
if (canvas) {
const hRatio = canvas.width / imageObj.width
const vRatio = canvas.height / imageObj.height
// Calculate ratio so the image is filled inside canvas
const ratio = Math.max(hRatio, vRatio)
canvasContext?.clearRect(0, 0, canvas.width, canvas.height)
canvasContext?.drawImage(
imageObj,
x,
y,
imageObj.width,
imageObj.height,
0,
0,
// for zooming scale is between 0 and 2
imageObj.width * ratio * scale,
imageObj.height * ratio * scale
)
}
}
imageObj.src = src
}
}, [src, x, y, scale])
After a lot of playing around with canvas I found the solution.
my old draw image:
canvasContext?.drawImage(
imageObj,
x,
y,
imageObj.width,
imageObj.height,
0,
0,
// for zooming scale is between 0 and 2
imageObj.width * ratio * scale,
imageObj.height * ratio * scale
)
my new draw image:
canvasContext?.drawImage(
imageObj,
x,
y,
// scale is between 0 and 2 for zooming
imageObj.width * ratio * scale,
imageObj.height * ratio * scale
)
I needed to apply the ratio and zoom to the source image size instead of canvas's.
So now to simply calculating overflow I can do this:
overflowY = 3000(canvas height) - (imageObj.height * ratio * scale)
overflowX = 4500(canvas width) - (imageObj.width * ratio * scale)