Quantcast
Channel: cyotek.com Blog Summary Feed
Viewing all articles
Browse latest Browse all 559

Zooming into a fixed point on a ScrollableControl

$
0
0

If I'd built subtitle support into the CMS that powers this website, then surely the subtitle would have been "or how I fixed that annoying zoom bug in the ImageBox control". And with that digression out of the way, onto the article, a nice and short one for a change!

I should probably point out that this article doesn't describe how to actually do any zooming (as that is dependant on what it is you are actually doing a zoom upon), but rather how to keep the viewport focused on a given point after zooming. To learn about zooming, please see previous articles that describe the ImageBox control in detail.

Users of the ImageBox control are probably aware of the zoom bug, where each time you use the mouse wheel to zoom in or out, the final image position is slightly offset, as shown by this short animation:

Mouse wheel zoom - subtly broken.

Fixing this bug is actually quite simple and I'm actually embarrassed at how long it took to fix and how I missed the solution for so long. The key to resolving this issue is finding out the document position under the mouse (by which I mean the position in the entire scroll area, not just the visible viewport) before applying the zoom, and then recalculating this position with the new zoom level, offset by the mouse position in the client control.

As it's probably easier just to show you the code rather than try and describe it, it results in this small function:

publicvirtualvoid ScrollTo(Point imageLocation, Point relativeDisplayPoint)
{int x;int y;

  x = (int)(imageLocation.X * this.ZoomFactor) - relativeDisplayPoint.X;
  y = (int)(imageLocation.Y * this.ZoomFactor) - relativeDisplayPoint.Y;this.AutoScrollPosition = new Point(x, y);
}

To use it, you add code similar to the following where you process mouse clicks, or mouse wheel, however you control zooming with the mouse:

Point cursorPosition;
Point currentPixel;int currentZoom;// TODO: Obtain cursor position from MouseEventArgs etc.

currentPixel = this.PointToImage(cursorPosition);
currentZoom = this.Zoom;// TODO: Perform zoom hereif (this.Zoom != currentZoom)this.ScrollTo(currentPixel, cursorPosition);

So how does this work?

  1. Get the mouse cursor position, relative to the control
  2. Convert that position into the position of your virtual document - for the ImageBox control we use the PointToImage method
  3. Perform your zoom and recalculate the document scroll size etc.
  4. Call the ScrollTo method, passing in the document position and mouse cursor position

And now you end up with something similar to this:

Mouse wheel zoom - works a lot smoother now.

There is one case where this does not work as expected - when you scroll in or out sufficiently to remove the scrollbars, or when moving from no-scrollbars to scrollbars. However, I think is fine given it works so well the rest of the time!

That's fine, but where's the ImageBox update?

Thanks to a generous donation from a visitor to the site, I recently sat down to work on the ImageBox control and resolve some of the issues - like the scrolling above. The next update has quite a lot of new functionality (better keyboard support, configurable zoom levels, flicker free scrolling and a handful of bug fixes to name a few of the changes) and will be posted presently. While the build is being finalized however, the above code will work fine in current builds of the ImageBox, if you adjust for the pixel offset the current PointToImage implementation uses.

All content Copyright © by Cyotek Ltd or its respective writers. Permission to reproduce news and web log entries and other RSS feed content in unmodified form without notice is granted provided they are not used to endorse or promote any products or opinions (other than what was expressed by the author) and without taking them out of context. Written permission from the copyright owner must be obtained for everything else.
Original URL of this content is http://www.cyotek.com/blog/zooming-into-a-fixed-point-on-a-scrollablecontrol?source=rss


Viewing all articles
Browse latest Browse all 559

Trending Articles