i'am trying to build some animation for tiles in my WPF project home page.
i want to do something like this sample
particularly the "looking for wordpress version" and "Full download" ones
1. Shadow
i try
<DropShadowEffect x:Key="MyEffect" ShadowDepth="0" Color="Red" Opacity="1" BlurRadius="20" Direction="0"/>
for shadow effect but even the inner color change tending to violet
2. for text animation i use this
<TextBlock x:Name="txtStateRunning" Background="Crimson" Text="text" Margin="10">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="TextBlock.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard x:Name="textAnimation">
<StringAnimationUsingKeyFrames Storyboard.TargetName="txtStateRunning" Duration="0:0:5"
Storyboard.TargetProperty="Text" RepeatBehavior="Forever" AutoReverse="False" >
<DiscreteStringKeyFrame Value="text 1" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="text 2" KeyTime="0:0:0.5" />
<DiscreteStringKeyFrame Value="text 3" KeyTime="0:0:2" />
<DiscreteStringKeyFrame Value="text 4" KeyTime="0:0:3.5" />
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
but the effect is instantaneous while i search for the entering effect
3. in the "download" of the example the color change gradually, how can be done?
Related
Basically I have a WPF datagrid, and I want to add a flashing outline to a specific cell in XAML via binding that will make this visible. I know how to do this except the flashing part.
How can I do that so that the rectangle outline flashes for a specific duration like 2 seconds, so it goes from opacity = 0 to 1 and then 0 and so on.
Does WPF have a mechanism for this?
<Border BorderThickness="1" BorderBrush="Red">
<Rectangle Fill="#FF5A9AE0"
Stretch="UniformToFill"
ClipToBounds="True"/>
</Border>
This will flash the border on and off.
<Border Name="MyBorder" BorderThickness="1" BorderBrush="Red">
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimationUsingKeyFrames
Storyboard.TargetName="MyBorder"
Storyboard.TargetProperty="BorderThickness"
AutoReverse="True" RepeatBehavior="Forever">
<DiscreteThicknessKeyFrame KeyTime="0:0:00.00" Value="1" />
<DiscreteThicknessKeyFrame KeyTime="0:0:00.25" Value="5" />
<DiscreteThicknessKeyFrame KeyTime="0:0:00.50" Value="1" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Rectangle Fill="#FF5A9AE0" Stretch="UniformToFill" ClipToBounds="True" />
</Border>
There are lots of animation options, so please have a look at https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/animation-overview?view=netframeworkdesktop-4.8 for details/ideas.
I'm trying to rotate a font icon inside a button 90° in the first click and back to 0° on the second click.
Currently I have:
<Page.Resources>
<Storyboard x:Name="RotateButton90Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="0"
To="90"
Duration="350" />
</Storyboard>
</Page.Resources>
<Button
x:Name="ShowSubTasks_Button"
Background="Transparent">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButton90Degrees}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<FontIcon
FontFamily="Segoe MDL2 Assets"
Glyph=""
RenderTransformOrigin="0.5, 0.5">
<FontIcon.RenderTransform>
<RotateTransform x:Name="ShowSubTasks_ButtonRotateTransform" />
</FontIcon.RenderTransform>
</FontIcon>
</Button>
The problem is that the app crashes when I click the button (it's not finding the ShowSubTasks_ButtonRotateTransform). The second is that I don't know how to revert the rotation effect after the first click (first click -> 90°, second click -> 0°, third click -> 90° and so on).
Any help would be appreciated.
Ok i got the problem, the thing is that im running all that code inside a DataTemplate ... So that explains why its crashing. For the fix i used what #Dishant suggested, created two storyboards and with a DataTriggerBehavior i change the angle of the rotate transform
<StackPanel.Resources>
<Storyboard x:Name="RotateButtonTo90Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="0"
To="90"
Duration="0:0:0.1" />
</Storyboard>
<Storyboard x:Name="RotateButtonTo0Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="90"
To="0"
Duration="0:0:0.1" />
</Storyboard>
</StackPanel.Resources>
<Button
Background="Transparent"
Visibility="{Binding HasSubTasks, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding ShowSubTasks, Mode=OneWay}" Value="True">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButtonTo90Degrees}" />
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding ShowSubTasks, Mode=OneWay}" Value="False">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButtonTo0Degrees}" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<FontIcon
FontFamily="Segoe MDL2 Assets"
Glyph=""
RenderTransformOrigin="0.5, 0.5">
<FontIcon.RenderTransform>
<RotateTransform x:Name="ShowSubTasks_ButtonRotateTransform" />
</FontIcon.RenderTransform>
</FontIcon>
</Button>
Also as #MartinZikmund suggested, i needed to change the duration from 350 to something like 0:0:0.5
In my case the app does not crash, but the icon does not rotate, because the duration is set to 350, which basically means 350 hours. If you change this value to something like 0:0:0.5, it should rotate in 0.5 seconds. To do the reverse animation, you would probably need to set the animation target programatically, but in such case you could just run the storyboard itself in the Click event handler.
If you are targeting Windows 10 15063 or higher, you can use Implicit Animations in XAML. In that case you could set up an implicit animation on the rotation of the icon and then just set the rotation property in the code-behind accordingly and implicit animation would take care of the animation itself.
I defined a Polygon like this:
<!-- Draws a hexagon by specifying the vertices of a polygon -->
<Polygon x:Name="polygon"
Points="0,50 0,120 50,170 120,170 170,120 170,50 120,0 50,0"
Margin="25, 0, 25, 25"
Stroke="Red"
RenderTransformOrigin="0.5,0.5">
<Polygon.RenderTransform>
<CompositeTransform />
</Polygon.RenderTransform>
<Polygon.Fill>
<ImageBrush x:Name="imageBrush"
ImageSource="Assets/image1.jpg"
Stretch="Fill">
</ImageBrush>
</Polygon.Fill>
</Polygon>
I also defined a storyboard like this:
<Storyboard x:Name="Storyboard2">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)"
Storyboard.TargetName="polygon">
<EasingDoubleKeyFrame KeyTime="0"
Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2"
Value="-360" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
I start the polygon rotation like this:
Storyboard2.BeginTime = new TimeSpan( 0 );
Storyboard2.Begin();
The above code rotate the whole polygon as expected. However I would like to modify it, and to have the polygon stationary and just to rotate the bitmap inside the polygon.
How do I do that?
Thx
To rotate the image inside your polygon, you can try with ImageBrush.RelativeTransform property like following:
<Polygon x:Name="polygon"
Margin="25, 0, 25, 25"
Points="0,50 0,120 50,170 120,170 170,120 170,50 120,0 50,0"
Stroke="Red">
<Polygon.Fill>
<ImageBrush x:Name="imageBrush" ImageSource="Assets/Capture.PNG" Stretch="Fill">
<ImageBrush.RelativeTransform>
<CompositeTransform CenterX="0.5" CenterY="0.5" />
</ImageBrush.RelativeTransform>
</ImageBrush>
</Polygon.Fill>
</Polygon>
And change your Storyboard like following:
<Storyboard x:Name="Storyboard2">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="imageBrush"
Storyboard.TargetProperty="(Brush.RelativeTransform).(CompositeTransform.Rotation)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="-360" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Here, as the target is ImageBrush, so we need to change Storyboard.TargetProperty to (Brush.RelativeTransform).(CompositeTransform.Rotation). And as the animation targets Brush.RelativeTransform, so it's a dependent animation. We need to set EnableDependentAnimation property to true to enable this animation. For more info about dependent animation, please see Dependent and independent animations.
After this, you can call Storyboard2.Begin(); to start the animation.
Since I can't test on a UWP enviro at the moment, here's how it's done in WPF, same concept...but I'm thinking the syntax may be a little different, hence why I wanted to test.
Storyboard:
<Storyboard x:Key="SpinThisBugger" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="polygon">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="360"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Trigger to start it:
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource SpinThisBugger}"/>
</EventTrigger>
</Window.Triggers>
The Poly:
<Polygon x:Name="polygon"
Points="0,50 0,120 50,170 120,170 170,120 170,50 120,0 50,0"
HorizontalAlignment="Center" VerticalAlignment="Center"
Stroke="Red"
RenderTransformOrigin="0.5,0.5">
<Polygon.Fill>
<ImageBrush x:Name="imageBrush"
ImageSource="Images/learn-hypnosis.jpg"
Stretch="Fill">
<ImageBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterY="0.5" CenterX="0.5"/>
<SkewTransform CenterY="0.5" CenterX="0.5"/>
<RotateTransform CenterY="0.5" CenterX="0.5"/>
<TranslateTransform/>
</TransformGroup>
</ImageBrush.RelativeTransform>
</ImageBrush>
</Polygon.Fill>
</Polygon>
...and the image I used, since it was nifty lol:
I'd like to create a glimmer animation on path's stroke in the direction of the path
My code looks like this:
<Path StrokeThickness="2">
<Path.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard Duration="0:0:3" RepeatBehavior="Forever">
<DoubleAnimation
Storyboard.TargetName="firstGradientStop"
Storyboard.TargetProperty="Offset"
From="-0.2" To="1.0" Duration="0:0:2" />
<DoubleAnimation
Storyboard.TargetName="middleGradientStop"
Storyboard.TargetProperty="Offset"
From="-0.1" To="1.1" Duration="0:0:2" />
<DoubleAnimation
Storyboard.TargetName="lastGradientStop"
Storyboard.TargetProperty="Offset"
From="0" To="1.2" Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
<Path.Stroke>
<LinearGradientBrush>
<GradientStop Color="#80000000" x:Name="firstGradientStop" Offset="0.4" />
<GradientStop Color="White" x:Name="middleGradientStop" Offset="0.5" />
<GradientStop Color="#80000000" x:Name="lastGradientStop" Offset="0.6" />
</LinearGradientBrush>
</Path.Stroke>
<Path.Data>
<!-- dynamic data here, sample path below -->
<GeometryGroup>
<LineGeometry StartPoint="0,0" EndPoint="100,100" />
<LineGeometry StartPoint="100,100" EndPoint="200,100" />
</GeometryGroup>
</Path.Data>
</Path>
the problem is that the animation is independent of the direction of path and I need the glow to go in the direction from StartPoint to EndPoint. Is this achievable?
You can use StartPoint and EndPoint of linearGradientBrush, something like that (play with values, so you can rotate angle of gradient like you want whenever you want):
<PointAnimation
Storyboard.TargetName="Brush"
Storyboard.TargetProperty="StartPoint"
From="0,0" To="0.5,0" Duration="0:0:1.5" />
<PointAnimation
Storyboard.TargetName="Brush"
Storyboard.TargetProperty="EndPoint"
From="1,1" To="0.5,1" Duration="0:0:1.5" />
But it's not a solution for complex dynamic path. (And that's limitations of stroke cause it's nothing more than background and you can't glimmer with it self-intersecting paths)
If you need more, then create a simple UserControl that will represent just a straight line with proper animation. After that you need to add that controls(with proper rotateTransform) to canvas from codeBehind iterating by path structure and set needed storyboards timeline. That would be a complete solution.
is it possible to create a c# animation for the AttachedPropertys like Alignment? Maybe 1 Second Move between the Change from HorizontalAlignment.Left to HorizontalAlignment.Right - is it possible?
Thanks a lot.
You can't animate it in the sense of producing a smooth animation where something slides from left to right since they are discrete states. There aren't any in-between values. It is possible to create an "animation" which changes the alignment at some point from left to right, it just won't slide across. You could also do a lot of work and measure all the controls to manually create an animation which moves something from one side of the screen to the other using things like Canvas.Left or margins to position the controls.
The attached property part is not an issue, just use the full name of the attached property in the target property part of your animation.
While it's not possible to directly animate smoothly between two properties like
HorizontalAlignment="Right" VerticalAlignment="Bottom"
to
HorizontalAlignment="Center" VerticalAlignment="Center"
I did come up with a way to do this for an app in a way that I thought might be worth sharing. I simply placed the control in a grid that took up the full pane of the window. I aligned the control to the bottom right of the grid. Then I animated the grid with to transform and scale the corner down that I need to the point I want to align the control too (center in this example. See the complete code below.
<Grid Margin="5,5,14,70" Visibility="{Binding Path=AdminModeIsEnabled, Converter={StaticResource CollapsedVisibilityConverter}, FallbackValue=Visible}">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform/>
</Setter.Value>
</Setter>
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform/>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding CenterPanel}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(LayoutTransform).(ScaleTransform.ScaleY)" To="2" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)" To=".5" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(LayoutTransform).(ScaleTransform.ScaleX)" To="2" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleX)" To=".5" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(LayoutTransform).(ScaleTransform.ScaleY)" To="1" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)" To="1" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(LayoutTransform).(ScaleTransform.ScaleX)" To="1" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleX)" To="1" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Image Height="15" Source="\Images\Test.png" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
</Grid>
It is possible, here is an example:
class StoryBoardManager : System.Windows.Media.Animation.Storyboard
{
public void ChangeRectangleAlignment(DependencyObject target, VerticalAlignment verticalAlignment, HorizontalAlignment horizontalAlignment, int BeginTimeMillisecond)
{
ObjectAnimationUsingKeyFrames objectAnimation = new ObjectAnimationUsingKeyFrames()
{
BeginTime = TimeSpan.FromMilliseconds(0)
};
Storyboard.SetTarget(objectAnimation, target);
Storyboard.SetTargetProperty(objectAnimation, new PropertyPath("(FrameworkElement.HorizontalAlignment)"));
DiscreteObjectKeyFrame keyFrame = new DiscreteObjectKeyFrame(horizontalAlignment, TimeSpan.FromMilliseconds(BeginTimeMillisecond));
objectAnimation.KeyFrames.Add(keyFrame);
this.Children.Add(objectAnimation);
}
}
For more information, see this other question.