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

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/

转载于:https://www.cnblogs.com/beniao/archive/2010/06/20/1735898.html

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

  1. css 入场动画_React系列十四 React过渡动画

    在开发中,我们想要给一个组件的显示和消失添加某种过渡动画,可以很好的增加用户体验. 当然,我们可以通过原生的CSS来实现这些过渡动画,但是React社区为我们提供了react-transition-g ...

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

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

  3. Silverlight Blend动画设计系列二:旋转动画(RotateTransform)

    原文:Silverlight & Blend动画设计系列二:旋转动画(RotateTransform) Silverlight的基础动画包括偏移.旋转.缩放.倾斜和翻转动画,这些基础动画毫无疑 ...

  4. Silverlight Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效...

    原文:Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化.波感特效 当我们在进行Silverlight & Bl ...

  5. Silverlight Blend动画设计系列四:倾斜动画(SkewTransform)

    Silverlight中的倾斜变化动画(SkewTransform)能够实现对象元素的水平.垂直方向的倾斜变化动画效果.我们现实生活中的倾斜变化效果是非常常见的,比如翻书的纸张效果,关门开门的时候门缝 ...

  6. Silverlight Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)

    原文:Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations) 正如你所看到的,Blend是一个非常强大的节约时间的设计工具,在Bl ...

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

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

  8. Silverlight Blend动画设计系列三:缩放动画(ScaleTransform)

    原文:Silverlight & Blend动画设计系列三:缩放动画(ScaleTransform) 在Silverlight的动画框架中,ScaleTransform类提供了在二维空间中的坐 ...

  9. Silverlight Blend动画设计系列八:拖放(Drag-Drop)操作与拖放行为(DragBehavior)

    Silverlight & Blend动画设计系列八:拖放(Drag-Drop)操作与拖放行为(DragBehavior) 原文:Silverlight & Blend动画设计系列八: ...

最新文章

  1. [umeditor] 多图片一次上传功能
  2. Makefile写法入门心得
  3. 比特币现金网络遭攻击?BCH粉丝:放马过来吧!
  4. AWS — AWS 上的 5G 网络及 MEC 边缘计算商业案例
  5. docker部署Javaweb环境数据库连接问题
  6. ubuntu14.6 密码重置_已迁移
  7. MySQL - mysqldump多种方式实现数据迁移
  8. Maven仓库搭建(一):一台HTTP服务器即可(Tomcat、Apache或Nginx)
  9. 领导者的资质——学习笔记(1)
  10. 32岁妈妈适合转行做软件测试吗,32+大龄妈妈,AMH偏低,可丽蓝助力好孕一次就中...
  11. 测试beta测试_重新想象不断变化的自动化世界中的Beta测试
  12. 一些自己常用的linux命令笔记
  13. eclipse远程连接hadoop_Hadoop群启集群
  14. java 钩子 64位 操作系统_Java与系统钩子
  15. 2022年中国研究生数学建模竞赛E题-草原放牧策略研究
  16. 手机浏览器服务器修复,手机IE浏览器怎么修复
  17. 从USB获得高效的双轨电源
  18. 遇见未知的自己 - 张德芬
  19. json.loads()的字符串中为单引号引发的错误
  20. 去水印软件哪个好_去水印工具

热门文章

  1. LeetCode 688. “马”在棋盘上的概率(DP)
  2. LeetCode 1088. 易混淆数 II(回溯/BFS)
  3. LeetCode 1054. 距离相等的条形码(优先队列)
  4. LeetCode 752. 打开转盘锁(图的BFS最短路径)
  5. LeetCode 547. 朋友圈(图的遍历BFS DFS)
  6. python冒泡算法_python_冒泡算法
  7. python中的多线程-threading
  8. extjs2.0 ie8 下拉树_ExtJs下拉树的实现
  9. python混沌时间序列分析_用Python进行时间序列分析
  10. 自训练:超越预训练,展现强大互补特性的上分新范式!