Silverlight animation issue - silverlight

Suppose I have the following XAML snippets, my confusion is what is the meaning of the value for Storyboard.TargetProperty? i.e. the meaning of "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)".
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="p1" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" BeginTime="00:00:00">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.2500000" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
...
<Path Height="2.75" Width="2.75" Data="M2.75,1.375 C2.75,2.1343915 2.1343915,2.75 1.375,2.75 C0.61560845,2.75 0,2.1343915 0,1.375 C0,0.61560845 0.61560845,0 1.375,0 C2.1343915,0 2.75,0.61560845 2.75,1.375 z" Fill="#FF9F9B9B" Stretch="Fill" Stroke="#FF000000" StrokeThickness="0" Canvas.Left="7" Canvas.Top="14" x:Name="p1">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
thanks in advance,
George

The Storyboard.TargetProperty specifies a particular property to change over time.
If you were writing it yourself, you could say something like:
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="myRectange"
Storyboard.TargetProperty="Width" BeginTime="00:00:00">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.2500000" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
and simplify things quite a bit. In the above example, you're changing the "Width" property of your rectangle over time. Blend, in its infinite WYSIWYG fashion, makes the targeting a little more complicated.
In your example, a transform is applied to the rectangle, and you're changing that transform over time.
Clarification:
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
is a PropertyPath. It specifies the property that will be changed over time. In this example, we're targeting the Rectangle's->RenderTransforms->first child (the ScaleTransform)->Scale X property. That's how we say what's going to change. The keyframes specify how that value changes over time.
Something to keep in mind: A transform is a static change. Apply a ScaleX of 2, and the thing doubles in the X dimension. But nothing changes over time (nothing moves on the screen). For that, you need an animation to change the transform over time.
hth, Erik

Related

Animating UserControl

I've made an opacity animation using Blend on one my two UserControls, deleted <UserControl.Resources>, <UserControl.Triggers> and Storyboard.TargetName from that, placed it in App.xaml and it looks like:
<Storyboard x:Key="Loaded">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" >
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
when I call it in code like this before setting the Content of my ContentControl:
Storyboard sb = FindResource("Loaded") as Storyboard;
sb.begin(uc1);
content.Content = uc1;
//and
Storyboard sb = FindResource("Loaded") as Storyboard;
sb.begin(uc2);
content.Content = uc2;
it works as expected. For the transform animation, I've deleted the TransformGroup as well in addition to those above and now it looks like:
<Storyboard x:Key="Unloaded">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="-800"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
If I call it in the same way, I get this error:
System.InvalidOperationException: ''[Unknown]' property does not point to a DependencyObject in path '(0).(1)[3].(2)'.'
How to fix the problem?
You will need to add a RenderTransform to your UserControl which is similar to the Storyboard.TargetProperty which currently expects a TransformGroup with 4th child as TranslateTransform.
Add the below code to each of your two UserControls:
<UserControl x:Class="YourUserControl"
...>
<UserControl.RenderTransform>
<TransformGroup>
<RotateTransform/>
<ScaleTransform/>
<SkewTransform/>
<TranslateTransform/>
</TransformGroup>
</UserControl.RenderTransform>

Animate a Path filling in - Silverlight

Given a closed Path of bezier curves, how would I go about animating it filling in. The fill would have to be non-linear - flowing around an acute angle rather than just a plane uncovering the filled color.
At this point, I'm assuming I'd have to use a WriteableBitmap and do it all myself. thoughts?
A RadialBrush originating from the center and spreading outwards often looks acceptable. See the "Coloring Pages" section of the Kinectimals website for an example.
Another implementation that might work would be to apply the shape to the Path's Clip property, then animate the StrokeThickness property to a very large value.
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<Storyboard x:Name="FillShape">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.StrokeThickness)" Storyboard.TargetName="path">
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="118">
<EasingDoubleKeyFrame.EasingFunction>
<CircleEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Path x:Name="path" Data="M118,128 C182,300 238,342 330,252 C422,162 358,-40.000271 270,37.999855 C182,115.99998 118,128 118,128 z" Margin="117.5,19.95,264.563,181.398" Stretch="Fill" Stroke="Black" UseLayoutRounding="False" Clip="M0.4999969,108.05005 C64.500069,280.04974 120.50012,322.04968 212.50023,232.04984 C304.50034,142.04999 240.50026,-59.949921 152.50015,18.050066 C64.500069,96.050049 0.4999969,108.05005 0.4999969,108.05005 z" StrokeThickness="0"/>
</Grid>

scale animation for wpf popup

