AB4D Forum

Full Version: Panning beyond image
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I need the ability to pan beyond the extents of a canvas so I can center a corner of canvas in the middle of the form. Our users need to zoom into detailed areas that they want centered. 


This is an interesting request.

To solve the problem I used the ZoomPanelDump to check what are the edge values where ZoomPanel's Viewbox value need to be preserved.

Below you can find the source for the solution. To check the solution, copy the source code over the existing code in the ZoomPanelDumpSample.xaml.cs file in the ZoomPanel Samples under ZoomPanel folder.

I will add the GetActualViewbox method to the next version of ZoomPanel so such calculations will be easier.

Note that when using ZoomPanelNavigator you need to set the IsZoomPanelLimitedToMinMaxZoomFactors property to false to prevent limiting Viewbox by the ZoomPanelNavigator.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Ab2d.Controls;

namespace Ab2d.ZoomControlSample.ZoomPanel
   /// <summary>
   /// Interaction logic for ZoomPanelDumpSample.xaml
   /// </summary>
   public partial class ZoomPanelDumpSample : Page
       public ZoomPanelDumpSample()

           ZoomPanel1.PreviewViewboxChanged += delegate(object sender, ViewboxChangedRoutedEventArgs e)
               // First we prevent zoom out (viewbox.Width or Height bigger then 1)
               if (e.NewViewboxValue.Width > 1)
                   e.NewViewboxValue = new Rect(e.OldViewboxValue.X, e.OldViewboxValue.Y, 1, e.NewViewboxValue.Height);

               if (e.NewViewboxValue.Height > 1)
                   e.NewViewboxValue = new Rect(e.OldViewboxValue.X, e.OldViewboxValue.Y, e.NewViewboxValue.Width, 1);

               var newViewbox       = e.NewViewboxValue;
               var actualNewViewbox = GetActualViewbox(newViewbox);

               //System.Diagnostics.Debug.WriteLine("actualViewbox: " + actualViewbox.ToString());

               if (actualNewViewbox.X < -(actualNewViewbox.Width / 2) ||
                   actualNewViewbox.X > (1 - actualNewViewbox.Width / 2))
                   // Update the viewbox to use the old X value
                   e.NewViewboxValue = new Rect(e.OldViewboxValue.X, newViewbox.Y, newViewbox.Width, newViewbox.Height);
                   //e.Handled = true; // Prevent any change

               if (actualNewViewbox.Y < -(actualNewViewbox.Height / 2) ||
                        actualNewViewbox.Y > (1 - actualNewViewbox.Height / 2))
                   // Update the viewbox to use the old Y value
                   e.NewViewboxValue = new Rect(e.NewViewboxValue.X, e.OldViewboxValue.Y, newViewbox.Width, newViewbox.Height);

                   //e.Handled = true; // Prevent any change

       private Rect GetActualViewbox(Rect viewbox)
           var actualContentSize = ZoomPanel1.UsedViewboxEx.ActualContentSize;

           double zoomPanelAspectRatio = ZoomPanel1.ActualWidth / ZoomPanel1.ActualHeight;
           double contentAspectRatio   = actualContentSize.Width / actualContentSize.Height;

           Rect actualViewbox;

           double aspectRatioFactor = zoomPanelAspectRatio / contentAspectRatio;

           if (aspectRatioFactor > 1) // zoomPanelAspectRatio < contentAspectRatio
               // ZoomPanel is wider then content - this means that on the left and right we show empty space - so the actualViewbox.Width is bigger then viewbox.Width
               double actualWidth = viewbox.Width * aspectRatioFactor;
               double actualX     = -0.5 * (actualWidth - viewbox.Width) + viewbox.X;
               actualViewbox      = new Rect(actualX, viewbox.Y, actualWidth, viewbox.Height);
               // ZoomPanel content is wider then ZoomPanel - this means that on the top and bottom show empty space - so the actualViewbox.Height is bigger then viewbox.Height
               double actualHeight = viewbox.Height / aspectRatioFactor;
               double actualY      = -0.5 * (actualHeight - viewbox.Height) + viewbox.Y;
               actualViewbox       = new Rect(viewbox.X, actualY, viewbox.Width, actualHeight);

           return actualViewbox;

       private void ShowAdditionalInfoCheckBox_Checked(object sender, RoutedEventArgs e)
           if (!this.IsLoaded)

           ZoomPanelDump1.ShowAdditionalInfo = true;

       private void ShowAdditionalInfoCheckBox_Unchecked(object sender, RoutedEventArgs e)
           if (!this.IsLoaded)

           ZoomPanelDump1.ShowAdditionalInfo = false;