Silverlight & Blend动画设计系列十二:三角函数(Trigonometry)动画之自由旋转(Free-form rotation)

  说到对象的旋转,或许就会联想到对象角度的概念。对象的旋转实现实际上就是利用对象的角度改变来实现的位置变换,在《Silverlight & Blend动画设计系列二:旋转动画(RotateTransform)》一文中有对对象的不同角度变换的实现介绍,本篇要介绍的自由旋转(Free-form rotation)将借助《Function Silverlight 3 Animation》一书中的示例项目介绍,详细敬请阅读本文。

 

  要实现自由旋转其实非常简单,需要特别注意的有四点,既旋转对象、旋转中心点、旋转角度及旋转焦点。可以简单理解为当点击对象上的某一点可以对对象实现其以某一中心点为准的不等角度旋转。为了方便控制通常会将旋转焦点设计为相对突出的UI呈现,如下图示:

        Silverlight & Blend动画设计系列十二:三角函数(Trigonometry)动画之自由旋转(Free-form rotation)_第1张图片

 

   上图的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然后将其添加到主容器控件中就可以了,如下演示代码:

 

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动画设计系列文章

  《Function Silverlight 3 Animation》----本篇中使用的示例素材选自此书

 

    

你可能感兴趣的:(function,image,null,animation,silverlight,Blend)