I'm experimenting with WPF animations, and I'm a bit stuck. Here's what I need to do:
MouseOver:
Fade In (0% to 100% opacity in 2 seconds)
MouseOut:
Pause for 2 seconds
Fade Out (100% to 0% opacity in 2 seconds)
I've got the Fade In and Fade Out effects, but I can't figure out how to implement the Pause, or even if it's possible.
Here's some XAML that shows how to do what you're after (you can paste the entire thing into Kaxaml to try it out:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Background="Red">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="1" To="0"
Duration="0:00:02"
BeginTime="0:00:02" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Grid.Triggers>
</Grid>
</Page>
The trick is to use the BeginTime propertly of the DoubleAnimation class.
Related
How i can enlarge an Ellipse in WPF, preffering using Margins, just like i did in my wrong code :D ? how i can do that, you will understand from the "wrong code"
<DoubleAnimation Duration="00:00:01" Storyboard.TargetProperty="Margin" From="789,-189,762,899" To="23,-189,-4,-637"/>
http://i.stack.imgur.com/Ryn31.png
Use ThicknessAnimation instead of DoubleAnimation :)
I tried enlarging an Ellipse by altering Margin values but did not see any visual change.
I see this question already has been answered, in any case, here is an example of how it is possible to animate the height and Width of an Ellipse in WPF using markup in XAML:
<Ellipse Height="100" Width="100" Fill="Blue" Stroke="Black">
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetProperty="Width" From="100" To="300" Duration="00:00:02" />
<DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetProperty="Height" From="100" To="300" Duration="00:00:02" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
I want to animate my window coming in from the right edge of the screen.
This is my xaml
<Window x:Class="SidebarTest.DockWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DockWindow" Width="275"
ShowInTaskbar="False"
WindowStyle="None" ResizeMode="NoResize"
AllowsTransparency="True" Background="Transparent" >
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:1.5" Storyboard.TargetProperty="Width" From="0" To="275" AccelerationRatio=".1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid Background="#2F2F2F">
</Grid>
But it animates the width from left to right instead of right to left.
Like this:
How can I change this so it comes in from the edge?
In your codebehind,
public DockWindow()
{
InitializeComponent();
this.Left = this.Width + SystemParameters.FullPrimaryScreenWidth;
}
Change your trigger to
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:1.5" Storyboard.TargetProperty="Left" To="10" AccelerationRatio=".1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
Instead of trying to scale the width I might suggest leaving the width fixed and applying a TranslateTransform to the Window itself and in effect literally sliding it in from offscreen. A quick and dirty example provided below, you'll likely want to play with the value of the X coordinate and the KeyTime to get the effect just right but hopefully this is helpful to you. Cheers
<Window.RenderTransform>
<TranslateTransform x:Name="SlideTheThingy" X="1000" />
</Window.RenderTransform>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SlideTheThingy"
Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:1.25" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
Windows are positioned by their Top-Left corner. So, when you animate your width and the position stays constant, the window will naturally grow to the right
In order to have the effect you're looking for, you also need to animate the position of the Window using the .Left property. If you want to snap the window to the right side of the screen and slide in from there, you need to start animating with a value of Left that matches your screen's width (and a zero-pixel width), and then animate to screenWidth - finalWidthOfWindow.
I actually figured it out, I needed to set the horizontal Alignment to right of the component I wanted to animate the size of. And it worked like a charm!
I would like to zoom in on a Image when Image.MouseEnter fires and then zoom out when Image.MouseLeave fires.
I thought of creating a Trigger, but no luck.
This is what i tried so far:
<Image Name="logo" Source="{Binding Path=ImagePath}"
Width="50" Height="50">
<Image.RenderTransform>
<ScaleTransform x:Name="TransRotate" />
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Image.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TransRotate"
Storyboard.TargetProperty="ScaleX"
From="0" To="100"
BeginTime="0:0:0"
Duration="0:0:10"
AutoReverse="False"/>
<DoubleAnimation Storyboard.TargetName="TransRotate"
Storyboard.TargetProperty="ScaleY"
From="0" To="100"
BeginTime="0:0:0"
Duration="0:0:10"
AutoReverse="False"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
Is this the correct way, or is there a better way?
I would remove the From property, this makes the animation jump, apart from that you just seem to be lacking the reverse animations on MouseLeave. Also to center the zoom you can set the RenderTransformOrigin of the Image to 0.5,0.5.
Instead of using those two events i usually prefer a trigger on IsMouseOver with Enter and ExitActions.
If you want to retain the space the image takes you can place it in a container with fixed size and set ClipToBounds to true.
I've got a canvas control that grows in height when you move the mouse over it and shrinks back on mouse leave.
<Canvas x:Name="infoBar" Width="720" Height="39" Background="Red">
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="infoBar"
Storyboard.TargetProperty="Height"
From="39" To="255" Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Canvas.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="infoBar"
Storyboard.TargetProperty="Height"
From="255" To="39" Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<StackPanel>
<TextBlock/>
<TextBlock/>
</StackPanel>
</Canvas>
This works fine. However if two quick consecutive events take place (mouseleave before mouse enter animation finishes) it goes nuts.
Is there anyway i can tell it to cancel out any other events that happen before an animation finishes?
Using your event triggers you can perform pause, stop, resume, etc. commands on named storyboards.
This article should answer your questions.
Why does the following animation flicker and act goofy on MouseLeave? If it can be repro-ed, I'll post a screencast.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas>
<Path Fill="Blue" Margin="15,15,15,15">
<Path.Data>
<!-- Describes an ellipse. -->
<EllipseGeometry x:Name="MyAnimatedEllipseGeometry" Center="200,100" RadiusX="15" RadiusY="15" />
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard>
<Storyboard Duration="0:0:.5">
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry"
Storyboard.TargetProperty="RadiusX"
From="15" To="100" />
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry"
Storyboard.TargetProperty="RadiusY"
From="15" To="100" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<BeginStoryboard>
<Storyboard Duration="0:0:.5">
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry"
Storyboard.TargetProperty="RadiusX"
From="100" To="15" />
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry"
Storyboard.TargetProperty="RadiusY"
From="100" To="15" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>
</Page>
The reason is that you specify a From on your DoubleAnimations.
If the radius is anything less than 100 when MouseLeave happens, the From property will make it jump up to 100 and likely cause a MouseEnter. Then, you have two competing animations and the mouse events go crazy as the ellipse radius flickers underneath the cursor.
The solution is to just omit the From properties, this will cause the animation to start from wherever the current radius is:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1">
<Canvas>
<Path Margin="15,15,15,15" Fill="Blue">
<Path.Data>
<!-- Describes an ellipse. -->
<EllipseGeometry x:Name="MyAnimatedEllipseGeometry" Center="200,100" RadiusX="15" RadiusY="15"/>
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry" Duration="0:0:.5" Storyboard.TargetProperty="RadiusX" To="100"/>
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry" Duration="0:0:.5" Storyboard.TargetProperty="RadiusY" To="100"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry" Duration="0:0:.5" Storyboard.TargetProperty="RadiusX" To="15"/>
<DoubleAnimation Storyboard.TargetName="MyAnimatedEllipseGeometry" Duration="0:0:.5" Storyboard.TargetProperty="RadiusY" To="15"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>
</Page>
On an unrelated note, when you set Storyboard.Duration, it won't speed up your child animations, it will just end the Storyboard prematurely. You really want to set Duration on your child DoubleAnimations - I've modified the XAML above to do this.
There's always the usual culprits of hardware. But I would suspect that it may have something to do with the time being taken to perform the animation. Try increasing the length of time the animation runs, or adjusting the size of the values you are moving between.
half a second is not much time to transition from 100 to 15 and vice versa, so you may just be running into not having a smooth enough transition, resulting in a choppy animation. Remember that time is key and that your target should be at least 30 fps for a smooth animation.