像画笔一样慢慢画出Path的三种方法(补充第四种)
今天大家在群里大家非常热闹的讨论像画笔一样慢慢画出Path的这种效果该如何实现.
北京-LGL 博客号@ligl007发起了这个话题.然后各路高手踊跃发表意见.最后雷叔 上海-雷蒙 博客号@雷蒙之星 以一种巧妙的思路实现了这个效果 使大家受益匪浅
本来这篇博客应该由雷叔来写的,奈何雷叔忙着写教材,就委托我来写了.
我之前也总结过两种方法,再加上雷叔这第三种方法,一起写出来,分享给大家.
方法1
这种方法是最容易想到的,但是局限性也比较大,只适用于接近直线的这种Path.但是相对的代码比较简单,也适用于动态生成Path的这种情况.仿Echarts地图用的就是这种方法.
思路:不管什么样的Path,最终整个控件其实都是一个矩形.实现这个效果就是给Path控件的透明掩码(OpacityMask)一个线性渐变画刷(LinearGradientBrush),把标识不透明度的节点用动画从一个方向推向另一个方向(DoubleAnimation控制GradientStop.Offset由0到1).
需要注意的也只是推的方向,是从左上角推向右下角,还是从右上角推向坐下角......等,那几种情况.实质就是根据Path起点和终点的坐标判断改怎样设置画刷的StartPoint和EndPoint.总结了一个方法,直接上代码吧.
1 //path的起点和终点
2 Point startPoint = figure1.StartPoint;
3 Point endPoint = arc1.Point;
4 //画刷的起点和终点,默认从左上角推向右下角,也就是X方向从左向右推,Y方向从上向下推
5 Point start = new Point(0, 0);
6 Point end = new Point(1, 1);
7 if (startPoint.X > endPoint.X)
8 {
9 //如果path起点的X大于终点的X,就说明起点在右边,需要从右向左推
10 start.X = 1;
11 end.X = 0;
12 }
13 if (startPoint.Y > endPoint.Y)
14 {
15 //如果path起点的Y大于终点的Y,就说明起点在下边,需要从下向上推
16 start.Y = 1;
17 end.Y = 0;
18 }
方法2
这种方法也很容易想到,能解决第一种方法解决不了的图形,缺点是计算相对复杂,需要有几何功底.
思路:计算出每个时刻path的终点,用帧动画或计时器直接去修改path对象.
例子比较简单了,就是个圆形.知道圆形的公式就可以了
圆心o(a,b)
(x-a)^2+(y-b)^2=r^2
x=a+r*cosθ
y=b+r*sinθ
需要注意的是几何的坐标系和wpf的坐标系不一样,wpf的坐标系是左上角是(0,0),向右X++,向下Y++.只需要把几何坐标系角度逆时针旋转90度就可以了.
具体看程序里的代码吧,比较直观.
方法3
这才是本文的重点,是雷叔提供的奇思妙想.不得不佩服雷叔扎实的基本功.感觉雷叔像邓肯,大基本功,不华丽,却是灵魂的所在.
思路:给path设置虚线,通过动画控制虚线的Offset来实现这个效果.把虚线的实线部分和虚线部分都和path设置的一样长,然后Offset也设置成path的长度,这就相当于path这显示的是虚线部分,实线部分刚好被挤出去.动画控制Offset变成0就可以了.
这么说可能比较抽象,上个图吧.
这样的话,在前台就能搞定任意静态的path了.
当然了,如果是动态的path还是需要求周长.然而这并不容易.还请各路高手指点.
源码下载: 像画笔一样慢慢画出Path.rar
方法4
额外补充第四种方法吧.不是我的,详见 http://www.cnblogs.com/tong-tong/archive/2012/10/19/2730825.html
大概意思就是给个一样的Sengment,通过点动画 PointAnimation,PointAnimationUsingPath 控制终点坐标.但是这种方法不能画贝塞尔曲线节点,因为控制的点多于一个.
上面提到的这个群是个wpf交流群,真心不错.我在这里进步很大,直接从菜鸟变得不怎么菜鸟了.推荐给大家.
群号码:152049269 欢迎各位萌新,菜鸟,高手,大神加入.分享心得,共同进步