代码之家  ›  专栏  ›  技术社区  ›  Siegfried.V

在画布上缩放,以鼠标位置为中心

  •  0
  • Siegfried.V  · 技术社区  · 7 年前

    我知道在stack和其他网站上有好几篇帖子,但似乎我还是做错了什么。当我用鼠标滚轮事件缩放时,缩放总是不居中,但画布的左侧始终保持在ViewBox的左侧,因此当我放大时,只能看到画布的左侧。

    XAML代码:

    <Grid x:Name="MainGrid">
            <Viewbox x:Name="ViewBoxDessin" Stretch="None" HorizontalAlignment="Center" VerticalAlignment="Center">
                <Canvas  x:Name="monDessin" Background="WhiteSmoke" MouseWheel="monDessin_MouseWheel">
                    <Canvas.LayoutTransform>
                        <ScaleTransform x:Name="st" ScaleX="1" ScaleY="-1" CenterX=".5" CenterY=".5" />
                    </Canvas.LayoutTransform>
                </Canvas>
            </Viewbox>
            <Viewbox x:Name="ViewBoxDessin2" Stretch="None">
                <Canvas x:Name="monDessin2">
                    <Canvas.LayoutTransform>
                        <ScaleTransform x:Name="st2" ScaleX="1" ScaleY="1" CenterX=".5" CenterY=".5" />
                    </Canvas.LayoutTransform>
                </Canvas>
            </Viewbox>
        </Grid>
    

    public AfficheGraphiquePiece()
            {
                InitializeComponent();
                MakeMyDrawing();
                ViewBoxDessin.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
                ViewBoxDessin.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
    
                double ech_x = monDessin.Width / System.Windows.SystemParameters.PrimaryScreenWidth;
                double ech_y = monDessin.Height / System.Windows.SystemParameters.PrimaryScreenHeight;
                double ech = Math.Min(ech_x, ech_y);
                this.ech_full = ech;
                st.ScaleX = ech;
                st.ScaleY = -ech;
                st2.ScaleX = ech;
                st2.ScaleY = ech;
            }
            private void monDessin_MouseWheel(object sender, MouseWheelEventArgs e)
            {
                double zoom = e.Delta > 0 ? 1.1 : 0.9;
                if(st.ScaleX<this.ech_full*1.1 && zoom<1)
                {
                    st.ScaleX = this.ech_full;
                    st.ScaleY = -this.ech_full;
                }
                else
                {
                    st.ScaleX *= zoom;
                    st.ScaleY *= zoom;
                    double coor_x = Mouse.GetPosition(monDessin).X;
                    double coor_y = Mouse.GetPosition(monDessin).Y;
                    st.CenterX = coor_x;
                    st.CenterY = coor_y;
    
                }
    
            }
    

    对不起,没有删除一些代码,可能会造成混乱,只是用函数MakeMyDrawing()替换了它

    好吧,在克莱门斯的建议和帮助下 link

    XAML编号:

    <Grid x:Name="MainGrid">
            <Canvas  x:Name="monDessin" Background="WhiteSmoke" MouseWheel="monDessin_MouseWheel" MouseLeftButtonDown="image_MouseLeftButtonDown" MouseMove="image_MouseMove" MouseLeftButtonUp="image_MouseLeftButtonUp" MouseLeave="image_MouseLeave" >
                <Canvas.RenderTransform >
                    <MatrixTransform/>
                </Canvas.RenderTransform>
            </Canvas>
            <Canvas x:Name="monDessin2">
                <Canvas.RenderTransform >
                    <MatrixTransform/>
                </Canvas.RenderTransform>
            </Canvas>
        </Grid>
    

    代码隐藏

    public AfficheGraphiquePiece(Repere rep)
            {
                InitializeComponent();
                ClassGraphique monGraphe = new ClassGraphique(monDessin);
                ClassGraphique monGraphe2 = new ClassGraphique(monDessin2);
                MakeMyDrawing();
                double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
                double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
    
                double ech_x = screenWidth/ monDessin.Width ;
                double ech_y = screenHeight/ monDessin.Height;
                double ech = Math.Min(ech_x, ech_y)*0.9;
                this.ech_full = ech;
                this.echelleNow = this.ech_full;
                MatrixTransform maTrans =(MatrixTransform)monDessin.RenderTransform;
                var mat = maTrans.Matrix;
                mat.ScaleAt(ech, -ech, 0.1* screenWidth, (screenHeight-monDessin.Height*ech)/2-0.1*screenHeight);
                MatrixTransform maTrans2 = (MatrixTransform)monDessin2.RenderTransform;
                var mat2 = maTrans2.Matrix;
                mat2.ScaleAt(ech, ech, 0.1 * screenWidth, screenHeight*ech-((screenHeight - monDessin.Height * ech) / 2 - 0.1 * screenHeight));
                maTrans.Matrix = mat;
                maTrans2.Matrix = mat2;
            }
            private void monDessin_MouseWheel(object sender, MouseWheelEventArgs e)
            {
                try
                {
                    var position = e.GetPosition(monDessin);
                    MatrixTransform transform = (MatrixTransform)monDessin.RenderTransform;
                    MatrixTransform transform2 = (MatrixTransform)monDessin2.RenderTransform;
                    var matrix = transform.Matrix;
                    var matrix2 = transform2.Matrix;
                    var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1); 
                    this.echelleNow *= scale;
                    matrix.ScaleAtPrepend(scale, scale, position.X, position.Y);
                    matrix2.ScaleAtPrepend(scale, scale, position.X,monDessin.Height-position.Y);
                    monDessin.RenderTransform = new MatrixTransform(matrix);
                    monDessin2.RenderTransform = new MatrixTransform(matrix2);
                }
                catch { }
            }
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   Clemens    7 年前

    <Canvas Background="Transparent"
            SizeChanged="ViewportSizeChanged"
            MouseLeftButtonDown="ViewportMouseLeftButtonDown"
            MouseLeftButtonUp="ViewportMouseLeftButtonUp"
            MouseMove="ViewportMouseMove"
            MouseWheel="ViewportMouseWheel">
    
        <Canvas x:Name="canvas" Width="1000" Height="600">
            <Canvas.RenderTransform>
                <MatrixTransform x:Name="transform"/>
            </Canvas.RenderTransform>
    
            <Ellipse Fill="Red" Width="100" Height="100" Canvas.Left="100" Canvas.Top="100"/>
            <Ellipse Fill="Green" Width="100" Height="100" Canvas.Right="100" Canvas.Bottom="100"/>
        </Canvas>
    </Canvas>
    

    代码隐藏:

    private Point? mousePos;
    
    private void ViewportSizeChanged(object sender, SizeChangedEventArgs e)
    {
        ((MatrixTransform)canvas.RenderTransform).Matrix = new Matrix(
            e.NewSize.Width / canvas.ActualWidth,
            0, 0,
            e.NewSize.Height / canvas.ActualHeight,
            0, 0);
    }
    
    private void ViewportMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var viewport = (UIElement)sender;
        viewport.CaptureMouse();
        mousePos = e.GetPosition(viewport);
    }
    
    private void ViewportMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        ((UIElement)sender).ReleaseMouseCapture();
        mousePos = null;
    }
    
    private void ViewportMouseMove(object sender, MouseEventArgs e)
    {
        if (mousePos.HasValue)
        {
            var pos = e.GetPosition((UIElement)sender);
            var matrix = transform.Matrix;
            matrix.Translate(pos.X - mousePos.Value.X, pos.Y - mousePos.Value.Y);
            transform.Matrix = matrix;
            mousePos = pos;
        }
    }
    
    private void ViewportMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var pos = e.GetPosition((UIElement)sender);
        var matrix = transform.Matrix;
        var scale = e.Delta > 0 ? 1.1 : 1 / 1.1;
        matrix.ScaleAt(scale, scale, pos.X, pos.Y);
        transform.Matrix = matrix;
    }
    
    推荐文章