首页 文章

使用故事板沿最短的时间旋转网格'route'

提问于
浏览
1

我'm developing a '罗盘式'控制,它能够沿0-360度的值旋转;即全圆 . 通过在ViewModel中设置属性,Grid将设置为新角度的动画 . 但是,当动画从10度旋转到350度时,动画不会使用到新角度的最短路径 . 它几乎绕整个圆圈旋转 clockwise .

但我想要实现的是它沿着最短的路线动画:从10到350应该只有20度的动画.1777043_ .

下面我添加了一个代码示例,但是它不是绑定到ViewModel中的属性,而是使用绑定到ListBox(复制粘贴应该让它运行) . 选择ListBox中的项目会旋转Grid(包含'needle') .

如果可能的话,我更喜欢“全XAML”解决方案 . 这是可行的,我想要实现的目标是什么?

<Window x:Class="CompassRotation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="375" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>

        <Grid>
            <Ellipse Width="300" Height="300" Fill="DarkCyan" />
            <Label Content="{Binding SelectedItem.Content, ElementName=Angle, UpdateSourceTrigger=Explicit}"
                   FontSize="36" />
            <Grid Width="300" Height="300"
                  RenderTransformOrigin="0.5,0.5"
                  Tag="{Binding SelectedItem.Content, ElementName=Angle, UpdateSourceTrigger=PropertyChanged,NotifyOnTargetUpdated=True}">
                <Grid.Triggers>
                    <EventTrigger RoutedEvent="Binding.TargetUpdated">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                    Storyboard.TargetProperty="(Grid.RenderTransform).(RotateTransform.Angle)"
                                    Duration="0:0:1" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Grid.Triggers>

                <Grid.RenderTransform>
                    <RotateTransform Angle="{Binding SelectedItem.Content, ElementName=Angle, FallbackValue=45}" />
                </Grid.RenderTransform>

                <Rectangle Width="15" Height="300">
                    <Rectangle.Fill>
                        <LinearGradientBrush>
                            <GradientStopCollection>
                                <GradientStop Color="Red" Offset="0" />
                                <GradientStop Color="Green" Offset="1" />
                            </GradientStopCollection>
                        </LinearGradientBrush>
                    </Rectangle.Fill>
                </Rectangle>
            </Grid>
        </Grid>
        <ListBox Grid.Column="1" Name="Angle">
            <ListBoxItem>0</ListBoxItem>
            <ListBoxItem>45</ListBoxItem>
            <ListBoxItem>90</ListBoxItem>
            <ListBoxItem>135</ListBoxItem>
            <ListBoxItem>180</ListBoxItem>
            <ListBoxItem>225</ListBoxItem>
            <ListBoxItem>270</ListBoxItem>
            <ListBoxItem>305</ListBoxItem>
            <ListBoxItem>360</ListBoxItem>
        </ListBox>
    </Grid>
</Window>

1 回答

  • 0

    DoubleAnimation 有一个From property,你可以绑定它来设置动画的起始值 .

    因此,在逆时针将ViewModel的 Angle 值从10更新为350之前,将ViewModel的 From 值设置为370,动画将从370(= 10)度标记逆时针滚动回350 .

    如果您要将 from 从值 from 更新为 to ,那么将留下如何确定要设置的 From 值的问题 .

    我们知道的一件事是要设置的 From 属性应该在 [to - 180, to + 180] 的区间内,以确保旋转采用最短的路径到 to .

    如果我们调用此区间的下限 lowerbound = to - 180 ,那么

    From = lowerbound + (from - lowerbound) % 360
    

    或者实际上,从% behaves oddly for negative values开始,一个更安全的公式适用于 [-360,360] 范围内的 fromto 角度

    From = lowerbound + (from - lowerbound + 720) % 360
    

相关问题