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

  1. Silverlight & Blend动画设计系列十:Silverlight中的坐标系统(Coordinate System)与向量(Vector)运动

    如果我们习惯于数学坐标系,那么对于Silverlight中的坐标系可能会有些不习惯.因为在Silverlight中的坐标系与Flash中的坐标系一样,一切都的颠倒的.在标准的数学坐标系中,X轴表示水平 ...

  2. Silverlight & Blend动画设计系列十三:三角函数(Trigonometry)动画之飘落的雪花(Falling Snow)

    平时我们所看到的雪花(Falling Snow)飘飘的效果实际上也是一个动画,是由许多的动画对象共同完成的一个界面效果.对于不同大小的雪片可以通过缩放变换(ScaleTransform)功能特性确定, ...

  3. Silverlight & Blend动画设计系列十一:沿路径动画(Animation Along a Path)

    Silverlight 提供一个好的动画基础,但缺少一种方便的方法沿任意几何路径对象进行动画处理.在Windows Presentation Foundation中提供了动画处理类DoubleAnim ...

  4. Silverlight & Blend动画设计系列七:模糊效果(BlurEffect)与阴影效果(DropShadowEffect)

    模糊效果(BlurEffect)与阴影效果(DropShadowEffect)是两个非常实用和常用的两个特效,比如在开发相册中,可以对照片的缩略图添加模糊效果,在放大照片的过程中动态改变照片的大小和模 ...

  5. Silverlight & Blend动画设计系列九:动画(Animation)与视图状态管理(Visual State Manager)

    Silverlight中的动画(Animation)与视图状态管理(Visual State Manager) 结合使用是非常常见的,动画用于管理对象在某段事件段内执行的动画动作,视图状态管理则用于控 ...

  6. Web 前端开发精华文章推荐(jQuery、HTML5、CSS3)【系列十二】

    2012年12月12日,[<Web 前端开发人员和设计师必读文章>系列十二]和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HT ...

  7. SQL Server 2008空间数据应用系列十二:Bing Maps中呈现GeoRSS订阅的空间数据

    原文:SQL Server 2008空间数据应用系列十二:Bing Maps中呈现GeoRSS订阅的空间数据 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Se ...

  8. Alamofire源码解读系列(十二)之请求(Request)

    本篇是Alamofire中的请求抽象层的讲解 前言 在Alamofire中,围绕着Request,设计了很多额外的特性,这也恰恰表明,Request是所有请求的基础部分和发起点.这无疑给我们一个Req ...

  9. struts2官方 中文教程 系列十二:控制标签

    介绍 struts2有一些控制语句的标签,本教程中我们将讨论如何使用 if 和iterator 标签.更多的控制标签可以参见 tags reference. 到此我们新建一个struts2 web 项 ...

随机推荐

  1. nowcoder(牛客网)普及组模拟赛第一场 解题报告

    蒟蒻我可能考了一场假试 T1 绩点 这题没什么好说的,应该是只要会语言的就会做. T2 巨大的棋盘 一个模拟题吧qwq,但是要注意取模的时候先加上n或者m再取模,要不然会错的. #include< ...

  2. [转]解读Unity中的CG编写Shader系列5——理论知识

    经过前面的系列文章中的三个例子,尽管代码简单,但是我想应该还有些地方没有100%弄明白,我们现在得回过头来补充一些必备的数学.图形学知识 1.图形管道第一个例子中我有提到顶点着色和片段着色在整个图形绘 ...

  3. 爬虫开发6.selenuim和phantonJs处理网页动态加载数据的爬取

    selenuim和phantonJs处理网页动态加载数据的爬取阅读量: 1203 动态数据加载处理 一.图片懒加载 什么是图片懒加载? 案例分析:抓取站长素材http://sc.chinaz.com/ ...

  4. 2个list取差集

    list操作 element in a list but not in other list,元素在一个list,不在另一个list 在数据量大的时候使用numpy的setdiff1d方法的性能非常好 ...

  5. kvm虚拟化之kvm虚拟机克隆

    kvm虚拟机的克隆分为两种情况,本文也就通过以下两种情况进行克隆,克隆虚拟机为OEL5.8X64. (1) KVM主机本机虚拟机直接克隆. (2) 通过复制配置文件与磁盘文件的虚拟机复制克隆(适用于异 ...

  6. 20 行代码极速为 App 加上聊天功能

    现在很多 App 都需要集成 IM 功能,今天就为大家分享一下集成 IM 基本功能的步骤.本文内容以 JMessage 为例.极光 IM ( JMessage ) = 极光推送 ( JPush ) + ...

  7. request.getSession()、reqeust.getSession(false)和request.getSession(true)

    getSession()/getSession(true):当session存在时返回该session,否则新建一个session并返回该对象 getSession(false):当session存在 ...

  8. leetcode-824-Goat Latin(字符串的处理)

    题目描述: A sentence S is given, composed of words separated by spaces. Each word consists of lowercase ...

  9. vue-cli起的webpack项目 用localhost可以访问,但是切换到ip就不可以访问

    我用的是vux起的一个项目(移动端,基于vue的),因为是移动端的,需要在手机上测试,发现用http://localhost:8081/访问的挺好的,但是换到ip就访问不了,期初我以为是代理的原因,将 ...

  10. Angular material mat-icon 资源参考_Connection

    ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...