原文:WPF Path实现虚线流动效果

最近闲来无事,每天上上网,看看博客生活也过得惬意,这下老总看不过去了,给我一个任务,叫我用WPF实现虚线流动效果,我想想,不就是虚线流动嘛,这简单于是就答应下来了,谁也没想到这简单的东西搞了3天没搞定,最后搞定了居然是那么的简单,自己是想得太复杂了,哎,脑子生锈了,废话不多说,进入这3天的无脑思考中。

  思路1:

  根据老总的说法,他只要我实现效果就行了,那好,我就偷一下懒,用Line实现,用一个Line数组,装入一定量的Line对象,使他们间隔相同的距离,开启多线程,使得每一个Line对象每秒向前移动 1/3,但是最后一个Line向前移动的时候,需要每次减掉 1/3的长度,直到长度为0,这样才让人有一种视觉错觉虚线在向某个方向流动,当最后一个Line长度为0的时候,把最后一个对象移动到数组的第一位,其他对象依次想后移,下面是代码:

  1 Line[] line = new Line[11];
2 double width;
3 double height;
4 int i = 0;
5 public MainWindow()
6 {
7 InitializeComponent();
8 }
9 /// <summary>
10 /// 线段向某方向移动
11 /// </summary>
12 private void LineMove()
13 {
14 double x1 = width / 20;
15 double x2 = x1 / 3;
16 for (int i = 10; i >=0; i--)
17 {
18 if (i == 10)
19 {
20 if (line[i].X1 >= line[i].X2)//如果最后一条长度为0的时候,就移动到第一位
21 {
22 LineArryMove();
23 }
24 line[i].X1 += x2;
25 }
26 else
27 {
28 line[i].X1 += x2;
29 line[i].X2 += x2;
30 }
31
32 }
33 }
34 /// <summary>
35 /// 最后一个对象移到第一位
36 /// </summary>
37 private void LineArryMove()
38 {
39 double x1 = width / 20;
40 double x2 = x1 / 3;
41 Line temp = line[0];
42 line[0] = line[10];
43 for (int i = 0; i < 10; i++)
44 {
45 Line temp1 = line[i + 1];
46 line[i + 1] = temp;
47 temp = temp1;
48 }
49 for (int i = 1; i<11; i++)
50 {
51 line[i].X1 += x2;
52 line[i].X2 += x2;
53 }
54 line[0].X1 = x2;
55 line[0].X2 = x2 + x1;
56 }
57 /// <summary>
58 /// 画出一条虚线
59 /// </summary>
60 private void LineDraw()
61 {
62 height=this.canvas.ActualHeight;
63 width = this.canvas.ActualWidth;
64 double x1 = width / 20;
65 double x2 = x1 / 3;
66 for (int i = 0; i < 11; i++)
67 {
68 line[i] = new Line();
69 line[i].Stroke = Brushes.Red;
70 line[i].StrokeThickness = 3;
71 line[i].X1 = (i + 1) * x2 + i * x1;
72 line[i].X2 = (i + 1) * x2 + (i+1)* x1;
73 line[i].Y1 = height / 2;
74 line[i].Y2 = height / 2;
75 this.canvas.Children.Add(line[i]);
76 }
77 }
78 /// <summary>
79 /// 开启多线程
80 /// </summary>
81 private void ThreadStart()
82 {
83 Thread P_th = new Thread(//建立线程
84
85 () =>//使用lambda表达式
86 {
87
88 while (true)//开始无限循环
89 {
90
91 this.Dispatcher.BeginInvoke(//在窗体线程中执行相关代码
92
93 System.Windows.Threading.DispatcherPriority.Normal,//设置线程优先级
94
95 (ThreadStart)(() =>//使用lambda表达式
96 {
97
98 LineMove();
99
100 }));
101
102 Thread.Sleep(1000);//线程挂起1秒钟
103 i++;
104
105 }
106
107 });
108
109 P_th.IsBackground = true;//设置线程为后台线程
110
111 P_th.Start();//线程开始
112 }
113 private void button1_Click(object sender, RoutedEventArgs e)
114 {
115 LineDraw();
116 }
117
118 private void button2_Click(object sender, RoutedEventArgs e)
119 {
120 ThreadStart();
121 }

  好吧,这样效果是实现了,但也仅仅是测试一下效果,要是曲线,或者一些不规则的线段的话,肯定不能这样实现,又想了一下,WPF可以实现动画效果,那我们试试用动画实现看看,这就涉及到了路径动画的实现,路径动画,也就是某个对象沿着一条路径运动,这就有了下一个思路。

  思路2:

  还是用Line作为填充对象,每一个对象的的运动周期是一样的,但是动画开始的时间不一样,设置间隔递增的开始时间,这样开始动画的时候,每个Line都会依次出现,这样就就有了流动的效果,但是还有一个问题,就是它有一个填充时间,当第一个对象的一个周期后,这条虚线才被填充完毕,- -这和老总说的有出入,也不知道能不能通过,下面是主要代码:

 1    /// <summary>
