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;
}
}
可旋转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)的更多相关文章
- Silverlight & Blend动画设计系列十:Silverlight中的坐标系统(Coordinate System)与向量(Vector)运动
如果我们习惯于数学坐标系,那么对于Silverlight中的坐标系可能会有些不习惯.因为在Silverlight中的坐标系与Flash中的坐标系一样,一切都的颠倒的.在标准的数学坐标系中,X轴表示水平 ...
- Silverlight & Blend动画设计系列十三:三角函数(Trigonometry)动画之飘落的雪花(Falling Snow)
平时我们所看到的雪花(Falling Snow)飘飘的效果实际上也是一个动画,是由许多的动画对象共同完成的一个界面效果.对于不同大小的雪片可以通过缩放变换(ScaleTransform)功能特性确定, ...
- Silverlight & Blend动画设计系列十一:沿路径动画(Animation Along a Path)
Silverlight 提供一个好的动画基础,但缺少一种方便的方法沿任意几何路径对象进行动画处理.在Windows Presentation Foundation中提供了动画处理类DoubleAnim ...
- Silverlight & Blend动画设计系列七:模糊效果(BlurEffect)与阴影效果(DropShadowEffect)
模糊效果(BlurEffect)与阴影效果(DropShadowEffect)是两个非常实用和常用的两个特效,比如在开发相册中,可以对照片的缩略图添加模糊效果,在放大照片的过程中动态改变照片的大小和模 ...
- Silverlight & Blend动画设计系列九:动画(Animation)与视图状态管理(Visual State Manager)
Silverlight中的动画(Animation)与视图状态管理(Visual State Manager) 结合使用是非常常见的,动画用于管理对象在某段事件段内执行的动画动作,视图状态管理则用于控 ...
- Web 前端开发精华文章推荐(jQuery、HTML5、CSS3)【系列十二】
2012年12月12日,[<Web 前端开发人员和设计师必读文章>系列十二]和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HT ...
- SQL Server 2008空间数据应用系列十二:Bing Maps中呈现GeoRSS订阅的空间数据
原文:SQL Server 2008空间数据应用系列十二:Bing Maps中呈现GeoRSS订阅的空间数据 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Se ...
- Alamofire源码解读系列(十二)之请求(Request)
本篇是Alamofire中的请求抽象层的讲解 前言 在Alamofire中,围绕着Request,设计了很多额外的特性,这也恰恰表明,Request是所有请求的基础部分和发起点.这无疑给我们一个Req ...
- struts2官方 中文教程 系列十二:控制标签
介绍 struts2有一些控制语句的标签,本教程中我们将讨论如何使用 if 和iterator 标签.更多的控制标签可以参见 tags reference. 到此我们新建一个struts2 web 项 ...
随机推荐
- 原创:各种normalize函数实现的性能和精度大比拼
///////////////////////////////////////////////////////////////////////// // // Performance benchmar ...
- 让子类使用父类的Logger
参考博客:https://blog.csdn.net/zx1323/article/details/71262613 1.让子类使用父类的Logger,这是一种语法思路,可以减少代码臃肿. 2.使用的 ...
- docker部署生产环境下的tomcat
1. dockerfile文件 FROM tomcat:7-jre8 WORKDIR /etc COPY ./Shanghai /etc/localtime WORKDIR /usr/share/zo ...
- 爬虫--python3如何安装scrapy?
直接使用pip3 install scrapy会报很多错误,所以试试以下步骤. (1) https://www.lfd.uci.edu/~gohlke/pythonlibs/ 在这个python第三方 ...
- 【BZOJ1296】[SCOI2009]粉刷匠 (DP+背包)
[SCOI2009]粉刷匠 题目描述 \(windy\)有 \(N\) 条木板需要被粉刷. 每条木板被分为 \(M\) 个格子. 每个格子要被刷成红色或蓝色. \(windy\)每次粉刷,只能选择一条 ...
- 斐讯K2P配置文件破解笔记
手上有一个斐讯K2P路由器,刷机前我想把原机带的固件备份出来.搜到恩山A大开启telnet.固件备份的教程,里面提到了配置文件破解的方法,心血来潮试了一下,发现算出的密码不能解密,一直报"b ...
- python简介和环境搭建
简介: python 是一种解释型.面向对象编程语言 由 Guido van Rossum 于1989年底发明, 第一个公开发行版发行于1991年, 最初被设计用于编写自动化脚本(shell) ...
- Bootrap 项目实战(微金所前端首页)第三部分(CSS,js源码)
CSS源码 common.css /** *Created by xxc on 2019/2/26 */ body, html, div, img, a, p, ul, ol, dl, dd, dt, ...
- 【关于selenium自动化中,Webdriver的原理以及工作流程】
原文地址:https://www.cnblogs.com/imyalost/p/7242747.html#4109245 作者:老 张 1.关于Webdriver 设计模式:按照Server-Clie ...
- EOFError: Compressed file ended before the end-of-stream marker was reached
EOFError: Compressed file ended before the end-of-stream marker was reached python在下载时,出现上述错误提示,一般这种 ...