2011-04-21 35 views
3

使用下面的XAML:我怎样才能在水墨上做缩放和旋转?

<Grid x:Name="grid" Background="LightBlue" ClipToBounds="True"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 
    <Viewbox x:Name="imgViewbox" > 
       <InkCanvas Grid.Row="0" Name="inkCanvas" Background="Red" > 
       <Image Source="Images/pic.png" HorizontalAlignment="Left" x:Name="imgObject" VerticalAlignment="Top" /> 
       <Label>Testing</Label> 
       </InkCanvas> 
    </Viewbox> 
</Grid> 

我想绕图像中心,还可以使用滚轮鼠标放大。我已经建立了这种变换组和事件:

public MainWindow() { 

    InitializeComponent(); 
    DataContext = new MainWindowViewModel(); 

    transformGroup = new TransformGroup(); 
    scaleTransform = new ScaleTransform(); 
    rotateTransform = new RotateTransform(); 
    translateTransform = new TranslateTransform(); 
    transformGroup.Children.Add(rotateTransform); 
    transformGroup.Children.Add(scaleTransform); 
    transformGroup.Children.Add(translateTransform); 

    imgViewbox.RenderTransform = transformGroup; 

    imgViewbox.MouseWheel += ImageViewboxMouseWheel; 
} 

旋转很简单:

void Rotate(object sender, RoutedEventArgs e) { 
    //imgViewbox.RenderTransformOrigin = new Point(0.5,0.5); 
    rotateTransform.Angle += 90; 
} 

但变焦在做各种奇怪的东西在屏幕上跳跃。缩放代码位于:

void ImageViewboxMouseWheel(object sender, MouseWheelEventArgs e) { 
    //imgViewbox.RenderTransformOrigin = new Point(0, 0); 
    double zoomFactor = DefaultZoomFactor; 
    if (e.Delta <= 0) zoomFactor = 1.0/DefaultZoomFactor; 
    // DoZoom requires both the logical and physical location of the mouse pointer 
    var physicalPoint = e.GetPosition(imgViewbox); 
    if (transformGroup.Inverse != null) { 
     DoZoom(zoomFactor, transformGroup.Inverse.Transform(physicalPoint), physicalPoint); 
    } 
    else { 
     throw new ArgumentException("Missing Inverse"); 
    } 

    //Set the center point of the ScaleTransform object to the cursor location. 
    scaleTransform.CenterX = e.GetPosition(imgViewbox).X; 
    scaleTransform.CenterY = e.GetPosition(imgViewbox).Y; 
    Debug.WriteLine(string.Format("IVMW Center {0},{1}", scaleTransform.CenterX, scaleTransform.CenterY)); 
} 

public void DoZoom(double deltaZoom, Point mousePosition, Point physicalPosition) { 
    double currentZoom = scaleTransform.ScaleX; 
    currentZoom *= deltaZoom; 

    translateTransform.X = -1*(mousePosition.X*currentZoom - physicalPosition.X); 
    translateTransform.Y = -1*(mousePosition.X*currentZoom - physicalPosition.Y); 
    scaleTransform.ScaleX = currentZoom; 
    scaleTransform.ScaleY = currentZoom; 
} 

我已经尽可能多地移除了动画等。希望只留下关键部分。我认为主要问题是scaleTransform.Center [X | Y],因为即使我尝试点击完全相同的位置,返回的数字也会遍布整个象限。 RenderTransformOrigin似乎与中心位置没有任何区别,但我知道我需要它围绕中心旋转。

我在做什么错?

回答

1

你需要以抵消你从TranslateTransform改变ScaleTranform的的centerX/Y这一跳得到,这里是一个泛&变焦控制我写了一个片段:

private void This_MouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    if (IsZoomEnabled) 
    { 
     Point cursorPos = e.GetPosition(this); 
     Point newCenter = _scaleT.Inverse.Transform(_translateT.Inverse.Transform(cursorPos)); 
     Point oldCenter = new Point(_scaleT.CenterX, _scaleT.CenterY); 
     Vector oldToNewCenter = newCenter - oldCenter; 
     _scaleT.CenterX = newCenter.X; 
     _scaleT.CenterY = newCenter.Y; 
     _translateT.X += oldToNewCenter.X * (_scaleT.ScaleX - 1.0); 
     _translateT.Y += oldToNewCenter.Y * (_scaleT.ScaleY - 1.0); 
     ... 

希望你能适应这个你码。在计算新中心的地方,您可能需要考虑RotateTransform。

+0

我把它放在里面,我想我理解为什么这是必要的,但是当我最大化窗口并在屏幕中心滚动轮子时,我看到旧中心的CenterY是负面的。这看起来不正确。任何想法为什么会发生? – Kevin 2011-04-21 14:52:08

+0

我在哪里编写了'e.GetPosition(this)',您可能需要将引用传递给InkCanvas或其他适当的控件/容器,可能会修复它。 – 2011-04-21 14:58:40