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

简介: 原文:Silverlight & Blend动画设计系列十二:三角函数(Trigonometry)动画之自由旋转(Free-form rotation)  说到对象的旋转,或许就会联想到对象角度的概念。
原文: Silverlight & Blend动画设计系列十二:三角函数(Trigonometry)动画之自由旋转(Free-form rotation)

  说到对象的旋转,或许就会联想到对象角度的概念。对象的旋转实现实际上就是利用对象的角度改变来实现的位置变换,在《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;
    }
}

 

img_405b18b4b6584ae338e0f6ecaf736533.gif 可旋转UserControl完整代码
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);
    }

    
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 );
    }

    
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;
        }
    }

        
    
///   <summary>
    
///  弧度转化为角度
    
///   </summary>
    
///   <param name="Radians"></param>
    
///   <returns></returns>
     private   double  RadiansToDegrees( double  Radians)
    {
        
return  Radians  *   180   /  Math.PI;
    }
}

 

  使用也是非常简单的,动态创建上面所创建的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》----本篇中使用的示例素材选自此书

 

    

版权说明

  本文属原创文章,欢迎转载且注明文章出处,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

 

目录
相关文章
|
容器
Silverlight & Blend动画设计系列二:旋转动画(RotateTransform)
原文:Silverlight & Blend动画设计系列二:旋转动画(RotateTransform)   Silverlight的基础动画包括偏移、旋转、缩放、倾斜和翻转动画,这些基础动画毫无疑问是在Silverlight中使用得最多的动画效果,其使用也是非常简单的。
1020 0
|
容器 数据可视化 内存技术
Silverlight & Blend动画设计系列一:偏移动画(TranslateTransform)
原文:Silverlight & Blend动画设计系列一:偏移动画(TranslateTransform)   用户界面组件、图像元素和多媒体功能可以让我们的界面生动活泼,除此之外,Silverlight还具备动画功能,它可以让应用程序“动起来”。
824 0
Silverlight & Blend动画设计系列三:缩放动画(ScaleTransform)
原文:Silverlight & Blend动画设计系列三:缩放动画(ScaleTransform)   在Silverlight的动画框架中,ScaleTransform类提供了在二维空间中的坐标内进行缩放操作,通过ScaleTransform可以在水平或垂直方向的缩放和拉伸对象,以实现一个简单的缩放动画效果,故此我将其称为缩放动画(ScaleTransform)。
942 0
Silverlight & Blend动画设计系列四:倾斜动画(SkewTransform)
原文:Silverlight & Blend动画设计系列四:倾斜动画(SkewTransform)   Silverlight中的倾斜变化动画(SkewTransform)能够实现对象元素的水平、垂直方向的倾斜变化动画效果。
848 0
|
容器
Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)
原文:Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)   正如你所看到的,Blend是一个非常强大的节约时间的设计工具,在Blend下能够设计出很多满意的动画作品,或许他具体是怎么实现的,通过什么方式实现的我们还是一无所知。
950 0