Reputation: 193
I am trying to create an animation where I want to rotate a circle by specific angle while translating.(Basically to create a wheel rolling on a surface). I want to control the angle of rotation of the wheel . How do I achieve this using per frame based animation.
<Window x:Class="WheelOnPath.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1000" Width="1000" WindowState="Maximized" WindowStartupLocation="CenterScreen">
<Border BorderBrush="Gray" BorderThickness="1" Margin="4">
<Canvas>
<Path >
<Path.Fill>
<LinearGradientBrush>
<GradientStop Color="Purple" Offset="0.5"/>
<GradientStop Color="LightPink" Offset="0.5"/>
</LinearGradientBrush>
</Path.Fill>
<Path.Data>
<EllipseGeometry x:Name="rotateEllipse"
RadiusX="90" RadiusY="90"
Center="100,380">
</EllipseGeometry>
</Path.Data>
</Path>
</Canvas>
</Border>
</Window>
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Threading;
namespace WheelOnPath
{
public partial class MainWindow : Window
{
double time = 0, dt = 0;
TimeSpan lastRender = new TimeSpan();
public MainWindow()
{
InitializeComponent();
lastRender = TimeSpan.FromTicks(DateTime.Now.Ticks);
CompositionTarget.Rendering += StartRolling;
}
private void StartRolling(object sender,EventArgs e)
{
RenderingEventArgs ra = (RenderingEventArgs)e;
dt = (ra.RenderingTime - lastRender).TotalSeconds;
lastRender = ra.RenderingTime;
double x = rotateEllipse.Center.X + 10;
rotateEllipse.Center = new Point(x, rotateEllipse.Center.Y);
*RotateTransform rt = new RotateTransform(45);
rt.CenterX = 90;
rt.CenterY = 90;
rotateEllipse.Transform = rt;*
time += dt;
}
}
}
Upvotes: 0
Views: 1422
Reputation: 128147
The rotation angle is calculated by dividing the translated path (here in x direction) by the wheel radius.
An easy way to combine translation and rotation is to use a TransformGroup
with a RotateTransform
and a TranslateTransform
for the the Path's RenderTransform
(instead of setting the center of the EllipseGeometry):
<Path>
<Path.Fill>
<LinearGradientBrush>
<GradientStop Color="Purple" Offset="0.5"/>
<GradientStop Color="LightPink" Offset="0.5"/>
</LinearGradientBrush>
</Path.Fill>
<Path.Data>
<EllipseGeometry x:Name="rotateEllipse" RadiusX="90" RadiusY="90"/>
</Path.Data>
<Path.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="rotateTransform"/>
<TranslateTransform x:Name="translateTransform" X="100" Y="100"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
Code behind:
public partial class MainWindow : Window
{
private double startX;
public MainWindow()
{
InitializeComponent();
startX = translateTransform.X;
CompositionTarget.Rendering += RollWheel;
}
private void RollWheel(object sender, EventArgs e)
{
translateTransform.X += 1.0; // calculate appropriate time-dependent value here
rotateTransform.Angle = (translateTransform.X - startX) / rotateEllipse.RadiusX
* 360 / Math.PI;
}
}
Upvotes: 1