原文:一头雾水的"Follow The Pointer"

一头雾水的"Follow The Pointer"
                                                                                                     周银辉

Microsoft Expression Blend中有一个示例程序"Follow The Pointer", 看程序演示会觉得很酷,看代码(点击下载)会觉得一头雾水, 不过现在我便借此介绍一下WPF中的CompositionTarget 以及该示例中设计到了一些物理知识.

一, CompositionTarget
虽然我们拥有Storyboard(故事板)以及Microsoft Expression Blend为WPF动画制作提供强有力的支持,但你会发现这是不够的,也许你希望能通过代码来控制动画中的每一帧,以便显示更加复杂和视觉效果更好的动画, 那么你就得了解CompositionTarget 类.

CompositionTarget 类用于呈现你的应用程序显示表面, 每次绘制时其都会触发其Rendering事件, 其绘制次数取决于你计算机的FPS.
我们可以自定义Rendering事件的处理器来进行一些自定义的绘制或其他工作(注意其会根据计算机的FPS来不停地调用改事件处理器,比如每秒60次,所以不应该在这里进行复杂费时的操作) 比如:

CompositionTarget.Rendering += delegate
{
    this.UpdateColor();
};

这里有一个简单的例子说明CompositionTarget的用法,你可以点击这里下载

二, "Follow The Pointer"中的物理知识
编写视觉效果稍稍好一点的动画时不使用数学或物理知识几乎是不可能的. "Follow The Pointer"示例中用到了力,速度,加速度以及流动摩擦(其变形形式).
动画的简单的流程: 当用户移动鼠标时,程序会计算可移动控件(以下称"小方块",就是跟随鼠标的那个控件)的位置到鼠标位置所形成的向量, 并将该向量作为施加到小方块上的作用力.该作用力会使小方块朝鼠标所在位置移动.假设小方块处于空气(或水等)环境中,小方块的移动会产生流摩擦力,该摩擦力与速度成正比,其会使小方块减速并最终停止下来.
具体如何表现这些物理知识请参考下面的两段代码
这里是原示例代码:

private void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            // Current position of mouse pointer relative to the movable control.
            // The Mouse class is defined in the System.Windows.Input namespace.
            Point mousePos = Mouse.GetPosition(this.MovableControl); 

            TimeSpan currentTime = this.stopwatch.Elapsed;
            double elapsedTime = (currentTime - this.prevTime).TotalSeconds;
            this.prevTime = currentTime;

            // The vector to the mouse pointer represents the force currently acting on the movable control.
            Vector force = new Vector(mousePos.X, mousePos.Y);

            // The smaller the value of damping, the more iterations it takes to approach the mouse pointer, thus allowing velocity to grow larger.
            force = (force * this.SpringSlider.Value - this.velocity * this.DampingSlider.Value) * elapsedTime;

            // The current force causes an acceleration (a change in velocity).
            this.velocity += force;

            // If the eye won't notice any further motion then don't animate on this iteration.
            if (velocity.Length < epsilon)
                return;

            // Distance equals speed times time.
            this.translation.X += this.velocity.X * elapsedTime; 
            this.translation.Y += this.velocity.Y * elapsedTime;
        }

这里是改写与简化后的示例代码:

void CompositionTarget_Rendering(object sender, EventArgs e)
        {

            //上次绘制到此时的时间间隔
            TimeSpan currentTime = this.stopwatch.Elapsed;
            double elapsedTime = (currentTime - this.prevTime).TotalSeconds;           
            this.prevTime = currentTime;

            //鼠标相对于小方块的位置
            Point mouseLoc = Mouse.GetPosition(this.rectangle1);
            //由于改相当位置是相对于小方块左上角的,将其纠正到相当于小方块中心
            mouseLoc.Offset(-this.rectangle1.ActualWidth / 2, -this.rectangle1.ActualHeight / 2);


            //使用鼠标相对于小方块的位置作为外力
            Vector force = new Vector(mouseLoc.X, mouseLoc.Y);

            //流动摩擦力系数假设为该值
            double coefficient = 5;

            //假设小方块质量为1,则加速度为a = force/1;
            //那么在elapsedTime内其速度的变化量为a*elapsedTime
            //由于流动摩擦力与速度成正比,那么流动摩擦力为coefficient * this.velocity
            //所以速度的变化为(force * 200 - coefficient * this.velocity) * elapsedTime
            //这里为了演示中小方块的速度更快一点,我们将外力扩大了200倍
            Vector velocityDelta = (force * 200 - coefficient * this.velocity) * elapsedTime;

            //当前速度
            this.velocity += velocityDelta;

            //小方块的新位置
            this.translation.X += this.velocity.X * elapsedTime;
            this.translation.Y += this.velocity.Y * elapsedTime;
            
        }
       

