User:GuoPC/编辑历史的ECharts折线图实现

大萌字.svg
阅读本用户子页面的任何人都可以参与编辑
Emoji u1f613.svg
本页的内容因笔者能力有限,可能存在部分难以理解的文字,欢迎了解相关内容的编辑者协助改善或在我的讨论页提出改进建议。
📈
本页的部分内容基于Apache ECharts官方文档。

Apache ECharts是一个基于JavaScript的开源可视化图表库。[1]通过它,你可以轻松地在网站上绘制各种图表。

进入正题。令人高兴的是,萌百上已经有了渲染ECharts图表的模板——{{Echart}}。本页面将简单介绍如何使用该模板绘制一个展示用户每月编辑历史的折线图。为了方便后文介绍,先放出成品:

{
   "title": {
       "text": "我的编辑历史",
       "subtext": "按月统计次数",
       "subtextStyle": {
           "color": "#333"
       }
   },
   "tooltip": {
       "trigger": "axis",
       "axisPointer": {
           "type": "cross",
           "animation": false
       }
   },
   "toolbox": {
       "show": true,
       "feature": {
           "dataZoom": {
               "yAxisIndex": "none"
           },
           "dataView": {
               "readOnly": true
           },
           "magicType": {
               "type": [
                   "line",
                   "bar"
               ]
           },
           "restore": {},
           "saveAsImage": {
               "excludeComponents": [
                   "toolbox",
                   "dataZoom"
               ]
           }
       }
   },
   "axisPointer": {
       "link": {
           "xAxisIndex": "all"
       }
   },
   "dataZoom": [
       {
           "type": "inside",
           "xAxisIndex": [
               0
           ],
           "startValue": 0,
           "end": 100
       },
       {
           "show": true,
           "xAxisIndex": [
               0
           ],
           "type": "slider",
           "start": 0,
           "end": 100
       }
   ],
   "legend": {
       "data": [
           "编辑次数"
       ]
   },
   "xAxis": {
       "data": [
           "2021年3月",
           "2021年4月",
           "2021年5月"
       ]
   },
   "yAxis": {},
   "series": [
       {
           "name": "编辑次数",
           "type": "line",
           "label": {
               "formatter": "{c}",
               "distance": 0,
               "backgroundColor": "transparent",
               "padding": 1
           },
           "data": [
               {
                   "value": 572,
                   "label": {
                       "show": false
                   }
               },
               {
                   "value": 312,
                   "label": {
                       "show": true,
                       "position": "bottom"
                   }
               },
               {
                   "value": 290,
                   "label": {
                       "show": false
                   }
               }
           ],
           "markPoint": {
               "data": [
                   {
                       "type": "max",
                       "name": "最大值"
                   },
                   {
                       "type": "min",
                       "name": "最小值"
                   }
               ],
               "silent": true
           },
           "markLine": {
               "data": [
                   {
                       "type": "average",
                       "name": "平均值"
                   }
               ],
               "silent": true
           }
       }
   ],
   "animation": false
}
图表数据页面:User:GuoPC/ECExample1

下面针对该实例进行介绍。

数据页面的建立

为了实现类似于上面的效果,我们需要一个用于模板接受数据的页面(以下简称“数据页面”),页面内容模型必须为JSON

实际上,在使用ECharts绘制图表之前需要在服务器端进行一定的配置,但这些都已经预先准备好了。我们可以自定义的部分是一个被称为setOption的函数。该函数用于设置图表实例的配置项以及数据,所有参数和数据的修改都可以通过其完成。[2]

可以认为模板已定义好的内容大致为:

  1. <div class="echart-app">
  2. <div class="echart-data">
  3. <!-- 此处为从数据页面接受的数据 -->
  4. </div>
  5. <div class="echart-main">
  6. <div>
  7. <canvas></canvas>
  8. </div>
  9. </div>
  10. </div>

其中echart-data对应<div>中的内容即为数据页面中的内容,也就是我们需要重点编写的。

创建页面

与创建一般的用户子页面相同,您可以通过在搜索框输入User:您的用户名/数据页面名称创建,也可在下方输入框中输入您想要的数据页面名称后点击右侧按钮创建(这里数据页面名称默认取contributions):

准备数据