2 ///
3 /// </summary>
4 /// <param name="btnPath"></param>
5 /// <param name="xNum">第N个对象</param>
6 /// <param name="sleepTime">间隔时间</param>
7 /// <param name="pathLine">Path对象</param>
8 /// <param name="DuTime">动画时间</param>
9 private void AnimationStart(Line btnPath, int xNum, int sleepTime,Path pathLine,int DuTime)
10 {
11
12 double realTime = ((double)sleepTime) / ((double)1000);
13 string strTranslate = "translate"+xNum;
14 string strRote = "rotate"+xNum;
15
16 //btnPath.Width = 20;
17 //btnPath.Height = 5;
18 btnPath.Stroke = Brushes.Red;
19 btnPath.X1 = 0;
20 btnPath.X2 = 20;
21 btnPath.StrokeThickness = 5;
22
23 Canvas.SetTop(btnPath, -2.5);
24 Canvas.SetLeft(btnPath, -10);//为了使对象与路径更加重合,可自己调节初始坐标
25
26 btnPath.RenderTransformOrigin = new Point(0.5, 0.5);
27
28 TranslateTransform translate = new TranslateTransform();
29 RotateTransform rotate = new RotateTransform();
30 TransformGroup group = new TransformGroup();
31
32 group.Children.Add(rotate);//先旋转
33 group.Children.Add(translate);//再平移
34
35 NameScope.SetNameScope(this, new NameScope());
36
37 this.RegisterName(strTranslate, translate);
38 this.RegisterName(strRote, rotate);
39
40 btnPath.RenderTransformOrigin = new Point(0.5, 0.5);
41 this.canvas.Children.Add(btnPath);
42
43 btnPath.RenderTransform = group;
44 //设置物体X轴的目标
45 DoubleAnimationUsingPath animationX = new DoubleAnimationUsingPath();
46 animationX.PathGeometry = pathLine.Data.GetFlattenedPathGeometry();
47 animationX.Source = PathAnimationSource.X;
48 animationX.Duration = new Duration(TimeSpan.FromSeconds(DuTime));
49 animationX.BeginTime = TimeSpan.FromSeconds(xNum * realTime);
50 animationX.RepeatBehavior = RepeatBehavior.Forever;
51 //设置物体Y轴的目标
52 DoubleAnimationUsingPath animationY = new DoubleAnimationUsingPath();
53 animationY.PathGeometry = pathLine.Data.GetFlattenedPathGeometry();
54 animationY.Source = PathAnimationSource.Y;
55 animationY.Duration = animationX.Duration;
56 animationY.BeginTime = TimeSpan.FromSeconds(xNum * realTime);
57 animationY.RepeatBehavior = RepeatBehavior.Forever;
58
59 //设置物体的旋转角度
60 DoubleAnimationUsingPath animationAngle = new DoubleAnimationUsingPath();
61 animationAngle.PathGeometry = pathLine.Data.GetFlattenedPathGeometry();
62 animationAngle.Source = PathAnimationSource.Angle;
63 animationAngle.Duration = animationX.Duration;
64 animationAngle.BeginTime = TimeSpan.FromSeconds(xNum * realTime);
65 animationAngle.RepeatBehavior = RepeatBehavior.Forever;
66
67 translate.BeginAnimation(TranslateTransform.XProperty, animationX);
68 translate.BeginAnimation(TranslateTransform.YProperty, animationY);
69 rotate.BeginAnimation(RotateTransform.AngleProperty, animationAngle);
70
71 }

  现在最大的一个问题来了,都传说WPF的动画很耗资源,一看CPU,哇,I5的处理器都达到百分之15,这不是坑爹么,这怎么拿出去见人啊,又到了思考的时候,CPU该怎么降下来,试了很多种方法,都是差不多,动画对象一多,CPU就高,当思路进入死胡同的时候,想出来就不那么容易了 - -,就这样耗费了两天时间,突然灵机一闪,我去MSDN一个个的查看Path的方法和属性,这一看,好吧,我承认自己脑残了。。。。

  Path主要属性:

  StrokeThickness 线段的粗细

  Data 路径数据  如:Data=“Data="M25,522 C25,522 6.5,322.5 102.5,319.5 198.5,316.5 245.49957,361.5 369.4992,207.5 493.49883,53.5 468.49891,29.5 559.49864,59.5 650.49837,89.5 692.49827,292.49995 698.49825,304.49996 704.49823,316.49996 698.49823,484.49999 615.49848,501.5
