We don't need to make any changes to onDraw(...)
because we have appropriately adjust the values of translateX
and translateY
by taking into account the previous translation values when we set startX
and startY
. So now we need to solve the problem of indefinite panning. Let's tackle the easier aspect of that problem first: stopping panning past the top and left edges of the canvas (i.e., where the X and Y coordinates are zero):
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
//We're going to scale the X and Y coordinates by the same amount
canvas.scale(scaleFactor, scaleFactor);
//I multiplied translateX and translateY by -1 because it made more sense to me to see if they were lesser than 0. If they are lesser
//than zero, we set their values to 0. Otherwise, we leave them as is. This ensures that we never pan past the top of left edge of the
//zoomed-in canvas.
translateX = (translateX * -1) < 0 ? 0 : translateX;
translateY = (translateY * -1) < 0 ? 0 : translateY;
//We need to divide by the scale factor here, otherwise we end up with excessive panning based on our zoom level
//because the translation amount also gets scaled according to how much we've zoomed into the canvas.
canvas.translate(translateX / scaleFactor, translateY / scaleFactor);
canvas.restore();
}
Now let's tackle the more difficult aspect of the indefinite-panning problem: panning past the bottom and right edges of the canvas. This part was hard for me. The solution seems pretty obvious now and so it might not actually be all that difficult; it took me a little time to figure it out however! The height of my display is 320px. I noticed that when I had zoomed in by a factor of 2, the value for translateY
was 320. At a zoom factor of 3, the value was 640px and so on. So basically the limit seemed to be the scale factor minus one, times the height of the display. I'm sure if I had spent more time I could have proved why that is, but at the time I was more concerned with getting this to work:
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
//We're going to scale the X and Y coordinates by the same amount
canvas.scale(scaleFactor, scaleFactor);
.
//If translateX times -1 is lesser than zero, let's set it to zero. This takes care of the left bound
if((translateX * -1) < 0) {
translateX = 0;
}
//This is where we take care of the right bound. We compare translateX times -1 to (scaleFactor - 1) * displayWidth.
//If translateX is greater than that value, then we know that we've gone over the bound. So we set the value of
//translateX to (1 - scaleFactor) times the display width. Notice that the terms are interchanged; it's the same
//as doing -1 * (scaleFactor - 1) * displayWidth
else if((translateX * -1) > (scaleFactor - 1) * displayWidth) {
translateX = (1 - scaleFactor) * displayWidth;
}
if(translateY * -1 < 0) {
translateY = 0;
}
//We do the exact same thing for the bottom bound, except in this case we use the height of the display
else if((translateY * -1) > (scaleFactor - 1) * displayHeight) {
translateY = (1 - scaleFactor) * displayHeight;
}
//We need to divide by the scale factor here, otherwise we end up with excessive panning based on our zoom level
//because the translation amount also gets scaled according to how much we've zoomed into the canvas.
canvas.translate(translateX / scaleFactor, translateY / scaleFactor);
canvas.restore();
}
I appreciate how clear you tried to explain everything. Thank you!
I want to do a “zoomable paint”, I mean a paint that I can zoom/zoom out and pan/drag the canvas and then draw on it.
I have a problem that I can’t solve: when I draw while the canvas is zoomed, I retrieve the X and Y coordinate and effectively drawing it on the canvas. But these coordinates are not correct because of the zoomed canvas.
I tried to correct these (multiply by (zoomHeigh/screenHeight)) but I can’t find a way to retrieve where I must draw on the original/none-zoomed screen
Whenever I try to implement above method the screen jitters on account of zoom effect but does not zoom essentially. I am drawing circle points on canvas and on zooming I want them to scale further apart. I don’t know if I tend to custom draw those circle points based on dimensions of zoomed canvas why is the overall effect a mere jitter ?