After panning, need to zoom the image from the center point that is visible on the screen

133 Views Asked by At

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.

Attached image for reference. Original center of the image Center of the image after panning

         <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;
        }
    }
}
0

There are 0 best solutions below