Is it possible to animate a LinearGradientBrush in WPF? - wpf

Is it possible to animate the StartPoint or EndPoint of a LinearGradientBrush? If so, what is the type of the Storyboard object used to animate the Points, as when I try the following I get "0,1" is not a valid value for Double, and I do realize I shouldn't be using the DoubleAnimationUsingKeyFrames type.
Current Code:
<UserControl.Triggers>
<EventTrigger RoutedEvent="UserControl.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Path1"
Storyboard.TargetProperty="(Path.Stroke).(LinearGradientBrush.StartPoint)">
<SplineDoubleKeyFrame KeyTime="00:00:0" Value="0,1"/>
<SplineDoubleKeyFrame KeyTime="00:00:2" Value=".5,.5"/>
<SplineDoubleKeyFrame KeyTime="00:00:4" Value="1,0"/>
<SplineDoubleKeyFrame KeyTime="00:00:6" Value=".5,.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Path1"
Storyboard.TargetProperty="(Path.Stroke).(LinearGradientBrush.EndPoint)">
<SplineDoubleKeyFrame KeyTime="00:00:0" Value="1,0"/>
<SplineDoubleKeyFrame KeyTime="00:00:2" Value=".5,.5"/>
<SplineDoubleKeyFrame KeyTime="00:00:4" Value="0,1"/>
<SplineDoubleKeyFrame KeyTime="00:00:6" Value=".5,.5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>

Yes. Just use "PointAnimationUsingKeyFrames" and "SplinePointKeyFrame" in your example above. It should work.

Related

How to use one animation for several controls in Silverlight

Im just studing silverlight(in C#) and i got a problem.
I have 14 rectangles and their width/Height are set to "Auto". I want to creat animation on MouseEnter/MouseLeave. Animation will be just changing the width/Height. I did it using Expression Blend for Silverlight 5, and everything is ok but it made HUGE code. Can i make some resourse animation for all rectangles ?
This is the XAML code made by Blend, and i have 14 such blocks
<Storyboard x:Name="BigTableOne_MouseEnter">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="Table1">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1.04"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="Table1">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1.04"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Name="BigTableOne_MouseLeave">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="Table1">
<EasingDoubleKeyFrame KeyTime="0" Value="1.04"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="Table1">
<EasingDoubleKeyFrame KeyTime="0" Value="1.04"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
All your storyboards have same content besides "Storyboard.TargetName" property.So you can just delete this property and set it at runtime dynamically.
You can find more detail here.

Is this the most straightforward way to handle this functionality?

I've created a button which changes its appearance when in different states, the way I do this (as a single example) when the button is being clicked down on:
<vsm:VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.Background).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="Green"/>
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform). (TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.94"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform). (TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.94"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
Is there a way I could accomplish this using less code? I Just want the scale and colour to both instantly change to green when pressed, is there a way to do it without using keyframes?
Thanks for any help!
This can be written so:
<ColorAnimation Duration="0" To="Green" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.Background).(SolidColorBrush.Color)" />
<DoubleAnimation Duration="0" To="0.94" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" />
<DoubleAnimation Duration="0" To="0.94" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" />
General animations are easier to understand and to use, and there is very few cases when frame animations can be used isnted of general animations.

How to get the animation resource inside a ControlTemplate?

....
<ControlTemplate TargetType="{x:Type CheckBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="OnChecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="slider"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame x:Name="SplineValue"
KeyTime="00:00:00.3000000"
Value="25" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnUnchecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="slider"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="slider"
Storyboard.TargetProperty="(FrameworkElement.Margin)">
<SplineThicknessKeyFrame KeyTime="00:00:00.3000000"
Value="1,1,1,1" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
....
I can get the Resource "OnChecking" in the code behind using the below statement.
Storyboard stb1 = this.Template.Resources["OnChecking"] as Storyboard;
But How can i get the "SplineValue" SplineDoubleKeyFrame inside the Storyboard?
This should work
Storyboard stb1 = chk.Template.Resources["OnChecking"] as Storyboard;
DoubleAnimationUsingKeyFrames animation =
(DoubleAnimationUsingKeyFrames)stb1.Children[0];
var val = ((SplineDoubleKeyFrame)animation.KeyFrames[0]).Value;

Set TargetName dynamically and DoubleAnimationUsingKeyFrames in XAML

