前言:

之前为了完成一些任务,因为公司只能限定一些网络访问且不能用存储设备进行拷贝,所以自己在家里写了一个demo就放到csdn的下载区回公司再下下来,令人意外的是这个非常小的demo居然两天里就有几十个下载还得到了几个评论(在我之前从来没有遇到过的)。想了一下干脆分享一下自己的学习心得好了。

接下来让我们初入WPF动画的世界吧

1.任务概述:

使用WPF模拟一个小人走路的动画效果。

之前没有过WPF开发的经验,但是拿到东西后第一反应就是利用多幅图片来反复播放,如果帧率足够的话就能完成这个事情了,所以撇开技术不说,任务实际上是非常简单的,因为我们已经知道要怎么做了,有思路了。

2.本次关键知识的储备

2.1 我们需要知道Image标签,如何绘图,插入图片以及后台线程(其实就是一个控件与三个简单的方法)

2.2 WPF基于帧的动画:CompositionTarget.Rendering += new EventHandler(DoSomething)

基于帧的动画是WPF提供的一套非常低级的方法(不是指功能低级,而是要自己处理比较多的内容),这种方法只需要调用 CompositionTarget.Rendering这个静态时间,它是WPF系统默认提供给我们的事件,触发这个事件会完成一件事情,就是在WPF在组合树呈现之前瞬间渲染要显示的图形或者图像,非常方便。

其实就是程序反复的触发这个事件帮我们刷新图片,MSDN上说是以每秒60帧的速度,而想要有动画效果,让图片以一定的帧率反复刷新多张变动比较小的图片就可以了。

例如我提供的这两张图片(临时手画的)

具体的代码如下:

        //保存需要展示的图片数量ObservableCollection<BitmapImage> bmList;//记录索引,用来重复切换图片int index = 0;public MainWindow(){InitializeComponent();InitList();//调用系统默认的帧进行动画CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);}

绘制图片:(注:GetImagePath是我写好的一个方法,主要作用是用来找图片地址的,稍后的源代码链接里面大家可以自己去下载下来看)

        public void InitList(){bmList = new ObservableCollection<BitmapImage>();//图片是按照1,2,3这样的命名规则,所以循环添加图片for (int i = 1; i < 3; i++){var path = GetImagePath(i);//在UI上绘制图片BitmapImage bmImg = new BitmapImage(new Uri(path));bmList.Add(bmImg);}}

下面是触发的具体方法(插入图片):

void CompositionTarget_Rendering(object sender, EventArgs e){if (index < bmList.Count){this.img1.Source = bmList[index];this.img1.Width = this.img1.Source.Width;this.img1.Height = this.img1.Source.Height;ImgMove();index++;}else{index = 0;}}}

XAML的代码:只有一句话,是一个Image标签控件

<Canvas Grid.Row="0"><Image Height="150" Width="100" x:Name="img1"></Image>
</Canvas>

通过上面的工作,实际上就已经完成了动画的效果了,就是对img1反复的赋值,再反复绘图,这样呈现出来的效果就是一个动画了。

但是现在有一些问题,帧率太快了,刷新的速度大大超过了我图片的数量(帧数是60/s,而我只是做一个demo所以只有两个图片),完全看不见友好的效果(你只能看见狂闪),所以还要稍微控制一下帧速,怎么控制呢?这个方法好像也没有提供属性或者方法调用,只好自己傻瓜一点去写了,在后台开一个线程,sleep等待一下。

之前的代码稍微修改一下

        //保存需要展示的图片数量ObservableCollection<BitmapImage> bmList;//记录索引,用来重复切换图片int index = 0;//是否刷新帧bool isRendering = false;public MainWindow(){InitializeComponent();InitList();//调用系统默认的帧进行动画CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);OpenBackgroundWork();}/// <summary>/// 开启一个后台线程,用来控制帧频率的刷新速度/// </summary>private void OpenBackgroundWork(){BackgroundWorker bw = new BackgroundWorker();bw.DoWork += new DoWorkEventHandler((sender, e) =>{while (true){isRendering = true;System.Threading.Thread.Sleep(100); //停100毫秒}});bw.RunWorkerAsync();}void CompositionTarget_Rendering(object sender, EventArgs e){if (isRendering){if (index < bmList.Count){this.img1.Source = bmList[index];this.img1.Width = this.img1.Source.Width;this.img1.Height = this.img1.Source.Height;ImgMove();index++;}else{index = 0;}isRendering = false;}}

此外,再计算一下Image的移动,每次在canvas画布上走动一小段距离模拟出行走的效果

        //设置画板上图片的初始坐标;Point location = new Point(0, 0);/// <summary>/// 利用坐标算出图片的位置,每次在横轴上增加50px,显示让图片往前走的效果/// </summary>private void ImgMove(){Canvas.SetLeft(img1, location.X);location.X = location.X + 50;//超过边界就回原点if (location.X > this.Width){location.X = 0;}}

做完这些工作之后,再运行程序,效果就比较明显了。

3.小结

总结一下,利用WPF的基于帧动画的方法,我们不需要储备太多知识,只需要明白(1)如何插入与绘制图片,(2)Image标签能够被插入图片再加一个CompositionTarget.Rendering的静态事件就能够解决。

