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

 

ExpandedBlockStart.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/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值