WPF rotating button - c#

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

Related

Dynamically move object on canvas

Scenario as follows.
I have an canvas on which I want to move, lets say an rectangel, across the screen. The way the rectangle is supposed to move is determined by one specific path (like a railway, the rectangle is supposed to only move on the rails). The position on which the rectangle is currently located is provided by external source.
Current Location is provided every ~200-500ms.
So far I have tried the following:
simple TranslateTransform. Does the trick, but the rectangle jumps from Point a to b. No smooth Translation.
Storyboard with a doubleAnimation
Smoother, but the rectangle doesn´t follow the required path.
DoubleAnimationUsingPath. Rectangle is moving on the path. But now I am not able to provide the current position by external source.
Easiest for me would be a way to use an DoubleAnimationUsingPath and providing the X-Koordinate by external source.
But I am not sure if overall storyboards and animations are the best way to tackel that Problem.
If you know of any completely different Approach I am more than happy hear about it.
Kind regards
Just to get an idea of what can be done with animations, take a look at this little demo of a object moving along a track:
<Canvas>
<Canvas.Resources>
<PathGeometry x:Key="track">
<PathFigure StartPoint="200,100" IsClosed="True">
<LineSegment Point="300,100"/>
<ArcSegment SweepDirection="Clockwise"
Size="100,100" Point="300,300"/>
<LineSegment Point="200,300"/>
<ArcSegment SweepDirection="Clockwise"
Size="100,100" Point="200,100"/>
</PathFigure>
</PathGeometry>
</Canvas.Resources>
<Canvas.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<MatrixAnimationUsingPath
Storyboard.TargetName="train"
Storyboard.TargetProperty="RenderTransform.Matrix"
PathGeometry="{StaticResource track}"
DoesRotateWithTangent="True"
Duration="0:0:10"
RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<Path Data="{StaticResource track}" Stroke="Black"
StrokeThickness="6"/>
<Path Data="{StaticResource track}" Stroke="White"
StrokeThickness="4" StrokeDashArray="2,2"/>
<Rectangle x:Name="train" Width="10" Height="6" Fill="Red"
Canvas.Left="-5" Canvas.Top="-3"
RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<MatrixTransform />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>

Rotate image inside a button UWP

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.

How to rotate a bitmap inside a polygon?

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:

WPF 3D object rotating continuously

I am using SplineRotation3DKeyFrame to rotate my 3D object continuously.
But the behavior is somehow queer:
1. there must be two SplineRotation3DKeyFrame inside Rotation3DAnimationUsingKeyFrames, or there will be not animation.
2. it seems the rotation is not continuous. there is always an abrupt movement every period.
And I want to make it rotate at some speed, for example 30 round per minute.
Could any give me some advice how to setup the animation code?
Thanks in advance.
Ting
here is my code (excluding 3D data)
Storyboard.TargetName="World"
Storyboard.TargetProperty="(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation)"
Duration="00:00:02"
AutoReverse="False">
<SplineRotation3DKeyFrame KeyTime="00:00:02">
<SplineRotation3DKeyFrame.Value >
<AxisAngleRotation3D Angle="180" Axis="0,0,1"/>
</SplineRotation3DKeyFrame.Value>
</SplineRotation3DKeyFrame>
<SplineRotation3DKeyFrame KeyTime="00:00:04">
<SplineRotation3DKeyFrame.Value>
<AxisAngleRotation3D Angle="359" Axis="0,0,1"/>
</SplineRotation3DKeyFrame.Value>
</SplineRotation3DKeyFrame>
</Rotation3DAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource RotateStoryboard}"/>
</EventTrigger>
</UserControl.Triggers>
<Grid>
<Viewport3D ClipToBounds="True" Margin="21,15,10,28">
<Viewport3D.Camera>
<OrthographicCamera FarPlaneDistance="291.04190202230194" LookDirection="0,-30,0" NearPlaneDistance="0.1" Position="0,30,0" UpDirection="0,0,-1" Width="50"/>
</Viewport3D.Camera>
<ModelVisual3D x:Name="World">
<ModelVisual3D.Transform> <!-- tinger -->
<Transform3DGroup>
<RotateTransform3D/>
</Transform3DGroup>
</ModelVisual3D.Transform>

WPF tiles animation

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?

Categories