2014-03-12 151 views
4

我正在尝试使用鼠标滚轮实现画布的缩放功能。 目前我只是使用CenterX =“0.5”和CenterY =“0.5”缩放到画布的中心位置。 我想改变行为,以便在鼠标位置发生缩放,我想知道这是否可以使用ScaleTransform。将画布缩放到鼠标位置

目前我使用下面的代码:

<Canvas Width="500" Height="500"> 
    <Canvas.LayoutTransform> 
     <ScaleTransform CenterX="0.5" CenterY="0.5" 
           ScaleX="{Binding Zoom}" 
           ScaleY="{Binding Zoom}" /> 
    </Canvas.LayoutTransform> 
</Canvas> 
+0

[这里](http://stackoverflow.com/questions/10372560/zooming-to-mouse-point-with-scrollview-and-viewbox-in-wpf)是一个例子, 他已经用ScrollViewer内的视图框。 然后他抓住了鼠标的初始位置并实现了缩放 希望这会有所帮助.... –

+0

有很多方法可以做到这一点,但不能使用LayoutTransform。因为LayoutTransform忽略任何翻译,转换的Canvas将永远不会被适当地移动。 RenderTransform也可以吗? – Clemens

+0

你能否给我举一个例子,我可以用RenderTransform做到这一点? – Eggi

回答

9

一个非常基本的方法在特定位置放大画布(或任何其他的UIElement)是使用一个MatrixTransform为RenderTransform财产

<Canvas Width="500" Height="500" MouseWheel="Canvas_MouseWheel"> 
    <Canvas.RenderTransform> 
     <MatrixTransform/> 
    </Canvas.RenderTransform> 
</Canvas> 

和更新的的Matrix属性在此鼠标滚轮处理变换一样:

private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    var element = sender as UIElement; 
    var position = e.GetPosition(element); 
    var transform = element.RenderTransform as MatrixTransform; 
    var matrix = transform.Matrix; 
    var scale = e.Delta >= 0 ? 1.1 : (1.0/1.1); // choose appropriate scaling factor 

    matrix.ScaleAtPrepend(scale, scale, position.X, position.Y); 
    transform.Matrix = matrix; 
} 
3

我过去两天在这个问题上苦苦挣扎,我想通了。这将使您平滑地放大鼠标并平滑缩小。我在这里发布我的解决方案给任何可能搜索和绊倒在这里的人。

// Class constructor 
public YourClass(Canvas theCanvas) //You may not need the Canvas as an argument depending on your scope 
    { 
     panTransform = new TranslateTransform(); 
     zoomTransform = new ScaleTransform(); 
     bothTransforms = new TransformGroup(); 

     bothTransforms.Children.Add(panTransform); 
     bothTransforms.Children.Add(zoomTransform); 

     theCanvas.RenderTransform = bothTransforms; 

     //Handler 
     theCanvas.MouseWheel += wheelEvent; 
     //You also need your own handlers for panning, which I'm not showing here. 
    } 

private void returnCalculatedScale() 
    { 
     double d; 
     //Do some math to get a new scale. I keep track of an integer, and run it through the formula y^(x/3) where X is the integer. 

     return d; 
    } 


// Mouse wheel handler, where the magic happens 
private void wheelEvent(object sender, MouseWheelEventArgs e) 
    { 
     Point position = e.GetPosition(mainCanvas);   

     zoomTransform.CenterX = position.X; 
     zoomTransform.CenterY = position.Y; 

     zoomTransform.ScaleX = returnCalculatedScale(); 
     zoomTransform.ScaleY = returnCalculatedScale(); 

     Point cursorpos = Mouse.GetPosition(mainCanvas); //This was the secret, as the mouse position gets out of whack when the transform occurs, but Mouse.GetPosition lets us get the point accurate to the transformed canvas. 

     double discrepancyX = cursorpos.X - position.X; 
     double discrepancyY = cursorpos.Y - position.Y; 

     //If your canvas is already panned an arbitrary amount, this aggregates the discrepancy to the TranslateTransform. 
     panTransform.X += discrepancyX; 
     panTransform.Y += discrepancyY;