WPF仿百度Echarts人口迁移图

图片 1

据此wpf做那么些事物一定是全然没有毛病的.附上那一个小程序
动画品质测试 有趣味的意中人能够开点动画
看看windows职分管理器里的cpu和内部存款和储蓄器的损耗境况

运动轨迹

自己用的是弧线ArcSegment
八个城市的点规定了,那么能够由此八个点的x,y,依据勾股定理计算出线段的长度.给3个点,连接那八个都市的点,可以构成叁个三角,多少个城市组成的线条对面包车型大巴万分角能够设置成一个角度参数,

这些线条固定,对角的角度固定,那么他所对应的外接圆的拱形就是定点的.大家可以依据正弦定理a/sinA=2r求出外接圆的半径.就足以画出这一个弧线来了.然后方可给那么些path的ToolTip附上鼠标移上去想体现的文字.改下ToolTip的体裁就行了

 

动画

 

都市的圆

她正是个圆圈,没什么好说的,注意一下中央的原则性就行了 Ellipse
颜色和轨道一样 ToolTip写上你想呈现的东西

都会的圆

他正是个圆形,没什么好说的,注意一下着力的一定就行了 Ellipse
颜色和轨迹一样 ToolTip写上您想体现的事物

效果图:

图片 2

 

都会的圆的动画

给Ellipse的晶莹掩码OpacityMask加2个放射型的渐变画刷RadialGradientBrush,加多个节点,offset0,offset1都以不透明的,在她们个中加二个截然透明的节点,然后动画控制offset值由0到1或由1到0,效果分化.

变更动画所须求的跑步的点,运动轨迹的path,表示到达城市的圈子

先说下差不离的思绪吧:

  1. 一经您未曾搞规划的帮您做地图的话,基本得去网上找矢量地图,转后更换来path
  2. 找到省会城市的坐标,那正是移动轨迹的源点和终点
  3. 传说起源终点生成运动轨迹的path和跑动的点,在点上做路径动画,生成2个圆,中央放到到达城市的坐标处
  4. 开首化进程的卡通
一抬手一动脚轨迹

自家用的是弧线ArcSegment
七个城市的点鲜明了,那么能够因而四个点的x,y,遵照勾股定理计算出线段的长度.给3个点,连接那七个都市的点,可以结合1个三角形,八个城市组成的线条对面包车型客车不得了角能够设置成一个角度参数,

那一个线条固定,对角的角度固定,那么他所对应的外接圆的拱形就是一定的.我们得以依照正弦定理a/sinA=2r求出外接圆的半径.就能够画出那几个弧线来了.然后得以给这一个path的ToolTip附上鼠标移上去想展现的文字.改下ToolTip的体裁就行了

有关可行性:在此以前常听人说wpf动画开多了会很卡,而本人也从没写过含有多量动画的档次,不领悟实际怎么着,这些地图显著全是动画片,所以自个儿写了个测试动画品质的小程序,生成玖拾柒个点和线跑动画,发现完全没有啥样难题.

布局

最初的初期,大家得先考虑布局,为了防范一旦做成用户控件的话,设置尺寸时地图走形.

  1. 最外层肯定要用Viewbox,按百分比缩放.必要专注的是,Viewbox内部放的控件是必须有切实可行的尺码的,它才能开始展览缩放,当然不必然需要求显式的去设置内部的Width和Height,只要当中有实际意义上的尺码就行.
  2. Viewbox内先放一个Grid,分成两列Width全体安装成auto,那样能依照在那之中央控制件的实际上尺寸来决定列宽.
  3. 0列放二个StackPanel.这么些是左手当菜单用的RadioButton的器皿,每种RadioButton都有现实的上升幅度,所以0列就有了切实的上升幅度
  4. 1列再放3个Grid,那个Grid一定要安装HorizontalAlignment=”Left”
    VerticalAlignment=”Top”,就是靠左上角布局,那样他里面包车型大巴控件就会给它撑起来,也就有了切实可行的尺码,这样Viewbox才能够缩放
  5. 把地图的path全部置于这些Grid里,path的Stretch必须是None,这样path就会把这么些Grid给撑起来,在那几个Grid里面全数path的上面再放1个Grid,用来做变更的卡通用的图样的器皿,他的坐标是和父级Grid的坐标重合的

