Silverlight动画基础五:动画与三角函数
时间:2011-04-12 来源:Nereus
主要介绍下三角学在Silverlight动画中的使用,简单来将就是常见三角函数以及角边关系在动画中的应用。
主要涉及的概念:角度、弧度、正弦、余弦、正切、余切等。
角度
角度用于表示角的度数,更重要 的是与弧度之间的关系。
角度和弧度关系是:1°≈0.0174533弧度,1弧度≈57.29578°。角度与弧度之间的换算公式如下:
1) 弧度=角度×π ÷180
2) 角度=弧度×180÷π
根据这个关系我们便可得出角度与弧度的换算函数,如下:
/// <summary>
/// 根据给定的弧度值换为角度
/// </summary>
/// <param name="Radians">弧度</param>
/// <returns>结果,转换后的角度</returns>
private double RadiansToDegrees(double Radians)
{
double Degrees = Radians * 180 / Math.PI;
return Degrees;
}
/// <summary>
/// 根据给定的角度值转换为弧度
/// </summary>
/// <param name="Degrees">角度</param>
/// <returns>结果,转换后的弧度</returns>
private double DegreesToRadians(double Degrees)
{
double Radians;
Radians = Degrees * Math.PI / 180;
return Radians;
}
弧度:1弧度=弧长等于半径的弧所对应的圆心角(如下图)。弧度是角的度量单位。圆周长的公式为C=2π r,因此根据上面的弧度定义就可以知道圆的一周的弧度为2π。
那么知道了这个关系,我们也就得到了如下的常见角与弧度的关系图:
1弧度=57.3角度(近似)
1角度=0.01745弧度(近似)
明确了角与弧度的关系,我们还需要了解常见的三角函数。
三角函数
常见三角函数,如右图,当平面上的三点A、B、C的连线,、、,构成一个直角三角形,其中为直角。对于与的夹角而言: 对边(opposite) 邻边(adjacent) 斜边(hypotenuse)
这些是三角函数的概念,在Silverlight中的Math类为三角函数、对数函数和其他通用数学函数提供常数和静态方法供我们使用。比如:
Sin 返回指定角度的正弦值。
Asin 返回正弦值为指定数字的角度。
Cos 返回指定角度的余弦值。
Acos 返回余弦值为指定数字的角度。
Tan 返回指定角度的正切值。
Atan 返回正切值为指定数字的角度。
以上是一些概念性的东西,下面就来看一下实际的应用。 下面这个示例主要是使用正弦、余弦函数以及弧度、角度来控制对象进行旋转运动。
DegreeRadianRotation
1.示例包含了一个DegreeRadianRotation对象,DegreeRadianRotation里包含了两个圆,以及各个圆的半径,一个圆使用角度控制半径围绕圆心进行运动,而另外一个则使用的是弧度。
DegreeRadianRotation.xaml 代码。
<UserControl.Resources>
<Storyboard x:Name="MoveTimer" Duration="00:00:00.00"/>
</UserControl.Resources>
<Canvas x:Name="LayoutRoot" Width="800" Height="600">
<Canvas.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF095DCD" Offset="0.009"/>
<GradientStop Color="#FF000000" Offset="1"/>
</LinearGradientBrush>
</Canvas.Background>
<Ellipse Height="200" Width="200" Stroke="#FFFFFFFF" Canvas.Left="130" Canvas.Top="200" x:Name="Circle"/>
<Ellipse Height="200" Width="200" Stroke="#FFFFFFFF" x:Name="Circle2" Canvas.Left="440" Canvas.Top="200"/>
<TextBlock x:Name="MsgDegrees" Text="角? 度è: 0" TextWrapping="Wrap"
Canvas.Top="416" Canvas.Left="171" Foreground="#FFFFFFFF"
Width="118.695" Height="27"/>
<TextBlock x:Name="MsgRadians" Text="弧 度: 0" TextWrapping="Wrap" Foreground="#FFFFFFFF"
Width="118.695" Height="27"
Canvas.Left="486" Canvas.Top="416"/>
<TextBlock Text="使用角度和弧度进行旋转运动." TextWrapping="Wrap" Foreground="#FFFFFFFF"
FontSize="18" FontStyle="Italic" Canvas.Top="10" Canvas.Left="10"/>
</Canvas>
DegreeRadianRotation.xaml.cs代码
public partial class DegreeRadianRotation : Page
{
//用于记录当前运动的角度。
private double SinAngle = 0;
private double SinAngle2 = 0;
//每次的递增量
private double RotateSpeed = 1;
private double RadianSpeed = .01745;
//圆的半径以及圆心位置
private Line SineRadius = new Line();
private Point CircleCenter = new Point();
private Line SineRadius2 = new Line();
private Point Circle2Center = new Point();
public DegreeRadianRotation()
{
InitializeComponent();
//初始化圆半径
SineRadius.StrokeThickness = 2;
SolidColorBrush SineStroke = new SolidColorBrush();
SineStroke.Color = Color.FromArgb(100, 59, 130, 255);
SineRadius.Stroke = SineStroke;
LayoutRoot.Children.Add(SineRadius);
SineRadius2.StrokeThickness = 2;
SolidColorBrush SineStroke2 = new SolidColorBrush();
SineStroke2.Color = Color.FromArgb(255, 255, 0, 0);
SineRadius2.Stroke = SineStroke2;
LayoutRoot.Children.Add(SineRadius2);
//设置半径的起点,位于圆心
CircleCenter.X = (double)Circle.GetValue(Canvas.LeftProperty) + Circle.Width / 2;
CircleCenter.Y = (double)Circle.GetValue(Canvas.TopProperty) + Circle.Height / 2;
SineRadius.X1 = SineRadius.X2 = CircleCenter.X;
SineRadius.Y1 = SineRadius.Y2 = CircleCenter.Y;
Circle2Center.X = (double)Circle2.GetValue(Canvas.LeftProperty) + Circle2.Width / 2;
Circle2Center.Y = (double)Circle2.GetValue(Canvas.TopProperty) + Circle2.Height / 2;
SineRadius2.X1 = SineRadius2.X2 = Circle2Center.X;
SineRadius2.Y1 = SineRadius2.Y2 = Circle2Center.Y;
MoveTimer.Completed += new EventHandler(moveTimer_Completed);
MoveTimer.Begin();
}
private void moveTimer_Completed(object sender, EventArgs e)
{
//分别计算当前角度的两个直角边的长度,这里使用的是最常见的解三角方程的用法 //已知角度和斜边的值,计算三角形的另外两个直角边的大小.
//分别使用了 sinθ=y/r 和 cosθ=x/r公式.
//x、y为直角边,θ=SinAngl、r=Circle.Width / 2
//由此公式便可计算x,y的大小,再和圆心位置进行相加就可以获取到半径r的终点坐标
//由于Math.Sin、Math.Cos的参数需要使用的是以弧度计算的角度,所以要将角度转换为弧度.
if (SinAngle == 360)
{
SineRadius.X2 = CircleCenter.X + Math.Cos(DegreesToRadians(SinAngle)) * Circle.Width / 2;
SineRadius.Y2 = CircleCenter.Y + Math.Sin(DegreesToRadians(SinAngle)) * Circle.Width / 2;
SinAngle = 0;
}
else
{
SineRadius.X2 = CircleCenter.X + Math.Cos(DegreesToRadians(SinAngle)) * Circle.Width / 2;
SineRadius.Y2 = CircleCenter.Y + Math.Sin(DegreesToRadians(SinAngle)) * Circle.Width / 2;
//根据递增角度计算置下一位置的角度
SinAngle += RotateSpeed;
MsgDegrees.Text = "角 度: " + SinAngle;
MoveTimer.Begin();
}
//直接使用弧度进行计算,递增弧度为0.01745,是因为1°≈0.1745弧度 .
SineRadius2.X2 = Circle2Center.X + Math.Cos(SinAngle2) * Circle.Width / 2;
SineRadius2.Y2 = Circle2Center.Y + Math.Sin(SinAngle2) * Circle.Width / 2;
MsgRadians.Text = "弧 度: " + String.Format("{0:0.00}", SinAngle2);
SinAngle2 += RadianSpeed;
}
/// <summary>
/// 根据给定的弧度值转换为角度
/// </summary>
/// <param name="Radians">弧度</param>
/// <returns>结果,转换后的角度</returns>
private double RadiansToDegrees(double Radians)
{
//弧度公式:l=nπDr/180
//n为角度,l为弧度
double Degrees = Radians * 180 / Math.PI;
return Degrees;
}
/// <summary>
/// 根据给定的角度值转换为弧度
/// </summary>
/// <param name="Degrees">度</param>
/// <returns>结果,转换后的弧度</returns>
private double DegreesToRadians(double Degrees)
{
double Radians = Degrees * Math.PI / 180;
return Radians;
}
}
由此整个代码就完成了。
运行效果演示地址:点击查看
总结:在每次动画完成中都会计算r的终点位置,由于当前旋转的角度和r的长度便可以计算出x,y的值,由图中也可以看到
半径 r 的终点位置只需要使用圆心坐标分别加上计算出来的x、y即可。
参考:1.三角函数 2.弧度
【注:本文技术论点源于《Foundation Silverlight 3 Animation》,个人理解可能存在差异,请参考原著】