WPF仿百度Echarts人口迁移图

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

UX设计受到之几只重要词:CX、UX、UI

CX_Customer Experience :顾客感受设计;UX_User Experience:
用户体验设计;UI_user interface: 用户界面设计。

CX指顾客对和一个品牌、公司发生的互相的感知。这是一个尤其宏观的概念,覆盖了一个品牌以及买主发生相互的持有渠道,比如顾客感受的上下和旅店里的灯光、背景音乐甚至是路边的同一虽然广告都见面出涉嫌,这种体验会以一个完完全全的样式给消费者对品牌有好或坏的印象,进而影响到那个是否成最终用户及忠诚度。

UX指终端使用者与一个小卖部之服务和制品竞相的拥有范畴,常见例子的哪怕是App/网站或者一个物产品的计划中会大量采取到UX。所以马上是一个对立微观之体会设计范围。UX专注让极端使用者——使用产品、服务之总人口,而顾客在一些地方或者与极用户重合,但是顾客为或是代表其他人用购买行为!所以消费者不肯定是最终用户,也就是说UX不克涵盖顾客的经验。

UI则是用户界面设计,主要专注让活规模的界面视觉呈现。国内对UI的认已特别普及,在浅无多废话。

从今点三个概念着,可以归结出如下的直观图来表示三者的隶属关系。即UI设计属于UX用户体验范畴内,而CX包含的限最广大。

CX&UX的异同

至于大名鼎鼎的百度Echarts我哪怕不多说了
不打听之爱侣一直扣官方的例子吧 http://echarts.baidu.com/examples.html

UX&UX&UI的异同点是何等呐? 

1.1  范畴不同:

CX是客户及品牌有方面的竞相总和的总称。
从广告及客户服务,直到产品交付,每个这些互动的圆影响塑造了客户针对成品要劳务产品的感想。

UX 是丁以及活(APP、WEB、WATCH、TV、智能设备相当)之间的干;体验差之 UX
会被一个秘客户质疑你的品牌及其服务的而信度(CX)

即CX着眼于品牌的皆渠道体验,而UX专注于一些还细分的出品,比如网站、App、软件系统等。(UX设计以及制品相当下,而CX
Design与品牌合作)

1.2 关注点不同:

CX更关爱通过广告、顾客服务同品牌营销等作为来多企业之销售额。更珍惜品牌名和顾客服务。

UX更小心于改善产品、服务最终的可用性来达成近似的目标。关注于信息架构、互动设计、内容策略、同理心、用户研究、可用性分析和测试相当。

1.3 二者相辅相成:

勿为CX的代价损坏UX,反之亦然,二者为是互为辅助关系。

CX Design vs UX Design: How They Differ

由国内当下向上之现状,大部分尚处于UI设计及UX设计之咀嚼水平,所以国内公众对CX的体味还处在比较逊色品位。但是相信随着一代之变化和同行业领域的日益成熟,CX将见面超越UX而进一步普及。

*
*

拉开阅读:Customer Experience Is the Future of Design:

https://uxmag.com/articles/customer-experience-is-the-future-of-design

CX将会是统筹之前途  Customer Experience Is the Future of
Design_https://uxmag.com/articles/customer-experience-is-the-future-of-design 

效果图:

Tesla’s customer experience

下面通过特斯拉(Tesla’s CX)的案例来叫大家更鲜明的刺探CX客户体验。

案例证明: Tesla’s customer experience

手续一样:网上消息查询

当我们决定使选购同辆特斯拉汽车时,顾客需要事先刊登陆官网进行信息查询。当我们在浏览信息上,特斯拉网站通过唤起、通知等互相体验来报告潜在消费群体,并且为推送适合我们的连锁配置;允许浏览特斯拉的技艺、学习电动车、配置汽车等文化——同时建议顾客将这些分享到社交平台如Facebook、Email、通讯录好友Friends

手续二:体验店内亲自体验