532.49872,518.5 317.4995,543.5 251.49967,516.5 185.49983,489.49999 789.49832,175.49996 502.49904,127.49994"”;

  StrokeDashArray 虚线的设置 如:StrokeDashArray=“10,5”;意思就是把Path分成若干线段,每一段是10,间隔为5,。

  StrokeDashOffset 线段的偏移量!好吧,这就是我们所需要的最重要属性。减去或加上一个数,线段就会向某个方向移动一段距离,要想做成移动的虚线,只要循环设置StrokeDashOffset的值就可以了,代码:

 1         private void ThreadStart()
2 {
3 Thread P_th = new Thread(//建立线程
4
5 () =>//使用lambda表达式
6 {
7
8 while (flag)//开始无限循环
9 {
10
11 this.Dispatcher.BeginInvoke(//在窗体线程中执行相关代码
12
13 System.Windows.Threading.DispatcherPriority.Normal,//设置线程优先级
14
15 (ThreadStart)(() =>//使用lambda表达式
16 {
17 this.path1.StrokeDashOffset -=10;
18
19 }));
20
21 Thread.Sleep(500);//线程挂起
22 }
23
24 });
25
26 P_th.IsBackground = true;//设置线程为后台线程
27
28 P_th.Start();//线程开始
29 }

  本文来自01_code的博客,原文地址:http://www.cnblogs.com/01codeworld/archive/2012/02/17/loce.html