地图

关于找地图,倒霉找,小编从未什么好的心得.反正目标就是找一个涵盖省会标记的地图矢量图,只固然矢量图,大家就应当有点子把他转换来Xmal.

小编是在百度文Curry找到2个ppt版的矢量地图,0下载券
矢量地图素材 下载下来后用ppt打开,要用微软的,别的也许保留不了源文件,右键地图=>另存为=>选.emf格式,然后用Microsoft
Expression Design打开,然后右键=>导出

图片 3

那样就收获了大家要的path,然后找到各种省会所对应的path,取他们的Canvas.Left+Width/2
Canvas.Top+Height/2 正是对应坐标点的(x,y).(小编算的没这么精细,正是大概加了下.那个工作太干燥,那不是重点.)

先吐槽下本人找的那几个地图,新加坡和萨格勒布以连在一起的,泰州也一去不复返不见了,2个都市全方位合成了一个path.所以提出我们温馨再去找找

留神wpf的坐标都以以左上角开端的(0,0)
向右加x值 向下加y值 前面大家转变的图片定位时都要 x值-本人Width/2
y值-本身Height/2 那样才能让图形的着力对准要求稳定的坐标点

有了地图和坐标,我们就足以做上面包车型地铁干活了

关于可行性:从前常听人说wpf动画开多了会很卡,而小编也尚未写过含有大量动画片的种类,不明了实际怎样,那个地图显著全是卡通片,所以小编写了个测试动画品质的小程序,生成九二十一个点和线跑动画,发现完全没有怎么难点.

城市的圆的动画片

给Ellipse的透明掩码OpacityMask加二个放射型的渐变画刷RadialGradientBrush,加四个节点,offset0,offset1都是不透明的,在他们中间加二个通通透明的节点,然后动画控制offset值由0到1或由1到0,效果分化.

动画

布局

早期的最初,大家得先考虑布局,为了防止一旦做成用户控件的话,设置尺寸时地图走形.

  1. 最外层肯定要用Viewbox,按百分比缩放.须求留意的是,Viewbox内部放的控件是必须有实际的尺寸的,它才能拓展缩放,当然不自然必必要显式的去设置内部的Width和Height,只要当中有实际意义上的尺寸就行.
  2. Viewbox内先放二个Grid,分成两列Width全体装置成auto,那样能依照当中央控制件的实际尺寸来控制列宽.
  3. 0列放二个StackPanel.那么些是左侧当菜单用的RadioButton的器皿,种种RadioButton都有具体的肥瘦,所以0列就有了具体的大幅
  4. 1列再放二个Grid,那一个Grid一定要安装HorizontalAlignment=”Left”
    VerticalAlignment=”Top”,就是靠左上角布局,那样他里头的控件就会给它撑起来,也就有了实际的尺寸,那样Viewbox才能够缩放
  5. 把地图的path全体松开这么些Grid里,path的Stretch必须是None,那样path就会把这些Grid给撑起来,在这些Grid里面有着path的底下再放3个Grid,用来做变更的卡通片用的图形的器皿,他的坐标是和父级Grid的坐标重合的

GitHub地址:https://github.com/ptddqr/wpf-echarts-map/tree/master

从而wpf做那个事物必定是一心没非常的.附上这么些小程序
卡通品质测试 有趣味的情人能够开点动画
看看windows任务管理器里的cpu和内部存款和储蓄器的损耗景况

  1. 假诺你从未搞规划的帮你做地图的话,基本得去网上找矢量地图,转后更换来path
  2. 找到省会城市的坐标,那正是运动轨迹的起源和终端
  3. 基于起源终点生成运动轨迹的path和跑动的点,在点上做路径动画,生成一个圆,大旨放到到达城市的坐标处
  4. 早先化进程的动画

先说下大概的笔触吧:

地图

至于找地图,不佳找,我未曾怎么好的心得.反正指标正是找三个暗含省会标记的地图矢量图,只借使矢量图,我们就应该有主意把她转换来Xmal.