I have a nice little popup, when it shows, I d'like it to growth from 0 to 1x scaley,
but I don't get it right, when I click multiple times, it looks like i "catch" the animation at
various states during the "growth".
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.MouseRightButtonDown"
>
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="SimplePopup"
Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Window.Triggers>
and the popup:
<Popup Name="SimplePopup"
AllowsTransparency="True"
StaysOpen="False">
<Popup.LayoutTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1" />
<SkewTransform AngleX="0" AngleY="0" />
<RotateTransform Angle="0" />
<TranslateTransform X="0" Y="0" />
</TransformGroup>
</Popup.LayoutTransform>
<Border> some Content here
</Border>
</Popup>
I'm not sure what you mean by
"catch" the animation at various states during the "growth".
Maybe that it won't finish the animation but restart when you click before storyboard is completed?
If so, you need to prevent the animation from restarting by firing action only when it's not running. I think it can be done with more complex behaviors or triggers available in Blend.
by "catch" the animation at various states during the "growth".
I mean that there is no animation at all, all I see is the static popup
scaled at different sizes, but not a visible animation.

Can I shake a users desktop using WPF?

I'm writing an application for personal use that will track how often I reach for the mouse, and will keep a counter of how long I've gone mouseless. When I use the mouse, I would like it to shake my desktop workspace for a second as a negative reinforcement action.
The application is going to be called WristSlap and will be on github as soon as I have a version 0.1 ready.
Danny is onto something with the transparent window idea. But it doesn't have to be transparent. You would have to accept some certain limitations though.
You would want to grab a screen shot of the desktop and apply it to a full screen WPF window. (Check out my blog for a handy FullScreenBehavior for WPF Window). Then you would just apply some epilepsy-inducing animation to a translate layout transform on the root element. This would give the effect of shaking. At the end the window could just close.
Since during the animation the coordinates of everything will be all over the place, you probably don't want to be bothered with trying to translate mouse clicks on the moving desktop to the underlying control. If the animation is short enough it won't matter because you won't have time to try to click anything while it is shaking.
For more realism you could look into using the DWM (Desktop Window Manager) to project a "live" view of the desktop but that's probably not worth it especially if you keep the animation very short.
I almost want to try this myself for fun.
I came up with this using a static image for now. It's ok but it could be improved.
<Image Source="Slide1.png" Stretch="UniformToFill">
<Image.Effect>
<BlurEffect Radius="5" />
</Image.Effect>
<Image.RenderTransform>
<TranslateTransform Y="0" X="0"/>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="00:00:01" SpeedRatio="15">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="-10"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="10"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.7000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="-10"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="-10"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="10"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.7000000" Value="10"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.9000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
You could create a transparent window with a changing twirl shader effect.
I'm not sure that will solve your addiction to computers though.

Small animations in Silverlight

I've made a simple storyboard that takes a particular ListBoxItem and lets it grow by a factor of 1.3. I'd like to add this animation to every ListBoxItem I create dynamically so that it can be activated when it gets a mouse-over, but the storyboard seems to be hardcoded to that first item:
<Storyboard x:Name="ListItem_MouseEntered">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="RecentNews" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1.3"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="RecentNews" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1.3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
How should I go about duplicating this storyboard and setting the target to every listboxitem?
Cheers
Nik
PS, I believe I have some errors in the animation, don't worry about that, it's not part of my question :-)
You can define a ControlTemplate for ListBoxItem in the Resources section of the UserControl like this:
<ControlTemplate x:Key="LIT" TargetType="ListBoxItem">
<Border x:Name="MainBorder" BorderBrush="Red" BorderThickness="2" Background="Yellow" MouseEnter="Border_MouseEnter">
<Border.Resources>
<Storyboard x:Name="ItemStory">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ItemTransform" Storyboard.TargetProperty="ScaleX">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1.3"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ItemTransform" Storyboard.TargetProperty="ScaleY">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1.3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Border.Resources>
<Border.RenderTransform>
<ScaleTransform x:Name="ItemTransform" />
</Border.RenderTransform>
<TextBlock Text="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
Handle the MouseEnter event:
private void Border_MouseEnter(object sender, MouseEventArgs e)
{
Border itemBorder = (Border)sender;
Storyboard itemStory = (Storyboard)itemBorder.FindName("ItemStory");
itemStory.Begin();
}
And use it like this in XAML:
<ListBox x:Name="MyList">
<ListBox.Items>
<ListBoxItem Content="Toto 1" Template="{StaticResource LIT}" />
</ListBox.Items>
</ListBox>
Or like this in C#:
MyList.Items.Add(new ListBoxItem()
{
Content="Toto 2",
Template = (ControlTemplate)Resources["LIT"]
});
If you use the visual state manager, you can apply this to all of type:
This shows how to do just that.

Resources