但前面说到了,这是一个低级方法,简单之外,也有它不好的地方,(1)我们要自己绘制大量图片 (2) 手动控制帧速 (3)帧动画事件是一个反复循环触发的事件,它没有非常好的时间线概念,什么时间结束这个动画,是需要自己做额外的处理。而且在意外忘记移除掉这个事件的话,会对整个程序造成不小的性能影响

综上所述,基于帧的动画,需要程序员自己处理大量细节逻辑,并且控制不好的话,效果和性能上都不足,且维护起来较麻烦,接下来,我还会使用其他两种不同的方案完成这个任务并简单介绍一下WPF里绘图与动画的基本要点。

本例的源代码下载:http://download.csdn.net/detail/yujunwu2525/6528261

(下一篇:小人快跑之WPF基础——图形与动画(二))

小人快跑之WPF基础——图形与动画(一)相关推荐

  1. 小人快跑之WPF基础——图形与动画(二)

    前言: 昨天说到了利用基于帧的动画来实现效果,这其实与WPF提供的图形与动画功能没有太大关系,在这里我们还是要关注一下WPF为我们提供的高级方法来解决问题. 本次主题将简述WPF中有关"图形 ...

  2. JavaScript事件——【小案例】小人快跑

    效果图: images: 操作:       按"上" "下" "左" "右" 键控制小人移动方向 步骤:        ...

  3. 小实操(3): 利用键盘事件实现小人快跑

    ** 实例: 利用html表单和js的数学对象及函数做一个有验证码的简单登录表单 实操:利用日期对象和方法以及其他相关知识实现简单的钟表功能 ....... js学习中的小实操(目录) **      ...

  4. js-键盘事件案例-小人快跑

    js-键盘事件案例-小人快跑 案例思路: 利用键盘的keycode判断按了上下左右什么键,然后利用键盘事件onkeydown对小人的定位进行改变即可 css部分: 由于操纵的是小人的位置,所以我们要先 ...

  5. js事件案例——小人快跑JavaScript

    效果 小人快跑 <!DOCTYPE html> <html lang="en"> <head><meta charset="UT ...

  6. Javascript学习笔记(13_2) --js事件案例(小人快跑)

    <!DOCTYPE html> <html><head><meta charset="UTF-8"><title>小人快 ...

  7. babylon.js小人快跑动画效果

    babylon.js小人快跑动画效果 var createScene = function () {// This creates a basic Babylon Scene object (non- ...

  8. C语言/C++基础之火车快跑

    C语言/C++基础之火车快跑 程序之美 前言 主体 运行效果 代码示例 代码分析 结束语 程序之美 前言 火车 作者:[土耳其]贾希特·塔朗吉 译者:余光中 朗读:月汐 去什么地方呢 这么晚了 美丽的 ...

  9. 原创跑酷小游戏《Cube Duck Run》 - - 方块鸭快跑

    自从unity5出来才开始关注unity,业余时间尝试做了个小游戏: <方块鸭快跑> (Cube Duck Run) 像素风,3d视角,色彩明快,有无尽和关卡两种模式. 应用连接: goo ...

最新文章

  1. 关于mysql engine(引擎)的疑问
  2. android ui动画效果怎么做,AndroidUI 布局动画-为列表添加布局动画效果
  3. xcode4自定义文件模板(Creating Custom Xcode 4 File Templates)
  4. Spring Cloud Alibaba:@SentinelResource注解的使用
  5. 中医药可投期刊推荐-24本-2021版
  6. COGS——T 8. 备用交换机
  7. VMware新装CentOS无法连接外网解决方法
  8. CSS从大图中抠取小图完整教程(background-position应用)
  9. springMVC通过spring.xml对属性注入bean值(工厂模式)
  10. 编码器rtsp规则-各厂商
  11. android系统app打开蓝牙+设置可见性
  12. HDU3501——欧拉函数裸题
  13. Atitit.http连接合并组件   ConnReducerV3 新特性
  14. K3CLOUD 常用数据表
  15. vue之解决跨域问题
  16. 无法启动程序因为计算机中丢失msvcr100,win7系统无法启动程序提示计算机中丢失msvcr100.dll的解决方法...
  17. 2017.08.18【NOIP提高组】模拟赛B组 沙耶的玩偶(doll)
  18. 全排列算法(字典序法、SJT Algorithm 、Heap's Algorithm)
  19. 微信小程序-Testerhome
  20. Eagerly caching bean '' to allow for resolving potential circular references

热门文章

  1. cent os 7 与cent os 6区别
  2. 一幅漫画告诉你:NB-IoT背后,还有一个大家都在说的LoRa是什么?
  3. 自媒体应该怎么入门,这几点教会你
  4. 阿里巴巴惠普_阿里巴巴UCAN设计课程学习笔记
  5. 《Unity3D人工智能编程精粹》笔记
  6. 一文讲透支付宝沙箱的基本应用
  7. 请插入多卷集的最后一张磁盘,然后单击”确认“继续
  8. 响应服务器554 5.7.1,554 5.7.1:中继访问被拒绝的centos后缀
  9. 宇信易诚 两季度亏损与高管出走的背后
  10. Java生成Excel表格的代码