When I zoom the image with render transform origin as (0.5, 0.5), it zooms from the center point of the image and is working fine. But after panning when I zoom, it is not taking the visible center portion of the image instead it takes the center of the original image.
How to calculate the center portion of the panned image.
Please find the working example and in that click on the increase button to increase the zoom and then pan the image and again increase the zoom, but image is not zoomed with respect to the visible center.
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid x:Name="panel" MouseWheel="Panel_MouseWheel" Grid.Column="0" Background="Yellow" ClipToBounds="True"
MouseLeftButtonDown="Panel_MouseLeftButtonDown" MouseMove="Panel_MouseMove"
MouseLeftButtonUp="Panel_MouseLeftButtonUp">
<Image x:Name="editorImage" Source="Buldingimage.jpeg" ></Image>
</Grid>
<StackPanel Orientation="Vertical" Grid.Column="1">
<Button Click="Button_Click" Content="Increase"/>
<Button Content="Decrease" Click="Button_Click_1"></Button>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Zoom factor : "></TextBlock>
<TextBlock Text="{Binding ZoomFactor}"></TextBlock>
</StackPanel>
<Button Content="Reset" Click="Button_Click_2"></Button>
</StackPanel>
</Grid>
public partial class MainWindow : Window
{
MatrixTransform ZoomMatrixTransform;
public MainWindow()
{
InitializeComponent();
grid.DataContext = this;
updateZoom = true;
}
bool updateZoom;
public int ZoomFactor
{
get { return (int)GetValue(ZoomFactorProperty); }
set { SetValue(ZoomFactorProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomFactor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomFactorProperty =
DependencyProperty.Register("ZoomFactor", typeof(int), typeof(MainWindow), new PropertyMetadata(100, OnZoomFactorChanged));
private static void OnZoomFactorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var window = d as MainWindow;
int factor = (int)e.NewValue;
if (factor >= 50 && factor <= 400 && window.updateZoom)
window.PerformZoom(e.NewValue);
}
private void PerformZoom(object newValue)
{
float zoomValue = Convert.ToInt32(newValue) / 100f;
Matrix matrix = Matrix.Identity;
var scaleX = zoomValue;
var scaleY = zoomValue;
matrix.Scale(scaleX, scaleY);
ZoomMatrixTransform = new MatrixTransform(matrix);
foreach (UIElement child in panel.Children)
{
child.RenderTransformOrigin = new Point(0.5, 0.5);
child.RenderTransform = ZoomMatrixTransform;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ZoomFactor += 10;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
ZoomFactor -= 10;
}
private void Panel_MouseWheel(object sender, MouseWheelEventArgs e)
{
var element = sender as UIElement;
var position = e.GetPosition(panel.Children[0]);
var matrix = ZoomMatrixTransform == null ? Matrix.Identity : ZoomMatrixTransform.Matrix;
var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1);
matrix.ScaleAtPrepend(scale, scale, position.X, position.Y);
var factor = (int)(matrix.M11 * 100);
updateZoom = false;
ZoomFactor = factor <= 50 ? 50 : factor >= 400 ? 400 : factor;
updateZoom = true;
if (factor >= 50 && factor <= 400)
{
ZoomMatrixTransform = new MatrixTransform(matrix);
foreach (UIElement child in panel.Children)
{
child.RenderTransform = ZoomMatrixTransform;
}
}
}
Point start;
Point origin;
private void Panel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if ( ZoomMatrixTransform != null && ZoomMatrixTransform.Matrix != Matrix.Identity)
{
start = e.GetPosition(panel);
origin = new Point(ZoomMatrixTransform.Matrix.OffsetX, ZoomMatrixTransform.Matrix.OffsetY);
editorImage.CaptureMouse();
}
Point position;
if (this.editorImage != null)
position = e.GetPosition(this.editorImage);
else
position = e.GetPosition(panel);
}
private void Panel_MouseMove(object sender, MouseEventArgs e)
{
Point position;
if (this.editorImage != null)
position = e.GetPosition(this.editorImage);
else
position = e.GetPosition(this.panel);
if (editorImage.IsMouseCaptured && ZoomMatrixTransform.Matrix != Matrix.Identity)
{
FrameworkElement frameworkElement;
if (editorImage != null)
frameworkElement = editorImage;
else
frameworkElement = panel;
var elementBounds = new Rect(frameworkElement.RenderSize);
var transformedBounds = editorImage.TransformToAncestor(panel).TransformBounds(elementBounds);
var matrix = ZoomMatrixTransform.Matrix;
Vector vector = start - e.GetPosition(panel);
if (transformedBounds.Left < 0 && vector.X <= 0)
matrix.OffsetX = origin.X - vector.X;
else if (vector.X >= 0 && transformedBounds.Right >= panel.ActualWidth)
matrix.OffsetX = origin.X - vector.X;
if (transformedBounds.Top < 0 && vector.Y <= 0)
matrix.OffsetY = origin.Y - vector.Y;
else if (vector.Y >= 0 && transformedBounds.Bottom >= panel.ActualHeight)
matrix.OffsetY = origin.Y - vector.Y;
ZoomMatrixTransform.Matrix = matrix;
foreach (UIElement child in panel.Children)
{
child.RenderTransform = ZoomMatrixTransform;
}
}
}
private void Panel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
editorImage.ReleaseMouseCapture();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
ZoomMatrixTransform.Matrix = Matrix.Identity;
foreach (UIElement child in panel.Children)
{
child.RenderTransform = ZoomMatrixTransform;
}
}
}