本身是在百度文库里找到五个ppt版的矢量地图,0下载券
矢量地图素材 下载下来后用ppt打开,要用微软的,其余恐怕保留不了源文件,右键地图=>另存为=>选.emf格式,然后用Microsoft
Expression Design打开,然后右键=>导出

图片 4

如此那般就拿走了大家要的path,然后找到每一个省聚会场馆对应的path,取他们的Canvas.Left+Width/2
Canvas.Top+Height/2 正是对应坐标点的(x,y).(笔者算的没那样精致,便是大约加了下.那么些工作太单调,那不是重点.)

先吐槽下小编找的这些地图,Hong Kong和丹佛是连在一起的,遵义也消解不见了,2个都市中华全国总工会体合成了多少个path.所以建议我们自个儿再去找找

在意wpf的坐标都以以左上角起初的(0,0)
向右加x值 向下加y值 后边大家转变的图形定位时都要 x值-本身Width/2
y值-自个儿Height/2 那样才能让图形的着力对准供给一定的坐标点

有了地图和坐标,大家就足以做上边包车型地铁行事了

 

有关赫赫有名的百度Echarts笔者就不多说了
不领会的心上人一贯看官方的事例吧 http://echarts.baidu.com/examples.html

伊始化进程的动画片

那有的卡通其实便是持筹握算时间,在适宜的年月尾步合适的动画.

一抬手一动脚轨迹的展现:正是给移动轨迹path的晶莹掩码给一个线型渐变画刷,依照向左,右,上,下移动,设置好StartPoint和EndPoint,然后五个节点3个晶莹剔透,2个不透明,同时从0向1做动画,需求注意的是若是一前一后运动,一定要透明的不得了节点在前面运动,

不然会产出很古怪的行事,把这些动画的时日设置成跑动的点的二分一的时间.那样轨迹比点跑的快,不至于点跑过去了,路径还并未表现到那

有关城市的圆,这一部分加的可比多,首先能够用二个DoubleAnimation来控制Ellipse的发光度,伊始时间是轨道显示的时刻,相当于点的时刻/2,这样刚好轨迹显示到圆时,圆开首表现,动画时间也设置成轨迹展现时间,那样刚好点运动到圆的时候,圆已经完全展现完.

下一场加3个ColorAnimation,来支配圆透明掩码里放射画刷的第一个节点,也便是控制点,让他改成透明,用时0就足以,那样就能够继续圆的放射型动画了.初始时间正是点运动到圆的时间.

接下去正是一些RadioButton,ToolTip,Path的体制难点了.那有的大家看心境,做个温馨喜爱的样式就足以了.

 

2016-08-01更新:

将名称注册动画改为对象注册动画

