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:
Related
In my WPF application I have an animation of a certain element. The element to be animated looks like this.
<Path x:Name="theX" StrokeThickness="7" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Data>
<GeometryGroup>
<LineGeometry StartPoint="4, 4" EndPoint="60, 60"/>
<LineGeometry StartPoint="4, 60" EndPoint="60, 4"/>
</GeometryGroup>
</Path.Data>
</Path>
The color of the LineGeometry elements should be animated, but I don't know how the Storyboard.TargetProperty path is resolved. In this case the GeometryGroup element causes problems. How is the GeometryGroup element accommodated in the path of the Storyboard.TargetProperty, see the three "???".
I've already tried the following:
...).GeometryGroup.(... ...).(GeometryGroup.Children).(... ...).GeometryCollection.(... ... also i've tried that (Path.Stroke).(SolidColorBrush.Color)
<ColorAnimationUsingKeyFrames BeginTime="0:0:1" Duration="0:0:1"
Storyboard.TargetName="theX"
Storyboard.TargetProperty="(Path.Stroke).???.(SolidColorBrush.Color)"
FillBehavior="Stop">
<DiscreteColorKeyFrame Value="#333333" KeyTime="0:0:0"/>
<LinearColorKeyFrame Value="#6AFF00" KeyTime="0:0:0.2"/>
<DiscreteColorKeyFrame Value="#6AFF00" KeyTime="0:0:0.5"/>
<LinearColorKeyFrame Value="#333333" KeyTime="0:0:0.9"/>
</ColorAnimationUsingKeyFrames>
The Geometry-elements are part of a DataTemplat of an ItemsControl with data binding. And I get an exception on the .NET property linked via data binding.
The translation of the exception:
System.InvalidOperationException: "Not all property references in property path" (0) .GeometryGroup. (1) "can be resolved. Make sure that suitable objects support the properties."
In the application there is a similar element, an EllipseGeometry, in which the animation works in this way. The difference is the GeometryGroup element.
<Path x:Name="theO" StrokeThickness="6" Stroke="Transparent">
<Path.Data>
<EllipseGeometry Center="25, 25" RadiusX="22" RadiusY="22"/>
</Path.Data>
</Path>
<ColorAnimationUsingKeyFrames BeginTime="0:0:1" Duration="0:0:1"
Storyboard.TargetName="theO"
Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)"
FillBehavior="Stop">
<DiscreteColorKeyFrame Value="#333333" KeyTime="0:0:0"/>
<LinearColorKeyFrame Value="#FF4F00" KeyTime="0:0:0.2"/>
<DiscreteColorKeyFrame Value="#FF4F00" KeyTime="0:0:0.5"/>
<LinearColorKeyFrame Value="#333333" KeyTime="0:0:0.9"/>
</ColorAnimationUsingKeyFrames>
Many thanks for the help.
Notice in the working example you have a transparent brush set to the Stroke property.
But in the first example, nothing is set to this property.
Hence it is null.
And null has no properties to animate them.
You can explicitly set SolidColorBrush instance in this property, give this instance a name, and access its Color property directly.
It will be much easier than all these casts.
Example:
<Path x:Name="theX" StrokeThickness="7" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Stroke>
<SolidColorBrush x:Name="PathStroke" Color="Transparent"/>
</Path.Stroke>
<Path.Data>
<GeometryGroup>
<LineGeometry StartPoint="4, 4" EndPoint="60, 60"/>
<LineGeometry StartPoint="4, 60" EndPoint="60, 4"/>
</GeometryGroup>
</Path.Data>
</Path>
<ColorAnimationUsingKeyFrames BeginTime="0:0:1"
Duration="0:0:1"
Storyboard.TargetName="PathStroke"
Storyboard.TargetProperty="Color"
FillBehavior="Stop">
<DiscreteColorKeyFrame Value="#333333" KeyTime="0:0:0"/>
<LinearColorKeyFrame Value="#6AFF00" KeyTime="0:0:0.2"/>
<DiscreteColorKeyFrame Value="#6AFF00" KeyTime="0:0:0.5"/>
<LinearColorKeyFrame Value="#333333" KeyTime="0:0:0.9"/>
</ColorAnimationUsingKeyFrames>
Given the following :
<Viewbox>
<Foo:Bar
x:FieldModifier="private"
x:Name="fooBar"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5">
<Foo:Bar.RenderTransform>
<TransformGroup>
<ScaleTransform
x:FieldModifier="private"
x:Name="xfScale"/>
<RotateTransform
x:FieldModifier="private"
x:Name="xfRotate"/>
</TransformGroup>
</Foo:Bar.RenderTransform>
<Foo:Bar.Style>
<Style TargetType="{x:Type Foo:Bar}">
<Style.Triggers>
<DataTrigger
Binding="{
Binding Flip,
RelativeSource={
RelativeSource AncestorType={
x:Type local:myFooBar}}}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty=""/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Foo:Bar.Style>
</Foo:Bar>
</Viewbox>
Which is for a new component that is basically a fancy label stuck inside of a ViewBox (for auto-scaling the label), what do I need to point the Storyboard.TargetProperty at to be able to animate, say, the RotateTransform Angle property?
Your TargetName will need to be set for your xfScale / xfRotate named transforms respectfully.
Your TargetProperty will be the properties of the transforms used.
Like for Scale;
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
and
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
Except that only specifies the Property, you still need to provide a Value to animate to. So in it's entirety, it would become something like;
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="xfScale"
Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0" />
</DoubleAnimationUsingKeyFrames>
Or for Rotate you need your Angle Property. It's worth mentioning, Blend makes this stuff much quicker/easier to do than by hand, especially for complex animations.
Hope this helps, cheers.
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.
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?
Help me plz. I need to animate rotation of the button on z-axis without using external libraries, only with C# and xaml code.
Is that possible? How can I do that?
Thanks.
Have a look at Viewport2DVisual3D
The example in the link does exactly that.
Edit: Here is the example from the link with an added animation of the Z axis
Looks like this
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera Position="0, 0, 4"/>
</Viewport3D.Camera>
<Viewport2DVisual3D x:Name="v2dv3d">
<Viewport2DVisual3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Angle="0" Axis="0, 1, 0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Viewport2DVisual3D.Transform>
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D Positions="-1,1,0 -1,-1,0 1,-1,0 1,1,0"
TextureCoordinates="0,0 0,1 1,1 1,0" TriangleIndices="0 1 2 0 2 3"/>
</Viewport2DVisual3D.Geometry>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
</Viewport2DVisual3D.Material>
<Button Content="Hello, 3D">
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<Rotation3DAnimation Storyboard.TargetName="v2dv3d"
Storyboard.TargetProperty="(Viewport2DVisual3D.Transform).(RotateTransform3D.Rotation)"
Duration="0:0:2"
BeginTime="0:0:0">
<Rotation3DAnimation.From>
<AxisAngleRotation3D Angle="0" Axis="0, 1, 0" />
</Rotation3DAnimation.From>
<Rotation3DAnimation.To>
<AxisAngleRotation3D Angle="90" Axis="0, 1, 0" />
</Rotation3DAnimation.To>
</Rotation3DAnimation>
<Rotation3DAnimation Storyboard.TargetName="v2dv3d"
Storyboard.TargetProperty="(Viewport2DVisual3D.Transform).(RotateTransform3D.Rotation)"
Duration="0:0:2"
BeginTime="0:0:2">
<Rotation3DAnimation.From>
<AxisAngleRotation3D Angle="-90" Axis="0, 1, 0" />
</Rotation3DAnimation.From>
<Rotation3DAnimation.To>
<AxisAngleRotation3D Angle="0" Axis="0, 1, 0" />
</Rotation3DAnimation.To>
</Rotation3DAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Viewport2DVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="#FFFFFFFF" Direction="0,0,-1"/>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
Transformations may help you in this case. Look at here if that helps.
The RotateTransform class is used to rotate a WPF object in an X-Y
plane. It can be applied via XAML or directly via imperative code.
If you only need to rotate your button about the Z axis, then you won't need any 3D graphics. All UIElements (such as Buttons) have the property RenderTransform, which enables basic transformation of their default appearance. By means of Storyboards, WPF allows you to animate almost any dependency property. You can use a storyboard, triggered on load, to animate the Angle property of a RotateTransform applied to the button:
<Button Width="100" Height="100" Content="Wheeee!">
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="ButtonRotation" Storyboard.TargetProperty="Angle">
<DoubleAnimation From="0" To="360" Duration="0:0:3" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
<Button.RenderTransform>
<RotateTransform x:Name="ButtonRotation" CenterX="50" CenterY="50" Angle="45"/>
</Button.RenderTransform>
</Button>
The Viewport2DVisual3D, as recommended by #Meleak, also supports animation, and is fun to play with if you have time. To animate the MSDN example, you need to add a name to the AxisAngleRotation3D element and switch it to target the Z axis:
<AxisAngleRotation3D x:Name="RotateAboutZ" Angle="40" Axis="0, 0, 1" />
Then, as above, trigger a storyboard to begin on the Loaded event of the Viewport3D. In either case, if you need more control over the animation, you can make your storyboard a named resource to be referenced by other events, or even build and control it entirely in code.
More about 2D transforms
More about 3D transforms