目前普遍采用手动统计的方式。即转到您的贡献页面,选定好起止日期进行统计。当然,当数目较大时,可以通过复制当月的贡献记录,然后粘贴到可以显示行数的文本编辑器(例如开启状态栏的Windows Notepad,whatever)以减少工作量。

页面编写

建议您使用诸如Visual Studio Code的代码编辑器新建JSON文件进行编写后再粘贴到您刚创建好的页面。

数据的框架可能看起来长成这样:

  1. {
  2. "title": {...},
  3. "tooltip": {...},
  4. "toolbox": {...},
  5. "axisPointer": {...},
  6. "dataZoom": [{...}],
  7. "legend": {...},
  8. "xAxis": {...},
  9. "yAxis": {...},
  10. "series": [{...}],
  11. "animation": false
  12. }

最外侧花括号中的键实际上是setOption函数支持的所有键。[3][4]下面仅根据上面的实例对这些键做具体介绍。

太多不看版

如果您只关注如何将每月的编辑数转化为折线图,那么只要了解xAxisseries的一部分即可。其余部分可参照官方文档[4]或其他已经写好的用户处[5]查看。

xAxis
xAxis
xAxis即为x轴,您可以通过在其中添加data: []来指定x轴的数据。例如:
  1. "xAxis": {
  2. "data": [
  3. "2021年3月",
  4. "2021年4月",
  5. "2021年5月"
  6. ]
  7. }
这段代码指定了x轴的数据为“2021年3月”“2021年4月”“2021年5月”,实际图表中x轴就会有这三个值。
series
series
series指定图表系列,大致结构为:
  1. "series": [
  2. {
  3. ...,
  4. "data": [{"value": ..., "label": {...}}],
  5. "markPoint": {
  6. "data": [
  7. {
  8. "type": "max",
  9. "name": "最大值"
  10. },
  11. {
  12. "type": "min",
  13. "name": "最小值"
  14. }
  15. ]
  16. },
  17. "markLine": {
  18. "data": [
  19. {
  20. "type": "average",
  21. "name": "平均值"
  22. }
  23. ]
  24. }
  25. }
  26. ]
data中指定:
  1. 单个数据项的数值(value),您可以在这里填入当月编辑数;
  2. 标签(label)是否显示(show),"show": true则显示、"show": false则不显示;
  3. 标签位置(position),需要"show": true"position": "bottom"则显示在点的下方,"position": "top"则显示在点的上方。
markPoint用于标注特殊点,上面的代码中标注出了最大值点和最小值点;
markLine用于标注特殊线,上面的代码中标注出了平均值线。
示例
假设2021年3月编辑数为572,4月为312,5月为290,综合前面xAxis的代码,则可写出:
  1. "series": [
  2. {
  3. ...,
  4. "data": [
  5. {
  6. "value": 572,
  7. "label": {
  8. "show": false
  9. }
  10. },
  11. {
  12. "value": 312,
  13. "label": {
  14. "show": true,
  15. "position": "bottom"
  16. }
  17. },
  18. {
  19. "value": 290,
  20. "label": {
  21. "show": false
  22. }
  23. }
  24. ],
  25. "markPoint": {
  26. "data": [
  27. {
  28. "type": "max",
  29. "name": "最大值"
  30. },
  31. {
  32. "type": "min",
  33. "name": "最小值"
  34. }
  35. ]
  36. },
  37. "markLine": {
  38. "data": [
  39. {
  40. "type": "average",
  41. "name": "平均值"
  42. }
  43. ]
  44. }
  45. }
  46. ]
说明:
因为在markPoint中标出了最大值和最小值点,于是将最大值572和最小值290对应点设置"show": false[6]

完整版

此章节介绍示例中涉及到的所有键。[4]

title
title
title为标题组件,包含主标题和副标题。例如:
  1. "title": {
  2. "text": "我的编辑历史",
  3. "subtext": "按月统计次数",
  4. "subtextStyle": {
  5. "color": "#333"
  6. }
  7. }
这段代码指定了:
  1. 主标题(text)为“我的编辑历史”;
  2. 副标题(subtext)为“按月统计次数”;
  3. 副标题样式(subtextStyle)为对象,其中有一个键值对:文本颜色为#333。
