mardi 26 décembre 2017

WPF Storyboard animation unintended shaking

I'm trying to create an animated checkbox in WPF, similar to this one.

This question is NOT a duplicate of this one, because there is no problem with the framerate of the animation.

The animations and the storyboards are already in place, and working properly, but for some rason, while the animation is playing, it looks like the whole thing is shaking, as demonstrated here. The effect is best seen on the right border of the box.

The following is the XAML source code of the custom checkbox. I don't think that there is a need to post the code behind, since it doesn't contain anything other than the RoutedEvent definitions (FlatCheckBox.Checked and FlatCheckBox.Unchecked).

<UserControl x:Name="userControl" x:Class="Sync_Launcher.Controls.FlatCheckBox"
         xmlns="http://ift.tt/o66D3f"
         xmlns:x="http://ift.tt/mPTqtT"
         xmlns:mc="http://ift.tt/pzd6Lm" 
         xmlns:d="http://ift.tt/pHvyf2"
         xmlns:controls="clr-namespace:Sync_Launcher.Controls"
         mc:Ignorable="d" 
         d:DesignHeight="30"
         Background="Transparent" MouseLeftButtonDown="FlatCheckBox_OnMouseLeftButtonDown">
<Grid SnapsToDevicePixels="True">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{Binding ActualHeight, ElementName=userControl}"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid Column="0">
        <Grid Name="tickHolderGridRoot" Margin="4">
            <Grid.LayoutTransform>
                <TransformGroup>
                    <RotateTransform x:Name="rotationTransform" Angle="0"/>
                </TransformGroup>
            </Grid.LayoutTransform>
            <Grid Name="tickHolderGrid" Margin="0,0">
                <Border Name="tickBorder" SnapsToDevicePixels="True" Opacity="0" BorderThickness="2,0,0,2" BorderBrush="#FF1CA36F" />
                <Border Name="overlayBorder" SnapsToDevicePixels="True" Opacity="1" BorderThickness="2,2,2,2" BorderBrush="#FF404D61" />
            </Grid>
        </Grid>
    </Grid>
    <Label 
        Grid.Column="1" 
        Content="{Binding Text, ElementName=userControl}" 
        VerticalContentAlignment="Center" 
        FontSize="16" 
        Padding="5,0" 
        FontStyle="{Binding FontStyle, ElementName=userControl}" 
        FontWeight="{Binding FontWeight, ElementName=userControl}"/>
</Grid>
<UserControl.Resources>
    <Duration x:Key="animationDuration">0:0:0.4</Duration>
    <KeyTime x:Key="animationEnd">0:0:0.4</KeyTime>
</UserControl.Resources>
<UserControl.Triggers>
    <EventTrigger SourceName="userControl" RoutedEvent="controls:FlatCheckBox.Checked">
        <BeginStoryboard>
            <Storyboard Timeline.DesiredFrameRate="60">
                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="rotationTransform" Storyboard.TargetProperty="Angle" Duration="{StaticResource animationDuration}">
                    <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                    <EasingDoubleKeyFrame KeyTime="{StaticResource animationEnd}" Value="-60">
                        <EasingDoubleKeyFrame.EasingFunction>
                            <CircleEase EasingMode="EaseOut"/>
                        </EasingDoubleKeyFrame.EasingFunction>
                    </EasingDoubleKeyFrame>
                </DoubleAnimationUsingKeyFrames>
                <DoubleAnimation Storyboard.TargetName="overlayBorder" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="{StaticResource animationDuration}"/>
                <DoubleAnimation Storyboard.TargetName="tickBorder" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="{StaticResource animationDuration}"/>
                <ThicknessAnimation Storyboard.TargetName="tickHolderGrid" Storyboard.TargetProperty="Margin" From="0,0" To="0,2" Duration="{StaticResource animationDuration}"/>
                <ThicknessAnimation Storyboard.TargetName="tickHolderGridRoot" Storyboard.TargetProperty="Margin" From="4" To="2,0,2,4" Duration="{StaticResource animationDuration}"/>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
    <EventTrigger SourceName="userControl" RoutedEvent="controls:FlatCheckBox.Unchecked">
        <BeginStoryboard>
            <Storyboard>
                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="rotationTransform" Storyboard.TargetProperty="Angle" Duration="{StaticResource animationDuration}">
                    <EasingDoubleKeyFrame KeyTime="0" Value="-60"/>
                    <EasingDoubleKeyFrame KeyTime="{StaticResource animationEnd}" Value="0">
                        <EasingDoubleKeyFrame.EasingFunction>
                            <CircleEase EasingMode="EaseOut"/>
                        </EasingDoubleKeyFrame.EasingFunction>
                    </EasingDoubleKeyFrame>
                </DoubleAnimationUsingKeyFrames>
                <DoubleAnimation Storyboard.TargetName="overlayBorder" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="{StaticResource animationDuration}"/>
                <DoubleAnimation Storyboard.TargetName="tickBorder" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="{StaticResource animationDuration}"/>
                <ThicknessAnimation Storyboard.TargetName="tickHolderGrid" Storyboard.TargetProperty="Margin" From="0,2" To="0,0" Duration="{StaticResource animationDuration}"/>
                <ThicknessAnimation Storyboard.TargetName="tickHolderGridRoot" Storyboard.TargetProperty="Margin" From="2" To="4" Duration="{StaticResource animationDuration}"/>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</UserControl.Triggers>

I have tried increasing the storyboard framerate by settings the Timeline.DesiredFrameRate to 60, as you can see in the code, but it had no effect on the shakyness of the animation.

I have also tried setting the SnapsToDevicePixels property to true hoping that it would improve the animation.

What might be the cause of this shaking effect, what can I do to eliminate it?




Aucun commentaire:

Enregistrer un commentaire