wpfxamlanimationrotationpathgeometry

Animation Rotating a PathGeometry


I have a path that has three defining PathGeometries: a circle, a connecting line, and a path that represents fan blades. I'd like to use the path's Tag property to trigger an animation that rotates the fan blade geometry. Since I need to reuse this many times, I'd also like to encompass the path and storyboard in a single style, if possible.

So far I've built up the paths, created a storyboard, created a rotate transform on the PathGeometry that I'd like to rotate, and created the necessary trigger.

I cannot figure out why the following does not work:

 <Style x:Key="fanPath" TargetType="{x:Type Path}">
        <Setter Property="Stroke" Value="Black"/>
        <Setter Property="StrokeThickness" Value="1"/>
        <Setter Property="Data">
            <Setter.Value>
                <GeometryGroup>
                    <PathGeometry>
                        <PathFigure StartPoint="15,30" IsFilled="False">
                            <LineSegment Point="15,50"/>
                        </PathFigure>
                    </PathGeometry>
                    <EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15"/>
                    <!-- Want to rotate the following -->
                    <PathGeometry>
                        <PathGeometry.Transform>
                            <RotateTransform x:Name="rotate" CenterX="15" CenterY="15"/>
                        </PathGeometry.Transform>
                        <PathFigure StartPoint="10,5" IsClosed="True">
                            <LineSegment Point="20,5"/>
                            <LineSegment Point="10,25"/>
                            <LineSegment Point="20,25"/>
                        </PathFigure>
                        <PathFigure StartPoint="5,10" IsClosed="True">
                            <LineSegment Point="5,20"/>
                            <LineSegment Point="25,10"/>
                            <LineSegment Point="25,20"/>
                        </PathFigure>
                    </PathGeometry>
                </GeometryGroup>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="Tag" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard Name="fanRotate">
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="rotate.Angle" From="0"
                                 To="90" RepeatBehavior="Forever"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <StopStoryboard BeginStoryboardName="fanRotate"/>
                </Trigger.ExitActions>
            </Trigger>
        </Style.Triggers>
    </Style>

I've checked that my Tag property is being set properly and I've checked that manually changing the Angle property of the rotate transform works as expected. I believe my problem lies in linking the Storyboard.TargetProperty property to the proper place (rotate.Angle), but I cannot figure out what core issue I'm encountering.


Solution

  • You need to access your Angle property via a path as follows:

    Storyboard.TargetProperty="(Path.Data).(GeometryGroup.Children)[2].(PathGeometry.Transform).Angle"
    

    This does what you need:

    enter image description here

    <Window x:Class="WpfApplication2.MainWindow"
            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"
            xmlns:local="clr-namespace:WpfApplication2"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <Style x:Key="fanPath" TargetType="{x:Type Path}">
                <Setter Property="Stroke" Value="Black"/>
                <Setter Property="StrokeThickness" Value="1"/>
                <Setter Property="Data">
                    <Setter.Value>
                    <GeometryGroup>
                        <PathGeometry>
                            <PathFigure StartPoint="15,30" IsFilled="False">
                                <LineSegment Point="15,50"/>
                            </PathFigure>
                        </PathGeometry>
                        <EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15"/>
                        <!-- Want to rotate the following -->
                        <PathGeometry>
                            <PathGeometry.Transform>
                                <RotateTransform x:Name="rotate" CenterX="15" CenterY="15"/>
                            </PathGeometry.Transform>
                            <PathFigure StartPoint="10,5" IsClosed="True">
                                <LineSegment Point="20,5"/>
                                <LineSegment Point="10,25"/>
                                <LineSegment Point="20,25"/>
                            </PathFigure>
                            <PathFigure StartPoint="5,10" IsClosed="True">
                                <LineSegment Point="5,20"/>
                                <LineSegment Point="25,10"/>
                                <LineSegment Point="25,20"/>
                            </PathFigure>
                        </PathGeometry>
                    </GeometryGroup>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <Trigger Property="Tag" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard Name="fanRotate">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetProperty="(Path.Data).(GeometryGroup.Children)[2].(PathGeometry.Transform).Angle" From="0"
                                     To="90" RepeatBehavior="Forever"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <StopStoryboard BeginStoryboardName="fanRotate"/>
                        </Trigger.ExitActions>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Path x:Name="paththing" Width="300" Height="300" Fill="Aqua" Stretch="Fill" Style="{StaticResource fanPath}"/>
            <Button Grid.Row="1" x:Name="button" Content="Go" VerticalAlignment="Bottom">
                <Button.Triggers>
                    <EventTrigger RoutedEvent="Button.Click">
                        <BeginStoryboard>
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="paththing" Storyboard.TargetProperty="Tag">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="True"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Button.Triggers>
            </Button>
        </Grid>
    </Window>