图片 5图片 6

  1         private void AddPointToStoryboard(Grid runPoint, Ellipse toEll, Storyboard sb, Path particlePath, double l, ProvincialCapital from, MapToItem toItem)
  2         {
  3             double pointTime = l / m_Speed;//点运动所需的时间
  4             double particleTime = pointTime / 2;//轨迹呈现所需时间(跑的比点快两倍)
  5             ////生成为控件注册名称的guid
  6             //string name = Guid.NewGuid().ToString().Replace("-", "");
  7 
  8             #region 运动的点
  9             TransformGroup tfg = new TransformGroup();
 10             MatrixTransform mtf = new MatrixTransform();
 11             tfg.Children.Add(mtf);
 12             TranslateTransform ttf = new TranslateTransform(-runPoint.Width / 2, -runPoint.Height / 2);//纠正最上角沿path运动到中心沿path运动
 13             tfg.Children.Add(ttf);
 14             runPoint.RenderTransform = tfg;
 15             //this.RegisterName("m" + name, mtf);
 16 
 17             MatrixAnimationUsingPath maup = new MatrixAnimationUsingPath();
 18             maup.PathGeometry = particlePath.Data.GetFlattenedPathGeometry();
 19             maup.Duration = new Duration(TimeSpan.FromSeconds(pointTime));
 20             maup.RepeatBehavior = RepeatBehavior.Forever;
 21             maup.AutoReverse = false;
 22             maup.IsOffsetCumulative = false;
 23             maup.DoesRotateWithTangent = true;
 24             //Storyboard.SetTargetName(maup, "m" + name);
 25             //Storyboard.SetTargetProperty(maup, new PropertyPath(MatrixTransform.MatrixProperty));
 26             Storyboard.SetTarget(maup, runPoint);
 27             Storyboard.SetTargetProperty(maup, new PropertyPath("(Grid.RenderTransform).Children[0].(MatrixTransform.Matrix)"));
 28             sb.Children.Add(maup);
 29             #endregion
 30 
 31             #region 达到城市的圆
 32             //this.RegisterName("ell" + name, toEll);
 33             //轨迹到达圆时 圆呈现
 34             DoubleAnimation ellda = new DoubleAnimation();
 35             ellda.From = 0.2;//此处值设置0-1会有不同的呈现效果
 36             ellda.To = 1;
 37             ellda.Duration = new Duration(TimeSpan.FromSeconds(particleTime));
 38             ellda.BeginTime = TimeSpan.FromSeconds(particleTime);//推迟动画开始时间 等轨迹连接到圆时 开始播放圆的呈现动画
 39             ellda.FillBehavior = FillBehavior.HoldEnd;
 40             //Storyboard.SetTargetName(ellda, "ell" + name);
 41             //Storyboard.SetTargetProperty(ellda, new PropertyPath(Ellipse.OpacityProperty));
 42             Storyboard.SetTarget(ellda, toEll);
 43             Storyboard.SetTargetProperty(ellda, new PropertyPath(Ellipse.OpacityProperty));
 44             sb.Children.Add(ellda);
 45             //圆呈放射状
 46             RadialGradientBrush rgBrush = new RadialGradientBrush();
 47             GradientStop gStop0 = new GradientStop(Color.FromArgb(255, 0, 0, 0), 0);
 48             //此为控制点 color的a值设为0 off值走0-1 透明部分向外放射 初始设为255是为了初始化效果 开始不呈放射状 等跑动的点运动到城市的圆后 color的a值才设为0开始呈现放射动画
 49             GradientStop gStopT = new GradientStop(Color.FromArgb(255, 0, 0, 0), 0);
 50             GradientStop gStop1 = new GradientStop(Color.FromArgb(255, 0, 0, 0), 1);
 51             rgBrush.GradientStops.Add(gStop0);
 52             rgBrush.GradientStops.Add(gStopT);
 53             rgBrush.GradientStops.Add(gStop1);
 54             toEll.OpacityMask = rgBrush;
 55             //this.RegisterName("e" + name, gStopT);
 56             //跑动的点达到城市的圆时 控制点由不透明变为透明 color的a值设为0 动画时间为0
 57             ColorAnimation ca = new ColorAnimation();
 58             ca.To = Color.FromArgb(0, 0, 0, 0);
 59             ca.Duration = new Duration(TimeSpan.FromSeconds(0));
 60             ca.BeginTime = TimeSpan.FromSeconds(pointTime);
 61             ca.FillBehavior = FillBehavior.HoldEnd;
 62             //Storyboard.SetTargetName(ca, "e" + name);
 63             //Storyboard.SetTargetProperty(ca, new PropertyPath(GradientStop.ColorProperty));
 64             Storyboard.SetTarget(ca, toEll);
 65             Storyboard.SetTargetProperty(ca, new PropertyPath("(Ellipse.OpacityMask).(GradientBrush.GradientStops)[1].(GradientStop.Color)"));
 66             sb.Children.Add(ca);
 67             //点达到城市的圆时 呈现放射状动画 控制点的off值走0-1 透明部分向外放射
 68             DoubleAnimation eda = new DoubleAnimation();
 69             eda.To = 1;
 70             eda.Duration = new Duration(TimeSpan.FromSeconds(2));
 71             eda.RepeatBehavior = RepeatBehavior.Forever;
 72             eda.BeginTime = TimeSpan.FromSeconds(particleTime);
 73             //Storyboard.SetTargetName(eda, "e" + name);
 74             //Storyboard.SetTargetProperty(eda, new PropertyPath(GradientStop.OffsetProperty));
 75             Storyboard.SetTarget(eda, toEll);
 76             Storyboard.SetTargetProperty(eda, new PropertyPath("(Ellipse.OpacityMask).(GradientBrush.GradientStops)[1].(GradientStop.Offset)"));
 77             sb.Children.Add(eda);
 78             #endregion
 79 
 80             #region 运动轨迹
 81             //找到渐变的起点和终点
 82             Point startPoint = GetProvincialCapitalPoint(from);
 83             Point endPoint = GetProvincialCapitalPoint(toItem.To);
 84             Point start = new Point(0, 0);
 85             Point end = new Point(1, 1);
 86             if (startPoint.X > endPoint.X)
 87             {
 88                 start.X = 1;
 89                 end.X = 0;
 90             }
 91             if (startPoint.Y > endPoint.Y)
 92             {
 93                 start.Y = 1;
 94                 end.Y = 0;
 95             }
 96             LinearGradientBrush lgBrush = new LinearGradientBrush();
 97             lgBrush.StartPoint = start;
 98             lgBrush.EndPoint = end;
 99             GradientStop lgStop0 = new GradientStop(Color.FromArgb(255, 0, 0, 0), 0);
100             GradientStop lgStop1 = new GradientStop(Color.FromArgb(0, 0, 0, 0), 0);
101             lgBrush.GradientStops.Add(lgStop0);
102             lgBrush.GradientStops.Add(lgStop1);
103             particlePath.OpacityMask = lgBrush;
104             //this.RegisterName("p0" + name, lgStop0);
105             //this.RegisterName("p1" + name, lgStop1);
106             //运动轨迹呈现
107             DoubleAnimation pda0 = new DoubleAnimation();
108             pda0.To = 1;
109             pda0.Duration = new Duration(TimeSpan.FromSeconds(particleTime));
110             pda0.FillBehavior = FillBehavior.HoldEnd;
111             //Storyboard.SetTargetName(pda0, "p0" + name);
112             //Storyboard.SetTargetProperty(pda0, new PropertyPath(GradientStop.OffsetProperty));
113             Storyboard.SetTarget(pda0, particlePath);
114             Storyboard.SetTargetProperty(pda0, new PropertyPath("(Path.OpacityMask).(GradientBrush.GradientStops)[0].(GradientStop.Offset)"));
115             sb.Children.Add(pda0);
116             DoubleAnimation pda1 = new DoubleAnimation();
117             //pda1.From = 0.5; //此处解开注释 值设为0-1 会有不同的轨迹呈现效果
118             pda1.To = 1;
119             pda1.Duration = new Duration(TimeSpan.FromSeconds(particleTime));
120             pda1.FillBehavior = FillBehavior.HoldEnd;
121             //Storyboard.SetTargetName(pda1, "p1" + name);
122             //Storyboard.SetTargetProperty(pda1, new PropertyPath(GradientStop.OffsetProperty));
123             Storyboard.SetTarget(pda1, particlePath);
124             Storyboard.SetTargetProperty(pda1, new PropertyPath("(Path.OpacityMask).(GradientBrush.GradientStops)[1].(GradientStop.Offset)"));
125             sb.Children.Add(pda1);
126             #endregion
127         }

