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.
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:
<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>
Related
all. I have started a simple WPF application and would like a button to follow an elliptical path when it is made visible(for now I just want it to occur when I click...for testing purposes). It should simply move along the path then come to rest at the final point. I am having trouble getting the storyboard to work in a style. It won't reference the path that I have already defined. How do I resolve this? Eventually, each button will need to have it's own final resting point, so I will need to pass in an extra animation at a later date. The code is in XAML(posted below).
<Window x:Class="EllipseFollowsPath.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:EllipseFollowsPath"
mc:Ignorable="d"
Title="MainWindow" Height="768" Width="1366">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Height="768" Width="1366">
<Grid.Resources>
<PathGeometry x:Key="path">
<PathGeometry.Figures>
<PathFigure StartPoint="921,384" IsClosed="False">
<ArcSegment Point="445,384" Size="60 60"
SweepDirection="Counterclockwise"/>
</PathFigure>
<PathFigure StartPoint="445,384" IsClosed="False">
<ArcSegment Point="921,384" Size="60 60"
SweepDirection="Counterclockwise"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
<Storyboard x:Key="sb" RepeatBehavior="Forever">
<MatrixAnimationUsingPath
Storyboard.TargetName="transform"
Storyboard.TargetProperty="Matrix"
PathGeometry="{StaticResource path}"
Duration="0:0:2">
</MatrixAnimationUsingPath>
</Storyboard>
</Grid.Resources>
<Button Height="20" Width="20">
<Button.RenderTransform>
<MatrixTransform x:Name="transform"/>
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource sb}">
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
The code below works...
<Window x:Class="EllipseFollowsPath.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:EllipseFollowsPath"
mc:Ignorable="d"
Title="MainWindow" Height="768" Width="1366">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Height="768" Width="1366">
<Grid.Resources>
<PathGeometry x:Key="path">
<PathGeometry.Figures>
<PathFigure StartPoint="921,384" IsClosed="False">
<ArcSegment Point="445,384" Size="60 60"
SweepDirection="Counterclockwise"/>
</PathFigure>
<PathFigure StartPoint="445,384" IsClosed="False">
<ArcSegment Point="921,384" Size="60 60"
SweepDirection="Counterclockwise"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
<Storyboard x:Key="sb" RepeatBehavior="Forever">
<MatrixAnimationUsingPath
Storyboard.TargetName="transform"
Storyboard.TargetProperty="Matrix"
PathGeometry="{StaticResource path}"
Duration="0:0:2">
</MatrixAnimationUsingPath>
</Storyboard>
</Grid.Resources>
<Button Height="20" Width="20">
<Button.RenderTransform>
<MatrixTransform x:Name="transform"/>
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource sb}">
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
I have a rectangle for which I want to animate the Width from 0 to some offset with a color say Red and the remaining width with different color say Green.
Any idea how to do it?
Example:
Animation flow ->
|start <- Red -> stop | start <- Green -> stop|
Rectangle doesnt allow you have Content in it. So, you can use Fill as a VisualBrush or DrawingBrush.
VisualBrush approach
This VisualBrush will have a StackPanel with two Rectangle objects.
Run below code as it is :
<Rectangle Height="100" Stroke="Black">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" From="0" To="200" Duration="0:0:10"/>
<DoubleAnimation Storyboard.TargetName="LeftRect" Storyboard.TargetProperty="Width" From="0" To="100" Duration="0:0:5"/>
<DoubleAnimation Storyboard.TargetName="RightRect" Storyboard.TargetProperty="Width" From="0" To="100" Duration="0:0:5" BeginTime="0:0:5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
<Rectangle.Fill>
<VisualBrush Stretch="None" AlignmentX="Left">
<VisualBrush.Visual>
<StackPanel Orientation="Horizontal">
<Rectangle x:Name="LeftRect" Height="100">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="Red"/>
<Setter Property="Width" Value="0"/>
</Style>
</Rectangle.Style>
</Rectangle>
<Rectangle x:Name="RightRect" Height="100">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="Green"/>
<Setter Property="Width" Value="0"/>
</Style>
</Rectangle.Style>
</Rectangle>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
DrawingBrush approach
This DrawingBrush will have RectangleGeometry and won't use any Control.
<Rectangle Height="100" Width="300" Stroke="Black" StrokeThickness="2" RenderTransformOrigin="0,0.5">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="LeftScaleX" Storyboard.TargetProperty="ScaleX" From="0" To="1" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="RightScaleX" Storyboard.TargetProperty="ScaleX" From="0" To="1" Duration="0:0:1" BeginTime="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
<Rectangle.Fill>
<DrawingBrush AlignmentX="Left" Stretch="None">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="Red">
<GeometryDrawing.Geometry>
<RectangleGeometry x:Name="LeftRect" Rect="0 0 200 100">
<RectangleGeometry.Transform>
<TransformGroup>
<ScaleTransform x:Name="LeftScaleX" ScaleX="0" CenterY="50"/>
</TransformGroup>
</RectangleGeometry.Transform>
</RectangleGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="Green">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="200 0 300 100">
<RectangleGeometry.Transform>
<TransformGroup>
<ScaleTransform x:Name="RightScaleX" ScaleX="0" CenterX="200"/>
</TransformGroup>
</RectangleGeometry.Transform>
</RectangleGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
A much simpler approach would be to animate ViewPort property.
<Rectangle Stroke="Black" Margin="44,67,44,0" Width="0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="100">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" To="300" Duration="0:0:1"/>
<RectAnimation Storyboard.TargetName="Brush1" Storyboard.TargetProperty="(DrawingBrush.Viewport)" To="0,0, 300,100" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
<Rectangle.Fill>
<DrawingBrush x:Name="Brush1" Viewport="0,0,0,100" AlignmentX="Left" Stretch="None" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="Red">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0, 200, 100"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="Green">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="200,0, 100, 100"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
Example Button Link
Can WPF do shape animation likes this button click's effect? I try to use double animation the width and cornerRadius but the effects is not quite good. I using the path animation to animate the progress circle but only the shape animation I really don know how to animate it. Anyone can help me or give some ideas?
This is my Code
<Path x:Name="path" Height="20" Width="20" Stroke="Gray" Stretch="Fill" Opacity="0.3"
StrokeThickness="2" Data="m35,2.5c17.955803,0 32.5,14.544199 32.5,32.5c0,17.955803 -14.544197,32.5 -32.5,32.5c-17.955803,0 -32.5,-14.544197 -32.5,-32.5c0,-17.955801 14.544197,-32.5 32.5,-32.5z"
StrokeDashOffset="204.243713378906">
<Path.StrokeDashArray>
<System:Double>204.243713378906</System:Double>
</Path.StrokeDashArray>
</Path>
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="bdrTest">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="path"
Storyboard.TargetProperty="(Shape.StrokeDashOffset)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="204.243713378906"/>
<SplineDoubleKeyFrame KeyTime="00:00:5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
What you are calling Animations are not Animations. It is simply the Button.Background and Button.Foreground changing colour in response to mouse over events. To give a Button rounded corners, you just need to supply your own ControlTemplate for the Button:
<Button Content="Submit" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="30" BorderThickness="2" BorderBrush="#FF1ECD97"
TextElement.Foreground="#FF1ECD97" TextElement.FontSize="20"
TextElement.FontWeight="SemiBold" Padding="100,20">
<ContentPresenter />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
Now to add the mouse over effects, we just need to add a Trigger to the ControlTemplate to change the colour of the Button.Background and Button.Foreground when the UIElement.IsMouseOver property is True:
<Button Content="Submit" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="Border" CornerRadius="30" Background="Transparent"
BorderThickness="2" BorderBrush="#FF1ECD97" TextElement.Foreground=
"#FF1ECD97" TextElement.FontSize="20" TextElement.FontWeight="SemiBold"
Padding="100,20">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background"
Value="#FF1ECD97" />
<Setter TargetName="Border" Property="TextElement.Foreground"
Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
The most difficult thing is animating the circular progress. If using codebehind, it's not such problematic. But I tried to use pure XAML. In codebehind we can calculate the Point of some ArcSegment from the corresponding angle and update the ArcSegment accordingly. But in XAML, we have to use some hacky work-around. I had to use 4 layers of borders to create this effect. Firstly I tried with just 2 layers but because changing the Background while animating it simply makes the animation not work expectedly.
I will concentrate mainly on the circular progress effect because this is the most challenging problem when solving with pure XAML. Basically you need some background Border having 2 halves with different colors making a full circle. The left half is grayed, the right half has active (progressed) color. This border is fixed:
You need another Border also with 2 different halves. Its left half is transparent and its right half has active/progressed color. This Border will be rotated (in fact its Background is rotated) in the second phase after the first phase is 180 degree rotated:
The next Border will be used in the first phase. This border also has 2 different halves. The left half is transparent and the right half is grayed:
So initially, these 3 Borders will make a full grayed circle (the left grayed half is of the first Border, the right grayed half is of the third):
In the first phase, the third border is 180 degree rotated. Its grayed half will gradually open the underneath active-color half of the second Border making the effect of progressing from 0 to 180 degree. After that the first phase has been finished. The third Border will be hidden, the second Border will be rotated. Now its active-color half (the right half) will gradually cover the grayed half of the first Border (on the left) and make the effect progressing from 180 to 360 (full of active color).
There are still other Border layers for the last effect of showing tickmark,... Here is the full code. It's fairly long and it's mainly used for reference, you may have to improve it much so that it can be used in your code. I just used simple animations (without easing):
<Button Background="Transparent" Content="Submit" FontSize="30" Foreground="#FF1ECD97" BorderBrush="#FF1ECD97">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Height" Value="80"/>
<Setter Property="Width" Value="280"/>
<Setter Property="BorderThickness" Value="2"/>
</Style>
</Button.Style>
<Button.Template>
<ControlTemplate TargetType="Button">
<ControlTemplate.Resources>
<DrawingBrush Stretch="Fill" x:Key="circle">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Geometry="M-25,-25 h50v50h-50v-50" Brush="Transparent">
</GeometryDrawing>
<GeometryDrawing Geometry="M0,-25 A25,25 0 0 1 0,25">
<GeometryDrawing.Pen>
<Pen Brush="{DynamicResource right}" Thickness="4"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
<GeometryDrawing Geometry="M0,25 A25,25 0 0 1 0,-25">
<GeometryDrawing.Pen>
<Pen Brush="{DynamicResource left}" Thickness="4"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
<DrawingBrush.RelativeTransform>
<RotateTransform Angle="0" CenterX="0.5" CenterY="0.5"/>
</DrawingBrush.RelativeTransform>
</DrawingBrush>
<DrawingBrush x:Key="ok" Stretch="None">
<DrawingBrush.Drawing>
<GeometryDrawing Geometry="M0,20 L10,30 30,5">
<GeometryDrawing.Pen>
<Pen Brush="White" Thickness="5" EndLineCap="Round" StartLineCap="Round"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
<DrawingBrush.RelativeTransform>
<ScaleTransform CenterX="0.5" CenterY=".5" ScaleX="0" ScaleY="0"/>
</DrawingBrush.RelativeTransform>
</DrawingBrush>
</ControlTemplate.Resources>
<Grid>
<Grid.Effect>
<DropShadowEffect ShadowDepth="1"/>
</Grid.Effect>
<Border BorderBrush="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}"
BorderThickness="{Binding BorderThickness, RelativeSource={RelativeSource TemplatedParent}}" CornerRadius="40"
Background="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}">
</Border>
<Border Opacity="0" Name="b1">
<Border.Resources>
<SolidColorBrush Color="#FF1ECD97" x:Key="right"/>
<SolidColorBrush Color="#ffdddddd" x:Key="left"/>
</Border.Resources>
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{StaticResource circle}"/>
</Style>
</Border.Style>
</Border>
<Border Opacity="0" Name="b12">
<Border.Resources>
<SolidColorBrush Color="#FF1ECD97" x:Key="right"/>
<SolidColorBrush Color="Transparent" x:Key="left"/>
</Border.Resources>
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{StaticResource circle}"/>
</Style>
</Border.Style>
</Border>
<Border Opacity="0" Name="b2">
<Border.Resources>
<SolidColorBrush Color="#ffdddddd" x:Key="right"/>
<SolidColorBrush Color="Transparent" x:Key="left"/>
</Border.Resources>
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{StaticResource circle}"/>
</Style>
</Border.Style>
</Border>
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Name="cp"/>
<Border Opacity="0" Name="b3_" Background="#FF1ECD97" CornerRadius="40"/>
<Border Opacity="0" Name="b3" Background="{StaticResource ok}"/>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Name="bg">
<Storyboard Duration="0:0:6" FillBehavior="Stop">
<DoubleAnimation Storyboard.TargetProperty="Width" To="80" Duration="0:0:.2">
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="b1" Storyboard.TargetProperty="Opacity" BeginTime="0:0:.2" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="b2" Storyboard.TargetProperty="Opacity" BeginTime="0:0:.2" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="cp" Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="b2" Storyboard.TargetProperty="Background.RelativeTransform.Angle" By="180" BeginTime="0:0:.2" Duration="0:0:2"/>
<DoubleAnimation Storyboard.TargetName="b12" Storyboard.TargetProperty="Opacity" BeginTime="0:0:2.2" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="b2" Storyboard.TargetProperty="Opacity" BeginTime="0:0:2.2" To="0" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="b12" Storyboard.TargetProperty="Background.RelativeTransform.Angle" By="180" Duration="0:0:2" BeginTime="0:0:2.2"/>
<!-- Reset -->
<DoubleAnimation Storyboard.TargetName="b1" Storyboard.TargetProperty="Opacity" BeginTime="0:0:4.2" To="0" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="b2" Storyboard.TargetProperty="Opacity" BeginTime="0:0:4.2" To="0" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="b12" Storyboard.TargetProperty="Opacity" BeginTime="0:0:4.2" To="0" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="b2" Storyboard.TargetProperty="Background.RelativeTransform.Angle" To="0" BeginTime="0:0:4.2" Duration="0:0:0"/>
<DoubleAnimation Storyboard.TargetName="b12" Storyboard.TargetProperty="Background.RelativeTransform.Angle" To="0" Duration="0:0:0" BeginTime="0:0:4.2"/>
<DoubleAnimation Storyboard.TargetProperty="Width" To="280" BeginTime="0:0:4.2" Duration="0:0:.2"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="b3" Storyboard.TargetProperty="Opacity" BeginTime="0:0:4.2" To="1" Duration="0:0:0"/>
<DoubleAnimation Storyboard.TargetName="b3_" Storyboard.TargetProperty="Opacity" BeginTime="0:0:4.2" To="1" Duration="0:0:.1"/>
<DoubleAnimation Storyboard.TargetName="b3" Storyboard.TargetProperty="Background.RelativeTransform.ScaleX" To="1" Duration="0:0:.2" BeginTime="0:0:4.2"/>
<DoubleAnimation Storyboard.TargetName="b3" Storyboard.TargetProperty="Background.RelativeTransform.ScaleY" To="1" Duration="0:0:.2" BeginTime="0:0:4.2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition SourceName="b1" Property="Opacity" Value="0"/>
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FF1ECD97" Duration="0:0:.3">
</ColorAnimation>
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="White" Duration="0:0:.3">
</ColorAnimation>
<ThicknessAnimation Storyboard.TargetProperty="BorderThickness" To="0" Duration="0:0:0">
</ThicknessAnimation>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Transparent" Duration="0:0:.3">
</ColorAnimation>
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="#FF1ECD97" Duration="0:0:.3">
</ColorAnimation>
<ThicknessAnimation Storyboard.TargetProperty="BorderThickness" To="2" Duration="0:0:0">
</ThicknessAnimation>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
I am trying to animate a clipping path. I read from Mask Animations (Clipping Path Animations) In Silverlight Without a Line of Code that I should animate the clipping path 1st so
Data=”M159.67175,104.26108 L177.91812,28.328932 L195.51648,104.43327 L255.0802,102.6104 L206.86984,151.82758 L225.8029,226.56477 L179.0616,179.17046 L129.73396,229.29906 L147.97842,150.63879 L98.650803,101.53297 z”
will be changed to
<Path.Data>
<PathGeometry>
<PathFigure IsClosed=”True” StartPoint=”91.0527648925781,84.0121078491211?>
<LineSegment Point=”118.057907104492,0.549586236476898?/>
<LineSegment Point=”144.103973388672,84.2013778686523?/>
<LineSegment Point=”232.259979248047,82.1977386474609?/>
<LineSegment Point=”160.907287597656,136.2958984375?/>
<LineSegment Point=”188.928756713867,218.444961547852?/>
<LineSegment Point=”119.750289916992,166.350433349609?/>
<LineSegment Point=”46.7439804077148,221.450408935547?/>
<LineSegment Point=”73.7462997436523,134.989212036133?/>
<LineSegment Point=”0.740016639232636,81.0134506225586?/>
</PathFigure>
</PathGeometry>
</Path.Data>
but after animating the path, my XAML still looks like
<Path x:Name="path" Data="M0.5,0.5 L84.5,0.5 L84.5,150.5 L0.5,150.5 z" HorizontalAlignment="Left" Height="151" Margin="76,55,0,0" Stretch="Fill" Stroke="{x:Null}" VerticalAlignment="Top" Width="85" Fill="Black" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
A short video on the problem http://screenr.com/1Wc
You need to create the clipping path prior to doing the animation.
Then, use the Direct Select tool (the second arrow down on the toolbar in Blend 4) to select the clipping path. Moving the clipping path while recording a timeline will result in the clipping being animated the way you expect.
Here's the XAML from two rectangles - a big one with a linear gradient, and a smaller one that is the clipping path. The clipping rectangle is animated and follows the gradient.
<UserControl
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"
x:Class="WpfSplash.TemplatePanel"
x:Name="UserControl" Height="1000" Width="544">
<UserControl.Resources>
<Storyboard x:Key="OnLoaded1">
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Clip).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(LineSegment.Point)" Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:1" Value="495,184.5"/>
</PointAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Clip).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(LineSegment.Point)" Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:1" Value="-14.9999999999998,184.5"/>
</PointAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Clip).(PathGeometry.Figures)[0].(PathFigure.StartPoint)" Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:1" Value="-14.9999999999998,142.5"/>
</PointAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Clip).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(LineSegment.Point)" Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:1" Value="495,142.5"/>
</PointAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
</EventTrigger>
</UserControl.Triggers>
<Canvas x:Name="LayoutRoot">
<Rectangle x:Name="rectangle" Height="207" Canvas.Left="33" Canvas.Top="106.5" Width="481.5">
<Rectangle.Clip>
<PathGeometry>
<PathFigure IsClosed="True" StartPoint="-15,16.5">
<LineSegment Point="495,16.5"/>
<LineSegment Point="495,54"/>
<LineSegment Point="-15,54"/>
</PathFigure>
</PathGeometry>
</Rectangle.Clip>
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFD6904A" Offset="1"/>
<GradientStop Color="#FFEBD8FF"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Canvas>
I have an Ellipse inside another control that gets its Fill changed when the parent is selected.
<Style TargetType="TabItem">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid MinWidth="150">
<Border BorderBrush="Transparent" BorderThickness="0">
<StackPanel Orientation="Vertical">
<ContentPresenter HorizontalAlignment="Center" ContentSource="Header" />
<Ellipse Name="Ellipse" Stroke="Black" StrokeThickness="1" Width="24" Height="24" Margin="5">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
<GradientStop x:Name="FirstGradient" Color="Transparent" Offset="0.3" />
<GradientStop x:Name="SecondGradient" Color="Transparent" Offset="0.75" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
</StackPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="FirstGradient" Storyboard.TargetProperty="Color"
From="Transparent" To="#FF9221" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="SecondGradient" Storyboard.TargetProperty="Color"
From="Transparent" To="#FFCFA5" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Works fine. What I've not managed to do though is to change the Fill back to default when the parent is no longer selected. How do I do that?
if you are looking for tabcontrol style
just see if this can help you out in some way.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication16.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="Transparent"/>
<SplineColorKeyFrame KeyTime="00:00:00.5000000" Value="#00FE3737"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Ellipse" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="Transparent"/>
<SplineColorKeyFrame KeyTime="00:00:00.5000000" Value="#FFFF2525"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid MinWidth="150">
<Border BorderBrush="Transparent" BorderThickness="0">
<StackPanel Orientation="Vertical">
<ContentPresenter HorizontalAlignment="Center" ContentSource="Header" />
<Ellipse Name="Ellipse" Stroke="Black" StrokeThickness="1" Width="24" Height="24" Margin="5">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
<GradientStop x:Name="FirstGradient" Color="Transparent" Offset="0.3" />
<GradientStop x:Name="SecondGradient" Color="Transparent" Offset="0.75" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
</StackPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Selector.IsSelected" Value="True">
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard1_BeginStoryboard"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard x:Name="Storyboard1_BeginStoryboard" Storyboard="{StaticResource Storyboard1}"/>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<TabControl>
<TabItem Header="First"></TabItem>
<TabItem Header="Second" IsSelected="true"></TabItem>
<TabItem Header="Last"></TabItem>
</TabControl>
</Grid>
The problem was that I had defined the default look of the Ellipse within the template,
<Ellipse Name="Ellipse" Stroke="Black" StrokeThickness="1" Width="24" Height="24" Margin="5">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
<GradientStop x:Name="FirstGradient" Color="Transparent" Offset="0.3" />
<GradientStop x:Name="SecondGradient" Color="Transparent" Offset="0.75" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
This caused so that when a TabItem no longer was selected, it didn't change back to it's default look.
To solve this I just TemplateBind the Ellipse.Fill to the Background of the TabItem.
Try with adding that:
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="FirstGradient" Storyboard.TargetProperty="Color"
To="Transparent" From="#FF9221" Duration="0:0:0" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="SecondGradient" Storyboard.TargetProperty="Color"
To="Transparent" From="#FFCFA5" Duration="0:0:0" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
to your Triggers