WPF Path实现虚线流动效果的更多相关文章

  1. WPF 图片浏览 伪3D效果

    原文:WPF 图片浏览 伪3D效果 首先上效果图: 因项目要求,需要把图片以"好看"."炫"的效果展示出来,特地研究了一下WPF关于3D方面的制作,奈何最终成果 ...

  2. Shape流动效果

    <Window x:Class="MvvmLight1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/ ...

  3. WPF中画虚线

    原文:WPF中画虚线 在WPF中,画线的方法十分简单,只要声明一个Line然后添加到指定的位置就可以了,但Line并不仅仅只能画一条直线,还可以对直线进行修饰. 1.Line.StrokeDashAr ...

  4. 基于HTML5实现3D监控应用流动效果

    http://www.hightopo.com/guide/guide/core/lighting/examples/example_flowing.html 流动效果在3D领域有着广泛的应用场景,如 ...

  5. HT for Web中3D流动效果的实现与应用

    流动效果在3D领域有着广泛的应用场景,如上图中医学领域可通过3D的流动直观的观察人体血液的流动,燃气领域可用于监控管道内流动的液体或气体的流向.流速和温度等指标. 如今企业数据中心机房普遍面临着设备散 ...

  6. WPF Multi-Touch 开发:惯性效果(Inertia)

    原文 WPF Multi-Touch 开发:惯性效果(Inertia) 从上一篇实例可以发现在图片移动过程中如果将手指移开屏幕则图片会立刻停止,根据这种情况WPF 提供另外一种惯性效果(Inertia ...

  7. 【WPF】两则动画效果

    原文:[WPF]两则动画效果 引言 利用WPF的动画可以轻而易举的实现各种各样的特效,如擦除,滑动进入等,先看两个效果图 第一个效果 这个动画其实利用了OpacityMask和LinearGradie ...

  8. 用WPF轻松打造iTunes CoverFlow效果

    原文:用WPF轻松打造iTunes CoverFlow效果 用WPF轻松打造iTunes CoverFlow效果                                             ...

  9. WPF特效-实现3D足球效果

    原文:WPF特效-实现3D足球效果 WPF 实现 3D足球效果,效果图如下:  每个面加载不同贴图. <UserControl x:Class="MediaBalll.Model3Ds ...

随机推荐

  1. mysql 查询重复 去除重复等等

    查找所有重复标题的记录: SELECT * FROM t_info a WHERE ((SELECT COUNT(*) FROM t_info WHERE Title = a.Title) >  ...

  2. .NET Framework基础知识(四)(转载)

    .反射:是编程的读取与类型相关联的元数据的行为.通过读取元数据,可以了解它是什么类型以及类型的成员. 比如类中的属性,方法,事件等.所属命名空间System.Reflection. 例:using S ...

  3. docker nginx实现一个主机部署多个站点

    原文:docker nginx实现一个主机部署多个站点 在某站租赁的虚拟机快到期了,续费得花200多,想到在阿里云新买的服务器,不如把这个也转移过去.域名我就用真实的吧,大家别黑我网站就好了,谢谢各位 ...

  4. [Node.js] Test Node RESTful API with Mocha and Chai

    In this lesson, we will use Chai's request method to test our Node application's API responses.By th ...

  5. [Vue] Import component into page

    Components are one of the most powerful features of Vue. Let's take a look at how to write our first ...

  6. Android的NDK开发(1)————Android JNI简介与调用流程

    1.JNI简介 JNI全称为Java Native Interface(Java本地调用).从Java1.1开始,JNI成为java平台的一部分,它允许Java代码和其他语言写的代码(如C&C ...

  7. [NPM] Use package.json variables in npm scripts

    In this lesson we will show that you can leverage values that you already have provided in your pack ...

  8. MySQL中关于OR条件的优化

    转载 MySQL在 5.0版本中引入新特性:索引合并优化(Index merge optimization),当查询中单张表可以使用多个索引时,同时扫描多个索引并将扫描结果进行合并. 该特新主要应用于 ...

  9. web开发-MVC IoC 框架(转)

    随着Web应用的商业逻辑包含逐渐复杂的公式分析计算.决策支持等,使客户机越 来越不堪重负,因此将系统的商业分离出来.单独形成一部分,这样三层结构产生了. 其中‘层’是逻辑上的划分. 三层体系结构是将整 ...

  10. leveldb学习:skiplist

    leveldb中的memtable仅仅是一个封装类,它的底层实现是一个跳表. 跳表是一种基于随机数的平衡数据结构.其它的平衡数据结构还有红黑树.AVL树.但跳表的原理比它们简单非常多.跳表有点像链表, ...