View Code

2016-12-19更新:

发布到GitHub,地址:https://github.com/ptddqr/wpf-echarts-map/tree/master

 

源码下载:仿百度Echarts人口迁移图.zip

转移动画所急需的跑动的点,运动轨迹的path,表示到达城市的圈子

GitHub地址:https://github.com/ptddqr/wpf-echarts-map/tree/master

点沿着轨迹跑的动画

那部分动画,笔者就隐瞒了,参考周银辉的博客 http://www.cnblogs.com/zhouyinhui/archive/2007/07/31/837893.html

 

奔走的点

跑步的点,作者用了八个Grid里面套了一个path和3个Ellipse.

椭圆做阴影,颜色和轨道一样,加1个透明掩码OpacityMask,里面是2个放射型的渐变画刷RadialGradientBrush.原点GradientOrigin(0.8,0.5) offset0处安装为不透明,offset1处不发光度设置为2/16.

水滴型的path作者就用blend里的钢笔随意画了二个,得到了它的Data. Fill给四个线型渐变画刷,StartPoint(0,0),EndPoint(1,0),offset0给1个半透明的轨迹色,offset1给个不透明的乌紫.

那一个Grid的IsHitTestVisible能够安装成false,不插手命中测试,那样鼠标在轨道上时,点通过时,不会堵塞轨迹ToolTip的呈现.