下载Demo以及源代码

一头雾水的"Follow The Pointer"的更多相关文章

  1. What is the difference between a Clustered and Non Clustered Index?

    A clustered index determines the order in which the rows of a table are stored on disk. If a table h ...

  2. Discovering the Computer Science Behind Postgres Indexes

    This is the last in a series of Postgres posts that Pat Shaughnessy wrote based on his presentation ...

  3. Enhancing the Scalability of Memcached

    原文地址: https://software.intel.com/en-us/articles/enhancing-the-scalability-of-memcached-0 1 Introduct ...

  4. 用arm-linux-gcc v4.3.4交叉编译Qt4.8.3

    1.解压缩 #tar zxvf  qt-everywhere-opensource-src-4.8.3.tar.gz 2. configure #mkdir buildarm-static #cd b ...

  5. Golang源码探索(三) GC的实现原理

    Golang从1.5开始引入了三色GC, 经过多次改进, 当前的1.9版本的GC停顿时间已经可以做到极短. 停顿时间的减少意味着"最大响应时间"的缩短, 这也让go更适合编写网络服 ...

  6. Understanding the Objective-C Runtime

    Wednesday, January 20, 2010 Understanding the Objective-C Runtime The Objective-C Runtime is one of ...

  7. Golang源码探索(三) GC的实现原理(转)

    Golang从1.5开始引入了三色GC, 经过多次改进, 当前的1.9版本的GC停顿时间已经可以做到极短.停顿时间的减少意味着"最大响应时间"的缩短, 这也让go更适合编写网络服务 ...

  8. golang----GC的实现原理

    Golang从1.5开始引入了三色GC, 经过多次改进, 当前的1.9版本的GC停顿时间已经可以做到极短.停顿时间的减少意味着"最大响应时间"的缩短, 这也让go更适合编写网络服务 ...

  9. Python C/C++ 拓展使用接口库(build-in) ctypes 使用手册

    Python C/C++ 拓展使用接口库(build-in) ctypes 使用手册 ctypes 是一个Python 标准库中的一个库.为了实现调用 DLL,或者共享库等C数据类型而设计.它可以把这 ...

随机推荐

  1. Java抽象类和接口的比较

    一个软件设计的好坏,我想很大程度上取决于它的整体架构,而这个整体架构其实就是你对整个宏观商业业务的抽象框架,当代表业务逻辑的高层抽象层结构 合理时,你底层的具体实现需要考虑的就仅仅是一些算法和一些具体 ...

  2. Android Studio:Support Library依赖包的版本号

    当我们用RecyclerView时,如果想用某一个特定的版本,怎样才能知道版本号呢?如果自己的笔记本中用过这个库,那么会保存在本地硬盘中. Android自身依赖包的版本号本地存放路径:  没有用过该 ...

  3. (网页)备注在HTML页面的放置的小技巧(title属性)

    其实很简单,就是title这个属性:(字符多余的剪切,title显示完整的字符) 下面是代码: <ul> <li title="江南style.江南style.江南styl ...

  4. JavaScript大杂烩7 - 理解内置集合

    JavaScript内置了很多对象,简单的类型如String,Number,Boolean (相应的"值类型"拥有相同的方法),复杂一点的如Function,Object,Arra ...

  5. 洗礼灵魂,修炼python(20)--自定义函数(1)—基础概念

    作为开发,那么我们前面学的那些知识其实够了,但是不够精简,也不好维护,比如需要打印斐波那契数列: 而当我们需要再次打印斐波那契数列,又要把这段代码加上,是不是很烦,有没有方法可以解决,当然可以,那就是 ...

  6. C#生成真值表

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  7. Eclipse配置和使用Maven

    一.ecplise配置Maven 1.下载eclipse的Maven插件.(有些eclipse版本中已经集成了此Maven插件,可以不用下载). 需要下载m2eclipse插件. 2.安装m2ecli ...

  8. Hive-1.2.1_04_DML操作

    Hive官方文档:Home-UserDocumentation Hive DML官方文档:LanguageManual DML 参考文章:Hive 用户指南 1. Loading files into ...

  9. MATLAB常微分方程的数值解法

    MATLAB常微分方程的数值解法 作者:凯鲁嘎吉 - 博客园http://www.cnblogs.com/kailugaji/ 一.实验目的 科学技术中常常要求解常微分方程的定解问题,所谓数值解法就是 ...

  10. MySQL5.7.21解压版安装详细教程

    由于本人经常装系统,每次装完系统之后都要重新安装一些软件,安装软件的时候又要上网查找安装的教程,比较麻烦,所以自己整理了MySQL5.7.21解压版的安装方法,以便查看. 1.首先,你要下载MySQL ...