为什么轮换会突然跳跃?

时间:2017-09-04 13:38:42

标签: wpf vb.net xaml

这是一个WPF桌面应用。我正在使用Thumb控件来旋转我的对象。虽然它总体上运行良好且平滑,但每次开始旋转时旋转角度都会突然跳跃。初始跳转后,旋转再次顺利进行。

很容易重现。这是完整的XAML:

<Window x:Class="TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" 
        Width="600" Height="600">
  <Canvas>
    <ContentControl x:Name="CC" Canvas.Left="300" Canvas.Top="300">
      <Grid>
        <Thumb DragDelta="Thumb_DragDelta">
          <Thumb.Template>
            <ControlTemplate>
              <Ellipse Width="10" Height="10" Fill="Red" Margin="0,-150,0,0" />
            </ControlTemplate>
          </Thumb.Template>
        </Thumb>

        <Rectangle Width="100" Height="100" Stroke="Black" Fill="Yellow" />
      </Grid>

      <ContentControl.RenderTransform>
        <RotateTransform x:Name="RT" />
      </ContentControl.RenderTransform>
    </ContentControl>
  </Canvas>
</Window>

这是完整的代码隐藏:

Imports System.Windows.Controls.Primitives

Class TestWindow
  Inherits Window

  Private Sub Thumb_DragDelta(sender As Object, e As Primitives.DragDeltaEventArgs)
    Dim T = DirectCast(sender, Thumb)
    Dim RT = DirectCast(CC.RenderTransform, RotateTransform)

    Dim Pos = Mouse.GetPosition(Me)
    Dim PCenter As New Point(350, 350) 'Center of yellow square

    Dim xDiff = Pos.X - PCenter.X
    Dim yDiff = Pos.Y - PCenter.Y
    Dim angle = Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI
    RT.Angle = angle + 90
  End Sub
End Class

单击红色拇指并旋转。它工作得很好。停止以任意角度旋转。再次单击红色拇指并开始旋转。旋转将首先进行大幅度的跳跃,然后再次开始平稳旋转。

问题在哪里,我该如何解决?

1 个答案:

答案 0 :(得分:1)

您的RotateTransform来源与代码隐藏中使用的中心点不匹配。

默认情况下,变换原点位于左上角,为(300; 300),而不是(350; 350)。 当初始角度不为零时,这会导致角度计算无效。

使用

<ContentControl x:Name="CC" Canvas.Left="300" Canvas.Top="300" RenderTransformOrigin="0.5, 0.5">
    <!--...-->
</ContentControl>

更新

如果您无法更改RenderTransformOrigin,则需要更正代码隐藏中的角度计算。

首先,使用正确的中心点:

Dim PCenter As New Point(300, 300)

然后请记住,您的拇指实际上并不对应您希望对象旋转的角度。拇指有一个偏移量。你需要考虑到这一点。

Dim offsetAngle = Math.Atan2(-25.0, 50.0) * 180 / Math.PI
Dim angle = Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI - offsetAngle 
RT.Angle = angle

您可以将offsetAngle设为const(不知道如何在VB中执行此操作)。

那些-25.050.0来自哪里? 50.0是拇指的水平偏移量,计算为Grid.ActualWidth / 2.0(因为拇指水平居中)。 -25.0是拇指的垂直偏移量,计算为(Grid.ActualHeight + Thumb.Margin.Top) / 2.0(因为拇指位于Grid之上)。