代码控,想本身写path的话,思路能够参考笔者的另一篇博客
WPF绘制不难常用的Path

初步化进度的动画

那部分动画其实就是计量时间,在适度的日子伊始合适的动画.

活动轨迹的表现:正是给移动轨迹path的晶莹掩码给一个线型渐变画刷,依据向左,右,上,下移动,设置好StartPoint和EndPoint,然后多少个节点三个晶莹剔透,二个不透明,同时从0向1做动画,需求小心的是只要一前一后运动,一定要透明的要命节点在前方运动,

不然会出现很蹊跷的作为,把那么些动画的年月设置成跑动的点的十分之五的时间.那样轨迹比点跑的快,不至于点跑过去了,路径还从未显示到那

至于城市的圆,那有个别加的可比多,首先能够用三个DoubleAnimation来控制Ellipse的光滑度,开首时间是轨道展现的小运,也正是点的小运/2,那样刚好轨迹显示到圆时,圆开首显现,动画时间也设置成轨迹呈现时间,那样刚好点运动到圆的时候,圆已经完全显示完.

接下来加三个ColorAnimation,来控制圆透明掩码里放射画刷的第二个节点,也正是控制点,让他成为透明,用时0就能够,那样就能够持续圆的放射型动画了.起首时间正是点运动到圆的时间.

接下去就是局地RadioButton,ToolTip,Path的体裁难点了.那部分大家看心境,做个自身喜好的体制就足以了.

 

2016-08-01更新:

将名称注册动画改为对象注册动画