通下你可能会见亲自到经验店里去感受试驾,这个时节特斯拉体验店专门设置了咖啡馆、网络服务、有特别的成品专家为您服务、开放性的服务空间,让用户能够于舒心的环境暨劳务中,了解你们想获得的漫天讯息。并且你能够浏览特斯拉的艺工作规律,亲自用肉眼、触觉、听觉等成套感官去感受。

步骤三:购买下单流程

于下单前,特斯拉可以允许消费者于同等完善时外转移配置model S,
同时您专属的问讯顾问也会见管您推荐给当地送货团队

步骤四:客户所有权服务(优质售后服务)

工作人员前往客户家开展定期年检、固件检修、设备更新等。创新的”house
call”服务,是客户不管哪里还能安然的采取特斯拉的成品。

手续五: 独家会员服务

说到底你得进入特斯拉底个别会员服务体系,特斯拉将衷心希望您将世界各地的都市特斯拉视为您自己的VIP贵宾私人网络的会员。给买主一样栽宾至如归的感到。

冲以上特斯拉的案例,我们再能清楚地懂得CX的第一,它是同栽全流程的体验式服务。在普链条环节遇,会产生那么些触点(Touch
Points)

CX体验差的案例_某机场

有鉴于此,CX的感受于一切公司的商业价值影响挺充分。做也CX设计师,我们需要调出产品规模的用户体验设计,而当还高瞻远瞩于全链条的计划性。——我想CX恰好也是2017年阿里系提出的“全链路设计师”的一个思路来吧!

流动:部分图形来自网络,转载请注明出处!

延伸阅读: 

UX and CX: What’s the
difference? https://www.marketingentourage.com.au/blog/ux-cx-whats-the-difference

https://www.capgemini.com/2015/02/ux-vs-cx-and-the-difference-between-a-ux-designer-and-a-cx-designer-1/\#

图片 1

 

有关可行性:以前常听人说wpf动画开多矣会生卡,而自己啊从不写了含有大量动画的类型,不知情实际怎样,这个地图显然都是动画片,所以我写了只测试动画性能的略微序,生成100独点以及线跑动画,发现了无什么问题.

故此wpf做这东西必定是全无问题的.附上这小程序
动画性能测试 有趣味的意中人可开点动画
看看windows任务管理器里之cpu和内存的耗费情况

 

预先说下约的笔触吧:

  1. 倘您从未打出规划之扶植您开地图的言语,基本得错过网上查找矢量地图,转后转换成path
  2. 找到省会城市的坐标,这就算是倒轨迹的起点和终点
  3. 根据起点终点生成运动轨迹的path和跑的接触,在接触达开路径动画,生成一个完善,中心放到到达城市之坐标处
  4. 初始化过程的卡通

布局

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

  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的下面还放开一个Grid,用来开变通的卡通用的图形的器皿,他的坐标是暨父级Grid的坐标重合的

地图

有关寻找地图,不好找,我尚未啊好的心得.反正目的就是摸索一个富含省会标记的地图矢量图,只要是矢量图,我们虽活该发生方法将他换成为Xmal.

自我是于百度文库里找到一个ppt版的矢量地图,0下充斥券
矢量地图素材 下充斥下来后就此ppt打开,要用微软的,别的可能保留不了自文件,右键地图=>另存为=>选.emf格式,然后据此Microsoft
Expression Design打开,然后右键=>导出

图片 2

如此这般即便得到了咱们要之path,然后找到每个省会所对应的path,取他们之Canvas.Left+Width/2
Canvas.Top+Height/2 就是本着许坐标点的(x,y).(我算的无这样精致,就是大体加了下.这个工作最干燥,这不是重点.)

优先吐槽下自己搜寻的这地图,北京跟天津凡是连在一起的,廊坊也磨不见了,3个城市全合成了一个path.所以建议大家温馨再次失去搜寻找

