Did you know that you can customize behavior of built-in interactions with callbacks?

Jan Studnicka on 23 Jul 2025
Latest activity Edit by Jan Studnicka on 24 Jul 2025

I would like to zoom directly on the selected region when using on my image created with image or imagesc. First of all, I would recommend using image or imagesc and not imshow for this case, see comparison here: Differences between imshow() and image()? However when zooming Stretch-to-Fill behavior happens and I don't want that. Try range zoom to image generated by this code:
fig = uifigure;
ax = uiaxes(fig);
im = imread("peppers.png");
h = imagesc(im,"Parent",ax);
axis(ax,'tight', 'off')
I can fix that with manualy setting data aspect ratio:
daspect(ax,[1 1 1])
However, I need this code to run automatically after zooming. So I create zoom object and ActionPostCallback which is called everytime after I zoom, see zoom - ActionPostCallback.
z = zoom(ax);
z.ActionPostCallback = @(fig,ax) daspect(ax.Axes,[1 1 1]);
If you need, you can also create ActionPreCallback which is called everytime before I zoom, see zoom - ActionPreCallback.
z.ActionPreCallback = @(fig,ax) daspect(ax.Axes,'auto');
Code written and run in R2025a.
Jan Studnicka
Jan Studnicka on 24 Jul 2025 (Edited on 24 Jul 2025)
Update:
There is still one issue with my solution. ActionPreCallback is called right after clicking on the image, and the data aspect ratio is set to auto mode. If the image is already zoomed in, Stretch-to-Fill takes effect during additional zooming.
Alternative solution: Create a custom push button for the axes toolbar that performes your own custom zoom. For my custom zoom I used function drawrectangle from the Image Processing Toolbox. ButtonPushedFcn for my "Rectangle Zoom" push button:
function rectangleZoomCallback(src,event)
roi = drawrectangle(event.Axes);
roiPos = roi.Position;
event.Axes.XLim = [roiPos(1), roiPos(1)+roiPos(3)];
event.Axes.YLim = [roiPos(2), roiPos(2)+roiPos(4)];
daspect(event.Axes,[1 1 1])
delete(roi)
end
I also need custom "restore view" button with ButtonPushedFcn:
function restoreRectangleZoomCallback(src,event)
axis(event.Axes,'tight', 'off')
end
Adam Danz
Adam Danz on 23 Jul 2025
Great tip @Jan Studnicka! I totally know what you mean about the imshow hesitations.
We have an article coming up in the Graphics and App Building blog later this year on our Interaction tools and best practices.
I'd love to know what MATLAB users are creating with our custom interaction tools!