Silverlight动画基础六:动画与三角函数-图片旋转
ImageRotate主要讲是使用正弦、余弦函数结合鼠标拖动来完成对象按拖动角度选择。
效果图如下,按黄色的角拖动可以使图片围绕中心旋转。
此代码主要包含了两个对象
1.RotateItem:用于实现和控制对象的旋转。
2.ImageRotate:容器。
首先来看一下RotateItem对象
RotateItem
主要对象,RotateItem对象实现了对自身鼠标旋转的控制,使用鼠标拖动事件结合Math.Atan2函数进行对象的角度。代码如下:
RotateItem.xaml代码
<Canvas x:Name="ItemCanvas" Width="320" Height="240"
Canvas.Left="77" Canvas.Top="57"
Background="#FFFFFFFF" RenderTransformOrigin="0.5,0.5">
<!--用于设置角度-->
<Canvas.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="RotateItemCanvas" Angle="0"/>
</TransformGroup>
</Canvas.RenderTransform>
<Image x:Name="Image" Width="300" Height="220"
Canvas.Left="10" Canvas.Top="10" Stretch="Fill"/>
<!--Thumb-->
<Ellipse x:Name="Handle" Width="15" Height="15"
Canvas.Left="313" Canvas.Top="233"
Fill="#FFEAFF00" Stroke="#FF000000"/>
</Canvas>
RotateItem.xaml.cs代码,主要代码都在这里处理。
public partial class RotateItem : UserControl
{
//是否捕捉焦点
private bool IsMouseCaptured;
//当前拖动的鼠标位置
private Point MousePosition;
//记录鼠标按下的位置
private Point LastPosition;
//中心点
public Point CanvasCenter;
//鼠标按下时的角度
private double LastAngle;
//拖拽后产生的角度
private double CurrentAngle;
private double AngleDelta;
public RotateItem()
{
InitializeComponent();
Handle.MouseLeftButtonDown += new MouseButtonEventHandler(Handle_MouseLeftButtonDown);
Handle.MouseLeftButtonUp += new MouseButtonEventHandler(Handle_MouseLeftButtonUp);
Handle.MouseMove += new MouseEventHandler(Handle_MouseMove);
}
void Handle_MouseMove(object sender, MouseEventArgs e)
{
//获取当前鼠标位置
MousePosition = e.GetPosition(null);
if (IsMouseCaptured)
{
//计算鼠标按下的初始角度
LastAngle = Math.Atan2(LastPosition.Y - CanvasCenter.Y,
LastPosition.X - CanvasCenter.X);
//计算鼠标拖动后的角度
CurrentAngle = Math.Atan2(MousePosition.Y - CanvasCenter.Y,
MousePosition.X - CanvasCenter.X);
//获取拖动的角度,并将值赋给对象,设置其位置
AngleDelta = CurrentAngle - LastAngle;
RotateItemCanvas.Angle += RadiansToDegrees(AngleDelta);
LastPosition = MousePosition;
}
}
void Handle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//释放鼠标捕捉
FrameworkElement Item = sender as FrameworkElement;
Item.ReleaseMouseCapture();
IsMouseCaptured = false;
Item.Cursor = null;
}
void Handle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//捕捉鼠标,记录鼠标位置
FrameworkElement Item = sender as FrameworkElement;
Item.CaptureMouse();
Item.Cursor = Cursors.Hand;
IsMouseCaptured = true;
LastPosition = e.GetPosition(null);
}
private double RadiansToDegrees(double Radians)
{
return Radians * 180 / Math.PI;
}
}
关键代码中的注释已经说明了它的基本用法。
ImageRotate
ImageRotate对象为容器,用于承载RotateItem,提供了对RotateItem的初始化、加载等功能。
ImageRotate.xaml代码:
<Canvas x:Name="LayoutRoot" Width="800" Height="600">
<Canvas.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF3F45AC"/>
<GradientStop Color="#FF05083A" Offset="1"/>
</LinearGradientBrush>
</Canvas.Background>
</Canvas>
ImageRotate.xaml.cs代码:
public partial class ImageRotate : Page
{
private RotateItem Picture1;
private RotateItem Picture2;
public ImageRotate()
{
InitializeComponent();
//初始化两个RotateItem对象,RotateItem根据各自的位置来设置其中心点
Picture1 = new RotateItem();
Picture1.Image.Source = new BitmapImage
(new Uri("/AnimationSample;component/images/Marigold.jpg", UriKind.Relative));
Picture1.SetValue(Canvas.LeftProperty, 100.00);
Picture1.SetValue(Canvas.TopProperty, 100.00);
//设置中心点
Picture1.CanvasCenter.X = (double)Picture1.GetValue(Canvas.LeftProperty) + Picture1.Width / 2;
Picture1.CanvasCenter.Y = (double)Picture1.GetValue(Canvas.TopProperty) + Picture1.Height / 2;
Picture1.RotateItemCanvas.Angle = -15;
LayoutRoot.Children.Add(Picture1);
Picture2 = new RotateItem();
Picture2.Image.Source = new BitmapImage
(new Uri("/AnimationSample;component/images/PurpleFlower.jpg", UriKind.Relative));
Picture2.SetValue(Canvas.LeftProperty, 400.00);
Picture2.SetValue(Canvas.TopProperty, 300.00);
//设置中心点
Picture2.CanvasCenter.X = (double)Picture2.GetValue(Canvas.LeftProperty) + Picture2.Width / 2;
Picture2.CanvasCenter.Y = (double)Picture2.GetValue(Canvas.TopProperty) + Picture2.Height / 2;
Picture2.RotateItemCanvas.Angle = -15;
LayoutRoot.Children.Add(Picture2);
}
}
所有代码已经完成了
运行效果演示地址:点击查看
总结:从代码中可以发现,主要使用了Math.Atan2函数,根据鼠标前后位置的变化值,
计算出围绕RotateItem中心点的旋转角度。
【注:本文技术论点源于《Foundation Silverlight 3 Animation》,个人理解可能存在差异,请参考原著】