飞线图实现原理

  1. 绘制背景的地图,geogeo画地图
  2. 绘制散点图,effectScatter在地图上画散点图
  3. 绘制飞线图, series.type: ‘lines’,lines绘制飞线
    1. 需要关闭 animation: false,否则会有上一个飞线的残影痕迹

地图绘制要点

  1. geoJson
  2. geoCoordMap
    1. [开始城市数据,结束城市数据]
    2. convertLinesData 城市 geoCoord转换为飞线图的坐标系数据[

](https://echarts.apache.org/examples/zh/editor.html?c=geo-lines)

销售TOP排行

image.png

切换动画残影

解决: animation: false 关闭动画

  1. 需要单独设置 zlevel
  2. 关闭该层的动画(animation: false
  3. 不然位于同个层的其它系列的图形,和动画的标签也会产生不必要的残影。

timeline切换飞线图,清除上一个飞线的痕迹,即动画残影。
文档 https://echarts.apache.org/zh/option.html#series-lines.effect

options

  1. import * as echarts from 'echarts';
  2. import {chinaJson} from '@/components/ECharts/Map';
  3. import {getData, colors, provinces, convertData, convertLinesData} from './_data';
  4. import {geo, timeline, baseOption} from './config';
  5. const cities = ['北京', '上海', '广州', '郑州', '成都', '海口'];
  6. const mapData = cities.map((it, i) => []);
  7. const cityGeoCoord = [
  8. [116.4551, 40.2539],
  9. [121.4648, 31.2891],
  10. [113.12244, 23.009505],
  11. [113.4668, 34.6234],
  12. [103.9526, 30.7617],
  13. [110.3893, 19.8516],
  14. ];
  15. const series = {
  16. data1: getData(10, 6000),
  17. data2: getData(10, 7000),
  18. data3: getData(10, 8000),
  19. data4: getData(10, 9000),
  20. data5: getData(100, 6000),
  21. data6: getData(100, 3000),
  22. }
  23. function chinaOption() {
  24. echarts.registerMap('china', chinaJson);
  25. // 柱图数据 [[], [], [], [], [], []]
  26. provinces
  27. .filter(it => it.code)
  28. .forEach((item, index) => {
  29. const key = item.name;
  30. mapData.forEach((child, i) => {
  31. const {value} = series[`data${i + 1}`].find(it => it.name === key) || {};
  32. child.push({name: key, value})
  33. child.sort((a, b) => a.value - b.value)
  34. })
  35. });
  36. // 柱图 X轴数据 [[], [], [], [], [], []]
  37. // const xdata = cities.map((it, i) => {
  38. // return mapData[i].map(it => it.name);
  39. // });
  40. // 柱状图数据
  41. const barData = cities.map((it, i) => {
  42. return mapData[i].map(it => it.value);
  43. });
  44. const config = {
  45. timeline: timeline(cities),
  46. baseOption: {
  47. ...baseOption(provinces),
  48. geo,
  49. },
  50. options: [],
  51. }
  52. // options[] 里面的每一项会合并 baseOption
  53. cities.forEach((item, i) => {
  54. const color = colors[3][i];
  55. const rowData = {
  56. title: [
  57. {
  58. text: '区域销售TOP6',
  59. left: 16,
  60. top: 16,
  61. textStyle: {
  62. color: '#fff',
  63. fontSize: 12,
  64. }
  65. },
  66. {
  67. id: 'statistic',
  68. text: `${item}销售额统计情况`,
  69. top: 8,
  70. right: 4,
  71. textStyle: {
  72. color: '#fff',
  73. fontSize: 12
  74. }
  75. }
  76. ],
  77. series: [
  78. // 2 在绘制散点图
  79. {
  80. type: 'effectScatter',
  81. coordinateSystem: 'geo',
  82. data: convertData(mapData[i]),
  83. symbolSize: arr => arr[2],
  84. showEffectOn: 'render',
  85. hoverAnimation: true,
  86. zlevel: 1,
  87. // 涟漪配置
  88. // https://echarts.apache.org/zh/option.html#series-effectScatter.rippleEffect
  89. rippleEffect: {
  90. brushType: 'stroke'
  91. },
  92. label: {
  93. normal: {
  94. formatter: '{b}',
  95. position: 'right',
  96. show: false // 全部显示,太拥挤了,高亮显示文字
  97. },
  98. emphasis: {
  99. show: true
  100. }
  101. },
  102. // 散点图颜色和柱图保持一致
  103. itemStyle: {
  104. normal: {
  105. color,
  106. shadowBlur: 8,
  107. shadowColor: color
  108. }
  109. },
  110. },
  111. // 3 最后绘制飞线图
  112. {
  113. name: `${item}销售TOP6`,
  114. type: 'lines',
  115. data: convertLinesData(mapData[i], cityGeoCoord[i]),
  116. zlevel: 2,
  117. effect: {
  118. show: true, // 带有动画的飞线
  119. period: 4, // 箭头指向速度,值越小速度越快
  120. trailLength: 0.02, // 特效尾迹长度[0,1]值越大,尾迹越长重
  121. symbol: 'arrow', // 箭头图标
  122. symbolSize: 3 // 图标大小
  123. },
  124. lineStyle: {
  125. normal: {
  126. color,
  127. width: 0.1, // 尾迹线条宽度
  128. opacity: 0.5, // 尾迹线条透明度
  129. curveness: 0.3 // 尾迹线条曲直度,线条的弧度,不加这个是直线
  130. }
  131. },
  132. animation: false
  133. },
  134. // 1 先绘制柱状图
  135. {
  136. zlevel: 1.5,
  137. type: 'bar',
  138. data: barData[i],
  139. itemStyle: {
  140. normal: {color}
  141. },
  142. }
  143. ]
  144. }
  145. config.options.push(rowData);
  146. });
  147. return config;
  148. }
  149. export default chinaOption;

convertLinesData

应用场景

  1. 物流的流向
    1. // 飞线图的数据
    2. export function convertLinesData(data, fromGeoCoord) {
    3. return data.map(item => {
    4. const {name, value} = item;
    5. const {geoCoord} = provinces.find(it => it.name === name) || {};
    6. return [
    7. // 起点位置
    8. { coord: fromGeoCoord, value, },
    9. // 终点位置
    10. { coord: geoCoord }
    11. ]
    12. });
    13. }