图片 7图片 8

  1         private void AddPointToStoryboard(Grid runPoint, Ellipse toEll, Storyboard sb, Path particlePath, double l, ProvincialCapital from, MapToItem toItem)
  2         {
  3             double pointTime = l / m_Speed;//点运动所需的时间
  4             double particleTime = pointTime / 2;//轨迹呈现所需时间(跑的比点快两倍)
  5             ////生成为控件注册名称的guid
  6             //string name = Guid.NewGuid().ToString().Replace("-", "");
  7 
  8             #region 运动的点
  9             TransformGroup tfg = new TransformGroup();
 10             MatrixTransform mtf = new MatrixTransform();
 11             tfg.Children.Add(mtf);
 12             TranslateTransform ttf = new TranslateTransform(-runPoint.Width / 2, -runPoint.Height / 2);//纠正最上角沿path运动到中心沿path运动
 13             tfg.Children.Add(ttf);
 14             runPoint.RenderTransform = tfg;
 15             //this.RegisterName("m" + name, mtf);
 16 
 17             MatrixAnimationUsingPath maup = new MatrixAnimationUsingPath();
 18             maup.PathGeometry = particlePath.Data.GetFlattenedPathGeometry();
 19             maup.Duration = new Duration(TimeSpan.FromSeconds(pointTime));
 20             maup.RepeatBehavior = RepeatBehavior.Forever;
 21             maup.AutoReverse = false;
 22             maup.IsOffsetCumulative = false;
 23             maup.DoesRotateWithTangent = true;
 24             //Storyboard.SetTargetName(maup, "m" + name);
 25             //Storyboard.SetTargetProperty(maup, new PropertyPath(MatrixTransform.MatrixProperty));
 26             Storyboard.SetTarget(maup, runPoint);
 27             Storyboard.SetTargetProperty(maup, new PropertyPath("(Grid.RenderTransform).Children[0].(MatrixTransform.Matrix)"));
 28             sb.Children.Add(maup);
 29             #endregion
 30 
 31             #region 达到城市的圆
 32             //this.RegisterName("ell" + name, toEll);
 33             //轨迹到达圆时 圆呈现
 34             DoubleAnimation ellda = new DoubleAnimation();
 35             ellda.From = 0.2;//此处值设置0-1会有不同的呈现效果
 36             ellda.To = 1;
 37             ellda.Duration = new Duration(TimeSpan.FromSeconds(particleTime));
 38             ellda.BeginTime = TimeSpan.FromSeconds(particleTime);//推迟动画开始时间 等轨迹连接到圆时 开始播放圆的呈现动画
 39             ellda.FillBehavior = FillBehavior.HoldEnd;
 40             //Storyboard.SetTargetName(ellda, "ell" + name);
 41             //Storyboard.SetTargetProperty(ellda, new PropertyPath(Ellipse.OpacityProperty));
 42             Storyboard.SetTarget(ellda, toEll);
 43             Storyboard.SetTargetProperty(ellda, new PropertyPath(Ellipse.OpacityProperty));
 44             sb.Children.Add(ellda);
 45             //圆呈放射状
 46             RadialGradientBrush rgBrush = new RadialGradientBrush();
 47             GradientStop gStop0 = new GradientStop(Color.FromArgb(255, 0, 0, 0), 0);
 48             //此为控制点 color的a值设为0 off值走0-1 透明部分向外放射 初始设为255是为了初始化效果 开始不呈放射状 等跑动的点运动到城市的圆后 color的a值才设为0开始呈现放射动画
 49             GradientStop gStopT = new GradientStop(Color.FromArgb(255, 0, 0, 0), 0);
 50             GradientStop gStop1 = new GradientStop(Color.FromArgb(255, 0, 0, 0), 1);
 51             rgBrush.GradientStops.Add(gStop0);
 52             rgBrush.GradientStops.Add(gStopT);
 53             rgBrush.GradientStops.Add(gStop1);
 54             toEll.OpacityMask = rgBrush;
 55             //this.RegisterName("e" + name, gStopT);
 56             //跑动的点达到城市的圆时 控制点由不透明变为透明 color的a值设为0 动画时间为0
 57             ColorAnimation ca = new ColorAnimation();
 58             ca.To = Color.FromArgb(0, 0, 0, 0);
 59             ca.Duration = new Duration(TimeSpan.FromSeconds(0));
 60             ca.BeginTime = TimeSpan.FromSeconds(pointTime);
 61             ca.FillBehavior = FillBehavior.HoldEnd;
 62             //Storyboard.SetTargetName(ca, "e" + name);
 63             //Storyboard.SetTargetProperty(ca, new PropertyPath(GradientStop.ColorProperty));
 64             Storyboard.SetTarget(ca, toEll);
 65             Storyboard.SetTargetProperty(ca, new PropertyPath("(Ellipse.OpacityMask).(GradientBrush.GradientStops)[1].(GradientStop.Color)"));
 66             sb.Children.Add(ca);
 67             //点达到城市的圆时 呈现放射状动画 控制点的off值走0-1 透明部分向外放射
 68             DoubleAnimation eda = new DoubleAnimation();
 69             eda.To = 1;
 70             eda.Duration = new Duration(TimeSpan.FromSeconds(2));
 71             eda.RepeatBehavior = RepeatBehavior.Forever;
 72             eda.BeginTime = TimeSpan.FromSeconds(particleTime);
 73             //Storyboard.SetTargetName(eda, "e" + name);
 74             //Storyboard.SetTargetProperty(eda, new PropertyPath(GradientStop.OffsetProperty));
 75             Storyboard.SetTarget(eda, toEll);
 76             Storyboard.SetTargetProperty(eda, new PropertyPath("(Ellipse.OpacityMask).(GradientBrush.GradientStops)[1].(GradientStop.Offset)"));
 77             sb.Children.Add(eda);
 78             #endregion
 79 
 80             #region 运动轨迹
 81             //找到渐变的起点和终点
 82             Point startPoint = GetProvincialCapitalPoint(from);
 83             Point endPoint = GetProvincialCapitalPoint(toItem.To);
 84             Point start = new Point(0, 0);
 85             Point end = new Point(1, 1);
 86             if (startPoint.X > endPoint.X)
 87             {
 88                 start.X = 1;
 89                 end.X = 0;
 90             }
 91             if (startPoint.Y > endPoint.Y)
 92             {
 93                 start.Y = 1;
 94                 end.Y = 0;
 95             }
 96             LinearGradientBrush lgBrush = new LinearGradientBrush();
 97             lgBrush.StartPoint = start;
 98             lgBrush.EndPoint = end;
 99             GradientStop lgStop0 = new GradientStop(Color.FromArgb(255, 0, 0, 0), 0);
100             GradientStop lgStop1 = new GradientStop(Color.FromArgb(0, 0, 0, 0), 0);
101             lgBrush.GradientStops.Add(lgStop0);
102             lgBrush.GradientStops.Add(lgStop1);
103             particlePath.OpacityMask = lgBrush;
104             //this.RegisterName("p0" + name, lgStop0);
105             //this.RegisterName("p1" + name, lgStop1);
106             //运动轨迹呈现
107             DoubleAnimation pda0 = new DoubleAnimation();
108             pda0.To = 1;
109             pda0.Duration = new Duration(TimeSpan.FromSeconds(particleTime));
110             pda0.FillBehavior = FillBehavior.HoldEnd;
111             //Storyboard.SetTargetName(pda0, "p0" + name);
112             //Storyboard.SetTargetProperty(pda0, new PropertyPath(GradientStop.OffsetProperty));
113             Storyboard.SetTarget(pda0, particlePath);
114             Storyboard.SetTargetProperty(pda0, new PropertyPath("(Path.OpacityMask).(GradientBrush.GradientStops)[0].(GradientStop.Offset)"));
115             sb.Children.Add(pda0);
116             DoubleAnimation pda1 = new DoubleAnimation();
117             //pda1.From = 0.5; //此处解开注释 值设为0-1 会有不同的轨迹呈现效果
118             pda1.To = 1;
119             pda1.Duration = new Duration(TimeSpan.FromSeconds(particleTime));
120             pda1.FillBehavior = FillBehavior.HoldEnd;
121             //Storyboard.SetTargetName(pda1, "p1" + name);
122             //Storyboard.SetTargetProperty(pda1, new PropertyPath(GradientStop.OffsetProperty));
123             Storyboard.SetTarget(pda1, particlePath);
124             Storyboard.SetTargetProperty(pda1, new PropertyPath("(Path.OpacityMask).(GradientBrush.GradientStops)[1].(GradientStop.Offset)"));
125             sb.Children.Add(pda1);
126             #endregion
127         }

