1. 程式人生 > >Silverlight & Blend動畫設計系列十二:三角函數(Trigonometry)動畫之自由旋轉(Free-form rotation)

Silverlight & Blend動畫設計系列十二:三角函數(Trigonometry)動畫之自由旋轉(Free-form rotation)

name angle 最終 clas oot pos ftp 旋轉動畫 one

說到對象的旋轉,或許就會聯想到對象角度的概念。對象的旋轉實現實際上就是利用對象的角度改變來實現的位置變換,在《Silverlight & Blend動畫設計系列二:旋轉動畫(RotateTransform)》一文中有對對象的不同角度變換的實現介紹,本篇要介紹的自由旋轉(Free-form rotation)將借助《Function Silverlight 3 Animation》一書中的示例項目介紹,詳細敬請閱讀本文。

  要實現自由旋轉其實非常簡單,需要特別註意的有四點,既旋轉對象、旋轉中心點、旋轉角度及旋轉焦點。可以簡單理解為當點擊對象上的某一點可以對對象實現其以某一中心點為準的不等角度旋轉。為了方便控制通常會將旋轉焦點設計為相對突出的UI呈現,如下圖示:

        技術分享圖片

  上圖的UI外觀設計為一個獨立的UserControl,對應的xaml定義如下:

技術分享圖片 <UserControl x:Class="ImageRotate.RotateItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="320" Height="240">
<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" Source="" Stretch="Fill"/>
<Ellipse x:Name="Handle" Width="15" Height="15" Fill="#FFEAFF00" Stroke="#FF000000" Canvas.Left="313" Canvas.Top="233"/>
</Canvas>
</UserControl> 技術分享圖片

  分析上面的xaml可以知道,整個界面通過基於坐標的Canvas進行布局,默認設置布局容器的旋轉角度為0度,在Canvas裏面放置了一個圖片作為可旋轉的對象外觀呈現,一個圓形作為旋轉焦點。最終實現旋轉功能的就是鼠標在Ellipse對象上的事件應用,通過事件處理函數來改變整個布局容器的旋轉角度(Angle)。

技術分享圖片 private bool IsMouseCaptured;
private Point MousePosition;
private Point LastPosition;
public Point CanvasCenter;
private double LastAngle;
private double CurrentAngle;
private double AngleDelta;

public RotateItem()
{
InitializeComponent();
//註冊Ellipse對象的鼠標事件
Handle.MouseLeftButtonDown += new MouseButtonEventHandler(Handle_MouseLeftButtonDown);
Handle.MouseLeftButtonUp += new MouseButtonEventHandler(Handle_MouseLeftButtonUp);
Handle.MouseMove += new MouseEventHandler(Handle_MouseMove);
}

private void Handle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement Item = sender as FrameworkElement;
Item.ReleaseMouseCapture();
IsMouseCaptured = false;
Item.Cursor = null;
}

private void Handle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement Item = sender as FrameworkElement;
Item.CaptureMouse();
Item.Cursor = Cursors.Hand;
IsMouseCaptured = true;
LastPosition = e.GetPosition(null);
} 技術分享圖片

  最關鍵的就是MouseMove事件了,在MouseMove事件處理函數中,通過計算鼠標點下時的坐標和當前所在的坐標進行弧度轉化角度的計算,將得到的角度值設置為Canvas的旋轉角度就達到了實現對象的自由旋轉功能。

        技術分享圖片

  以下為弧度轉化為角度的計算公式以及MouseMove事件算法實現:

技術分享圖片 /// <summary>
/// 弧度轉化為角度
/// </summary>
/// <param name="Radians"></param>
/// <returns></returns>
private double RadiansToDegrees(double Radians)
{
return Radians * 180 / Math.PI;
} 技術分享圖片

技術分享圖片 private 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;
}
} 技術分享圖片

技術分享圖片可旋轉UserControl完整代碼

  使用也是非常簡單的,動態創建上面所創建的UserControl然後將其添加到主容器控件中就可以了,如下演示代碼:

技術分享圖片 public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();

var Picture1 = new RotateItem();
Picture1.Image.Source = new BitmapImage(new Uri("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);
}
} 技術分享圖片

        技術分享圖片

Silverlight & Blend動畫設計系列十二:三角函數(Trigonometry)動畫之自由旋轉(Free-form rotation)