Pan and Zoom in WPF
Posted: January 21, 2011 Filed under: Uncategorized 2 Comments »DeepZoom is a cool feature of Silverlight 2.0 allowing the user to zoom and pan around an image, while optimizing the bandwidth and how much of the image is downloaded. The UI metaphor is potentially quite powerful – even outside of image viewing. Take WPF, with its scalable vector content, panning and zooming around ad-hoc rendered content could have several uses – even without the dynamic image loading.
This quick post details how to achieve this is WPF with a simple ContentControl. It borrows some functionality from Jaime Rodriguez’s excellent DeepZoom Primer.
The entire pan and zoom functionality can be achieved by a single transform group. I use a class derived from a content control with two transforms, a scale transform for zooming and a TranslateTransform for panning. This transform group will then pan and zoom the content of the content control (much like the scroll viewer). The initialization is done in code:
this.source = VisualTreeHelper.GetChild(this, 0) as FrameworkElement;
this.translateTransform = new TranslateTransform();
this.zoomTransform = new ScaleTransform();
this.transformGroup = new TransformGroup();
this.transformGroup.Children.Add(this.zoomTransform);
this.transformGroup.Children.Add(this.translateTransform);
this.source.RenderTransform = this.transformGroup;
The DoZoom function modifies these transforms based on the parameters sent. This is similar to Jaime’s DoZoom function:
/// <summary>Zoom into or out of the content.</summary> /// <param name="deltaZoom">Factor to mutliply the zoom level by. </param> /// <param name="mousePosition">Logical mouse position relative to the /// original content.</param> /// <param name="physicalPosition">Actual mouse position on the screen /// (relative to the parent window)</param> public void DoZoom(double deltaZoom, Point mousePosition, Point physicalPosition) { double currentZoom = this.zoomTransform.ScaleX; currentZoom *= deltaZoom; this.translateTransform.BeginAnimation(TranslateTransform.XProperty, CreateZoomAnimation(-1 * (mousePosition.X * currentZoom - physicalPosition.X))); this.translateTransform.BeginAnimation(TranslateTransform.YProperty, CreateZoomAnimation(-1 * (mousePosition.Y * currentZoom - physicalPosition.Y))); this.zoomTransform.BeginAnimation(ScaleTransform.ScaleXProperty, CreateZoomAnimation(currentZoom)); this.zoomTransform.BeginAnimation(ScaleTransform.ScaleYProperty, CreateZoomAnimation(currentZoom)); }
The rest of the code simply hooks up the mouse events to the DoZoom function. This is all self contained within the ContentControl, so using this Pan And Zoom functionality is simply a matter of adding the control and filling in the content.
It’s still missing some functionality, like the navigation overlay. It would also be nice to add events for the zoom detail so you could adjust detail of the rendered content based on the zoom level.
Source code can be found here
Updated this post and source code link here: http://blogs.windowsclient.net/joeyw/archive/2009/06/02/pan-and-zoom-updated.aspx
The links to source code are broken. Could you please update the links?
Thanks a lot,
Ming Huang
Thanks for this good post
…but the link to your source-code is broken… – maybe you can fix this?
Stone