博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Silverlight & Blend动画设计系列十二:三角函数(Trigonometry)动画之自由旋转(Free-form rotation)...
阅读量:5222 次
发布时间:2019-06-14

本文共 5512 字,大约阅读时间需要 18 分钟。

原文:

  说到对象的旋转,或许就会联想到对象角度的概念。对象的旋转实现实际上就是利用对象的角度改变来实现的位置变换,在《》一文中有对对象的不同角度变换的实现介绍,本篇要介绍的自由旋转(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);
    }
}

 

         

 

  推荐资源:

  

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

 

    

版权说明

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

  作      者:Beniao

 文章出处:  或 

 

posted on
2018-10-21 13:37 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/lonelyxmas/p/9824767.html

你可能感兴趣的文章
将Cent0S 7的网卡名称eno33改为eth0
查看>>
透明度Opacity多浏览器兼容处理
查看>>
oracle 常用简单命令语句
查看>>
【机器学习_3】常见术语区别
查看>>
Oracle基础 数据库备份和恢复
查看>>
C#编程时应注意的性能处理
查看>>
Java集合--概述
查看>>
1-TwoSum(简单)
查看>>
css box模型content-box 和border-box
查看>>
Fragment
查看>>
比较安全的获取站点更目录
查看>>
读书笔记——乔布斯,做最好的自己,共创式教练
查看>>
ubuontu16.04安装Opencv库引发的find_package()错误信息处理及其简单使用
查看>>
用Linux远程挂载Windows上的共享文件夹.md
查看>>
洛谷 P4317 花神的数论题(组合数)
查看>>
【Python】学习笔记5-利用flask来mock接口
查看>>
vue
查看>>
MySQL存储过程和存储函数
查看>>
【bzoj 2208】[Jsoi2010]连通数(dfs||Tarjan算法+拓扑序+dp)
查看>>
iis 隐藏 banner
查看>>