Powered by MSDN

US - English
NEW! Silverlight 5 is available Learn More

  • silverlightOnly

    silverlightOnly

    Member

    20 Points

    12 Posts

    matrix Pan and Zoom

    Nov 19, 2008 05:03 PM | LINK

    Discovered a strange translation occurring on centered zoom (zoom<>1) after a pan.
    The goal is to zoom always on a constant point of the screen, presented by a red circle. Pan is controlled with arrow keys, zoom - with key plus(+) or minus(-).
    Everything works fine, except when scaling with zoom <>1 after a pan. Cannot figure out where this one-time translation comes from... Before and after this event panning and zooming work as expected.
    Here is the code. What am I missing ?

     <UserControl x:Class="ZoPanNS.ZoPan"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="600" Height="600">
        <Canvas Background="White">
            <Ellipse Canvas.Left="200" Canvas.Top="200" Canvas.ZIndex="2"
                    Width="12" Height="12" Stroke="Red" StrokeThickness="2" Fill="Transparent" />
            <TextBlock x:Name="TxtB" Canvas.Left="0" Canvas.Top="0" Canvas.ZIndex="2"
                    Width="200" Height="20" Text="click here to start" />
            
            <Canvas x:Name="cMoved" Background="PaleGreen" Canvas.Left="100" Canvas.Top="100"
                    Width="200" Height="200" RenderTransformOrigin="0,0">
                <Rectangle Canvas.Left="0" Canvas.Top="0"
                    Width="200" Height="200" Stroke="DarkCyan" StrokeThickness="2" Fill="Wheat" />
                <Ellipse x:Name="Ccircle" Canvas.Left="100" Canvas.Top="100"
                    Width="7" Height="7" Stroke="Green" StrokeThickness="2" Fill="Green" />
            </Canvas>
        </Canvas>
    </UserControl>

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Shapes;

    namespace ZoPanNS
    {
        public partial class ZoPan : UserControl
        {
            double Xstep = 40, Ystep = 40, Zstep = 0.2;
            double CenterX=100, CenterY=100;
            private MatrixTransform _matrixTransform = new MatrixTransform();

            public ZoPan()
            {
                InitializeComponent();
                this.Loaded += new RoutedEventHandler(Page_Loaded);
            }
            private void Page_Loaded(object o, EventArgs e)
            {
                cMoved.RenderTransform = _matrixTransform;
                cMoved.RenderTransformOrigin = new Point(.5, .5); //center
                this.KeyDown += new KeyEventHandler(page_KeyDown);
            }
            private void page_KeyDown(object sender, KeyEventArgs e)
            {
                Matrix matrix = _matrixTransform.Matrix;
                switch (e.Key)
                {
                    case Key.Left:
                        CenterX += Xstep;
                        Ccircle.SetValue(Canvas.LeftProperty, CenterX);
                        matrix.OffsetX -= Xstep * matrix.M11;
                        break;
                    case Key.Right:
                        CenterX -= Xstep;
                        Ccircle.SetValue(Canvas.LeftProperty, CenterX);
                        matrix.OffsetX += Xstep * matrix.M11;
                        break;
                    case Key.Up:
                        CenterY += Ystep;
                        Ccircle.SetValue(Canvas.TopProperty, CenterY);
                        matrix.OffsetY -= Ystep * matrix.M22;
                        break;
                    case Key.Down:
                        CenterY -= Ystep;
                        Ccircle.SetValue(Canvas.TopProperty, CenterY);
                        matrix.OffsetY += Ystep * matrix.M22;
                        break;

                    case Key.Add:
                        matrix.M11 += Zstep;
                        matrix.M22 = matrix.M11;
                        cMoved.RenderTransformOrigin = new Point(
                            CenterX / cMoved.ActualWidth, CenterY / cMoved.ActualHeight);
                        break;

                    case Key.Subtract:
                        matrix.M11 -= Zstep;
                        matrix.M22 = matrix.M11;
                        cMoved.RenderTransformOrigin = new Point(
                            CenterX / cMoved.ActualWidth, CenterY / cMoved.ActualHeight);
                        break;
                    default:
                        return;
                }
                _matrixTransform.Matrix = matrix;
                TxtB.Text = "zoom=" + matrix.M11.ToString("0.0")
                    + " cX=" + CenterX.ToString("0.0")
                    + " oX=" + matrix.OffsetX.ToString("0.0")
                    + " rX=" + cMoved.RenderTransformOrigin.X.ToString("0.0")
                ;
            }
        }
    }

    RenderTransformOrigin Silverlight 2 Pan and zoom