tooltip
tooltip
tooltip为提示框组件。例如:
  1. "tooltip": {
  2. "trigger": "axis",
  3. "axisPointer": {
  4. "type": "cross",
  5. "animation": false
  6. }
  7. }
这段代码指定了:
  1. 触发类型(trigger)为坐标轴触发(axis),主要在柱状图、折线图等会使用类目轴的图表中使用;
  2. 坐标轴指示器(axisPointer)对象,其中有两个键值对:指示器类型为十字准星指示器、不开启动画。
toolbox
toolbox
toolbox为工具栏。例如:
  1. "toolbox": {
  2. "show": true,
  3. "feature": {
  4. "dataZoom": {
  5. "yAxisIndex": "none"
  6. },
  7. "dataView": {
  8. "readOnly": true
  9. },
  10. "magicType": {
  11. "type": ["line", "bar"]
  12. },
  13. "restore": {},
  14. "saveAsImage": {
  15. "excludeComponents": ["toolbox", "dataZoom"]
  16. }
  17. }
  18. }
这段代码指定了:
  1. 显示工具栏组件(show);
  2. 各工具配置项(feature)对象,其中有五个键值对:
    1. 数据区域缩放(dataZoom)对象,其中有一个键值对:y轴索引为空,即不控制任何y轴;
    2. 数据视图(dataView)对象,其中有一个键值对:只读,即不可编辑;
    3. 动态类型(magicType)对象,其中有一个键值对:启用的动态类型为折线图和柱状图;
    4. 配置项还原(restore)为空;
    5. 保存为图片(saveAsImage)对象,其中有一个键值对:忽略的组件列表为工具栏(toolbox)和数据区域缩放组件(dataZoom)。
axisPointer
axisPointer
axisPointer为坐标轴指示器。例如:
  1. "axisPointer": {
  2. "link": {
  3. "xAxisIndex": "all"
  4. }
  5. }
这段代码指定了:
  1. 联动(link)对象,其中有一个键值对:所有的x轴进行联动。
dataZoom
dataZoom
dataZoom为数据区域缩放组件。例如:
  1. "dataZoom": [
  2. {
  3. "type": "inside",
  4. "xAxisIndex": [0],
  5. "startValue": 0,
  6. "end": 100
  7. },
  8. {
  9. "show": true,
  10. "xAxisIndex": [0],
  11. "type": "slider",
  12. "start": 0,
  13. "end": 100
  14. }
  15. ]
这段代码指定了两个对象。其中第一个对象指定了:
  1. 数据区域缩放组件类型(type)为内置型(inside),即可以通过鼠标拖拽和滚轮滚动来缩放坐标系;
  2. 控制的x轴(xAxisIndex)为第一个x轴;
  3. 数据区域的起始值(startValue)为0;
  4. 数据区域的结束百分比(end)为100%。
第二个对象指定了:
  1. 数据区域缩放组件类型(type)为滑动条型(slider),即展示数据缩略图;
  2. 显示该滑动条组件(show);
  3. 控制的x轴(xAxisIndex)为第一个x轴;
  4. 数据区域的起始百分比(start)为0%;
  5. 数据区域的结束百分比(end)为100%。
legend
legend
legend为图例组件。例如:
  1. "legend": {
  2. "data": [
  3. "编辑次数"
  4. ]
  5. }
这段代码指定了:
  1. 图例的数据数组(data)为一个字符串“编辑次数”。其与series中的图表名称(name)对应。
xAxis
xAxis
xAxis为直角坐标系的x轴。例如:
  1. "xAxis": {
  2. "data": [
  3. "2021年3月",
  4. "2021年4月",
  5. "2021年5月"
  6. ]
  7. }
这段代码指定了:
  1. x轴的数据数组(data)为三个字符串。
yAxis
yAxis
yAxis为直角坐标系的y轴。
series
series
series指定图表系列。例如:
  1. "series": [
  2. {
  3. "name": "编辑次数",
  4. "type": "line",
  5. "label": {
  6. "formatter": "{c}",
  7. "distance": 0,
  8. "backgroundColor": "transparent",
  9. "padding": 1
  10. },
  11. "data": [
  12. {
  13. "value": 572,
  14. "label": {
  15. "show": false
  16. }
  17. },
  18. {
  19. "value": 312,
  20. "label": {
  21. "show": true,
  22. "position": "bottom"
  23. }
  24. },
  25. {
  26. "value": 290,
  27. "label": {
  28. "show": false
  29. }
  30. }
  31. ],
  32. "markPoint": {
  33. "data": [
  34. {
  35. "type": "max",
  36. "name": "最大值"
  37. },
  38. {
  39. "type": "min",
  40. "name": "最小值"
  41. }
  42. ]
  43. },
  44. "markLine": {
  45. "data": [
  46. {
  47. "type": "average",
  48. "name": "平均值"
  49. }
  50. ]
  51. }
  52. }
  53. ]