i want to know how to change target name dynamicaly with same animation
Please find Below is my code of WPF for xaml and c# code
XAML code
<Storyboard x:Key="deepanshu">
<DoubleAnimationUsingKeyFrames x:Name="gupta"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
Storyboard.TargetName="image1">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0.641"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
Storyboard.TargetName="image1">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0.689"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="image1">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="-1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)"
Storyboard.TargetName="image1">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
c#
Storyboard sb = (Storyboard)FindResource("deepanshu");
Now how to change storyboaname from image1 to image2?
Thanks
Regards,
Deepanshu
Storyboard sb = (Storyboard)FindResource("deepanshu");
foreach (var animation in sb.Children)
{
Storyboard.SetTargetName(animation, "image2");
}
What H.B. said is working perfectly fine. In XAML put storyboard without specifying TargetName like this
<Storyboard x:Key="OpacityUpAnim">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1.3">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
for C# I wrote a custom function to call Animation.
private void RunStoryBoardFromName(string animName, string targetName = null)
{
Storyboard storyBoard = (Storyboard)this.Resources[animName];
if (targetName != null)
{
foreach (var anim in storyBoard.Children)
{
Storyboard.SetTargetName(anim, targetName);
}
}
storyBoard.Begin();
}
then I called it in C# like
RunStoryBoardFromName("OpacityUpAnim", "PopupGrid");

Why does the animation I copied in from Expression Blend to Silverlight VS project only run once?

In my Silverlight application, I want different texts to repeatedly fly in from the right changing colors and getting smaller. The animation works the first time through the loop but not subsequent times.
Here's what I did:
(1) I went into Expression blend, used the "Create Storyboard" tool to create the animation.
then (2) copied the StoryBoard block to my XAML:
<UserControl x:Class="TestWeb124.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="600">
<UserControl.Resources>
<Storyboard x:Key="FadeTextIn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:01.5000000" Value="-111" KeySpline="0,0,0,1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:01.5000000" Value="-88" KeySpline="0,0,0,1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(TextBlock.FontSize)">
<SplineDoubleKeyFrame KeyTime="00:00:01.5000000" Value="14" KeySpline="0,0,0,1"/>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="#FFC24343"/>
<SplineColorKeyFrame KeyTime="00:00:01.5000000" Value="#FF000000" KeySpline="0,0,0,1"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Margin="20">
<TextBlock Height="57" Margin="190,90,133,0" VerticalAlignment="Top" Text="This is a test." TextWrapping="Wrap" FontSize="36" RenderTransformOrigin="0.5,0.5" x:Name="OutputText" Foreground="#FF000000">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
</Grid>
</UserControl>
Then (3) in my code behind I run through a timer loop. The animation works great the first time, but subsequent times there is no animation:
public void Each_Tick(object o, EventArgs sender)
{
if (_secondsElapsed % 5 == 0 || _secondsElapsed == 0)
{
OutputText.Text = String.Format("{0}", _customerFirstNames.ElementAt(_customerNodeIndex));
Storyboard fadeTextIn = (Storyboard)Resources["FadeTextIn"];
fadeTextIn.Begin();
_customerNodeIndex++;
if (_customerNodeIndex > _customerFirstNames.Count() - 1) _customerNodeIndex = 0;
}
_secondsElapsed++;
}
It seems that I need to reset the position of the new piece next piece of text that is supposed to fly it. How do I do that?
<Storyboard x:Name="FadeTextIn">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" KeySpline="0,0,0,1"/>
<SplineDoubleKeyFrame KeyTime="00:00:01.5000000" Value="-111" KeySpline="0,0,0,1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" KeySpline="0,0,0,0"/>
<SplineDoubleKeyFrame KeyTime="00:00:01.5000000" Value="-88" KeySpline="0,0,0,1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(TextBlock.FontSize)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="36" KeySpline="0,0,0,0"/>
<SplineDoubleKeyFrame KeyTime="00:00:01.5000000" Value="14" KeySpline="0,0,0,1"/>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OutputText" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="#FFC24343"/>
<SplineColorKeyFrame KeyTime="00:00:01.5000000" Value="#FF000000" KeySpline="0,0,0,1"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
What the Storyboard is doing is to take an Element and then animate the manipulation of it's properties. That's why the second time it runs the Element already has the target properties, so by adding a keyframe for the start of the animation that sets the values to the initial values your animation will repeat nicely.

Resources