View Code

2016-12-19更新:

发布到GitHub,地址:https://github.com/ptddqr/wpf-echarts-map/tree/master

 

源码下载:仿百度Echarts人口迁移图.zip

点沿着轨迹跑的动画片

那有的动画,小编就隐瞒了,参考周银辉的博客 http://www.cnblogs.com/zhouyinhui/archive/2007/07/31/837893.html

 

效果图:

至于远近有名的百度Echarts笔者就不多说了
不打听的朋友一贯看官方的例子吧 http://echarts.baidu.com/examples.html

跑步的点

奔走的点,作者用了3个Grid里面套了一个path和八个Ellipse.

椭圆做阴影,颜色和轨道一样,加3个透明掩码OpacityMask,里面是2个放射型的渐变画刷RadialGradientBrush.原点GradientOrigin(0.8,0.5) offset0处安装为不透明,offset1处不折射率设置为2/16.

水滴型的path笔者就用blend里的钢笔随意画了四个,得到了它的Data. Fill给3个线型渐变画刷,StartPoint(0,0),EndPoint(1,0),offset0给二个半透明的轨迹色,offset1给个不透明的铁红.

以此Grid的IsHitTestVisible能够设置成false,不出席命中测试,那样鼠标在轨道上时,点通过时,不会卡住轨迹ToolTip的显示.

代码控,想协调写path的话,思路能够参见作者的另一篇博客
WPF绘制不难常用的Path