这段代码指定了:
  1. 图表类型(type)为折线图(line);
  2. 图表名称(name)为“每月编辑数”,在提示框(tooltip)中显示。其与legend中的数据数组(data)对应;
  3. 图表文本标签(label)对象,其中有四个键值对:标签内容格式为数据值、与图形元素的距离为0、文字块背景色为透明、文字块的内边距为1;
  4. 数据内容数组(data)中包含三个对象,指定了单个数据项的数值(value),标签(label)是否显示(show)以及位置(position);
  5. 图表标注(markPoint)对象,包含一个数据数组(data),指定了标注出最大值点和最小值点;
  6. 图表标线(markLine)对象,包含一个数据数组(data),指定了标注出平均值线。
animation
animation
animation指定是否开启动画。

其他说明

  • 若希望不显示除最大、最小值之外其他数据的值,可考虑指定xAxistype"category",此时data中只需以列表形式(如[2, 3, 5, 7, 11, 13])提供对应数据即可。修改方式可参考此条差异[7]
  • 若希望不显示图表右上角的工具栏,将toolbox及其下属内容全部删除即可。此外,若希望调整工具栏中的功能,可参考官方文档。[8]

更改页面内容类型

将编写完成的页面保存后需要将该页面的类型更改为JSON,电脑版视图下的具体操作步骤为:

  1. Vector皮肤下在页面左栏找到“工具”,点击“页面信息”;MoeSkin皮肤下在底端工具栏点击“页面信息”;
  2. 找到“基本信息”表格中的“页面内容类型”,点击右侧的“更改”;
  3. 在“新的内容模型”下拉列表中选择“JSON”,之后点击“更改”。

至此,该页面的内容类型就变成了JSON,可以通过{{Echart}}调用了。

{{Echart}}模板的使用参见模板文档,在此不再赘述。

页面开头的图表即使用{{Echart|datapage=User:GuoPC/ECExample1|height=300}}进行渲染。

数据更新

作为“每月编辑历史折线图”,需要至少每月更新一次[来源请求],如何在已有数据页面的基础上增添数据呢?需要修改的还是xAxisseries两部分。假定2021年6月的编辑数为400。

xAxis
xAxis
修改前
  1. "xAxis": {
  2. "data": [
  3. "2021年3月",
  4. "2021年4月",
  5. "2021年5月"
  6. ]
  7. }