瞩目wpf的坐标都是以左上角开始的(0,0)
向右加x值 向下加y值 后面我们转变的图片定位时犹设 x值-自身Width/2
y值-自身Height/2 这样才会叫图形的中心对需要一定的坐标点

生了地图及坐标,我们不怕可以开下的行事了

浮动动画所需要之奔跑的点,运动轨迹的path,表示到市之圈子

跑步的接触

奔走的点,我为此了一个Grid里面学了一个path和一个Ellipse.

椭圆举行阴影,颜色跟轨迹一样,加一个晶莹剔透掩码OpacityMask,里面凡是一个放射型的渐变画刷RadialGradientBrush.原点GradientOrigin(0.8,0.5) offset0高居安装为未透明,offset1处在不透明度设置为2/16.

水滴型的path我哪怕因此blend里之钢笔随意画了一个,得到了她的Data. Fill给一个线型渐变画刷,StartPoint(0,0),EndPoint(1,0),offset0给一个半晶莹剔透底轨迹色,offset1深受个非透明的纯白.

是Grid的IsHitTestVisible可以装成false,不介入中测试,这样鼠标在轨道及时,点通过时,不会见死轨迹ToolTip的显示.

代表码控,想协调写path的话,思路好参见我的其它一样篇博客
WPF绘制简单常用的Path

都之圆

外即便是独圆形,没什么好说的,注意一下骨干的一贯就是推行了 Ellipse
颜色与轨迹一样 ToolTip写及而想展示的物

活动轨迹

自我用的是弧线ArcSegment
两独都之触发确定了,那么得透过简单独点之x,y,根据勾股定理计算出线段落的长度.给一个触及,连接这片只都的触发,可以结合一个三角形,两只都整合的线条对面的好角可以安装成一个角度参数,

是线条固定,对竞赛的角度固定,那么他所对应的外接圆之半圆形就是稳定的.我们得以依据正弦定理a/sinA=2r求来他搭圆之半径.即便可以画出这个弧线来了.然后可为这个path的ToolTip附上鼠标移上失去思展示的文字.改下ToolTip的体制就实行了

动画

点沿着轨迹跑的卡通片

立即一部分动画片,我不怕背着了,参考周银辉的博客 http://www.cnblogs.com/zhouyinhui/archive/2007/07/31/837893.html

 

都会的圆满之动画片

受Ellipse的晶莹掩码OpacityMask加一个放射型的渐变画刷RadialGradientBrush,加三单节点,offset0,offset1都是休透明的,在她们中间加一个了透明底节点,然后动画控制offset值由0到1或者出于1到0,效果不同.

初始化过程的动画

立刻部分动画片其实就是是精打细算时间,在适宜的岁月开当的动画.

倒轨迹的显现:就是为移动轨迹path的晶莹掩码给一个线型渐变画刷,根据往左,右,上,下走,设置好StartPoint和EndPoint,然后简单单节点一个晶莹剔透,一个免透明,同时从0向1举行动画,需要留意的是如一前一后运动,一定要透明的怪节点在眼前走,

不然会起异常奇特的表现,把这个动画的日子设置成跑的接触的一半底时间.这样轨迹比点跑的快,不至于点走过去了,路径还从来不显现到那么

关于市之无微不至,这有的加的可比多,首先可以据此一个DoubleAnimation来控制Ellipse的透明度,开始日是轨道呈现的时刻,也就是沾的工夫/2,这样恰好好轨迹呈现到圆时,圆开始显现,动画时间吗装成轨迹呈现时间,这样恰好好点走及完善的时节,圆就完全见完.

接下来加一个ColorAnimation,来支配到透明掩码里放射画刷的第二单节点,也即是控制点,让他成为透明,用时0就好,这样就是可持续完善的放射型动画了.开始日便是触发走及全面的时间.

通下去就是片RadioButton,ToolTip,Path的体制问题了.这有的豪门看心情,做个协调喜欢的样式就好了.

 

2016-08-01更新:

将称注册动画改呢对象注册动画

图片 3图片 4

  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