修改后(第6行之后,注意第5行最后需加一个,
  1. "xAxis": {
  2. "data": [
  3. "2021年3月",
  4. "2021年4月",
  5. "2021年5月",
  6. "2021年6月"
  7. ]
  8. }
series
series
修改前
  1. "series": [
  2. {
  3. ...,
  4. "data": [
  5. {
  6. "value": 572,
  7. "label": {
  8. "show": false
  9. }
  10. },
  11. {
  12. "value": 312,
  13. "label": {
  14. "show": true,
  15. "position": "bottom"
  16. }
  17. },
  18. {
  19. "value": 290,
  20. "label": {
  21. "show": false
  22. }
  23. }
  24. ],
  25. "markPoint": {
  26. "data": [
  27. {
  28. "type": "max",
  29. "name": "最大值"
  30. },
  31. {
  32. "type": "min",
  33. "name": "最小值"
  34. }
  35. ]
  36. },
  37. "markLine": {
  38. "data": [
  39. {
  40. "type": "average",
  41. "name": "平均值"
  42. }
  43. ]
  44. }
  45. }
  46. ]
修改后(第24行之后,注意第23行最后需加一个,
  1. "series": [
  2. {
  3. ...,
  4. "data": [
  5. {
  6. "value": 572,
  7. "label": {
  8. "show": false
  9. }
  10. },
  11. {
  12. "value": 312,
  13. "label": {
  14. "show": true,
  15. "position": "bottom"
  16. }
  17. },
  18. {
  19. "value": 290,
  20. "label": {
  21. "show": false
  22. }
  23. },
  24. {
  25. "value": 400,
  26. "label": {
  27. "show": true,
  28. "position": "bottom"
  29. }
  30. }
  31. ],
  32. "markPoint": {
  33. "data": [
  34. {
  35. "type": "max",
  36. "name": "最大值"
  37. },
  38. {
  39. "type": "min",
  40. "name": "最小值"
  41. }
  42. ]
  43. },
  44. "markLine": {
  45. "data": [
  46. {
  47. "type": "average",
  48. "name": "平均值"
  49. }
  50. ]
  51. }
  52. }
  53. ]

更新之后的图表如下:

{
   "title": {
       "text": "我的编辑历史",
       "subtext": "按月统计次数",
       "subtextStyle": {
           "color": "#333"
       }
   },
   "tooltip": {
       "trigger": "axis",
       "axisPointer": {
           "type": "cross",
           "animation": false
       }
   },
   "toolbox": {
       "show": true,
       "feature": {
           "dataZoom": {
               "yAxisIndex": "none"
           },
           "dataView": {
               "readOnly": true
           },
           "magicType": {
               "type": [
                   "line",
                   "bar"
               ]
           },
           "restore": {},
           "saveAsImage": {
               "excludeComponents": [
                   "toolbox",
                   "dataZoom"
               ]
           }
       }
   },
   "axisPointer": {
       "link": {
           "xAxisIndex": "all"
       }
   },
   "dataZoom": [
       {
           "type": "inside",
           "xAxisIndex": [
               0
           ],
           "startValue": 0,
           "end": 100
       },
       {
           "show": true,
           "xAxisIndex": [
               0
           ],
           "type": "slider",
           "start": 0,
           "end": 100
       }
   ],
   "legend": {
       "data": [
           "编辑次数"
       ]
   },
   "xAxis": {
       "data": [
           "2021年3月",
           "2021年4月",
           "2021年5月",
           "2021年6月"
       ]
   },
   "yAxis": {},
   "series": [
       {
           "name": "编辑次数",
           "type": "line",
           "label": {
               "formatter": "{c}",
               "distance": 0,
               "backgroundColor": "transparent",
               "padding": 1
           },
           "data": [
               {
                   "value": 572,
                   "label": {
                       "show": false
                   }
               },
               {
                   "value": 312,
                   "label": {
                       "show": true,
                       "position": "bottom"
                   }
               },
               {
                   "value": 290,
                   "label": {
                       "show": false
                   }
               },
               {
                   "value": 400,
                   "label": {
                       "show": true
                   }
               }
           ],
           "markPoint": {
               "data": [
                   {
                       "type": "max",
                       "name": "最大值"
                   },
                   {
                       "type": "min",
                       "name": "最小值"
                   }
               ],
               "silent": true
           },
           "markLine": {
               "data": [
                   {
                       "type": "average",
                       "name": "平均值"
                   }
               ],
               "silent": true
           }
       }
   ],
   "animation": false
}
图表数据页面:User:GuoPC/ECExample2

根据实际编辑数的不同,如果更新数据后最大或最小值有变,只要对labelshowposition的值进行修改即可。

注释

  1. Apache ECharts
  2. API: echartsInstance.setOption - Documentation - Apache ECharts
  3. key: value的形式称为键值对,其中key为键、value为值,键值对之间用,隔开。更多JSON相关内容在此不再赘述
  4. 4.0 4.1 4.2 setOption函数支持的所有键参见配置项 - Documentation - Apache ECharts
  5. 此处提供用户名字空间下“contributions”的搜索结果以供参考:“contributions”的搜索结果 - 萌娘百科
  6. 实际上因为图表本身可以沿x轴缩放,且缩放后会根据当前缩放级别下显示的数据重新寻找最大值与最小值并进行标记,所以此处只能保证在默认缩放级别下的美观性。另可参考#其他说明中将修改横轴为类目(category)类型的相关内容。
  7. 配置项: xAxis.data - Documentation - Apache ECharts
  8. 配置项: toolbox.feature - Documentation - Apache ECharts
返回顶部