如何在le5le-topology中封装第三方图形库,如echarts、highcharts等,而不是重复造轮子。可参考源码中:libs/topology-chart-diagram

1. 加载图形库 js,并注册自定义节点

  1. import { registerNode } from 'topology-core/middles';
  2. import { loadJS } from 'topology-core/utils';
  3. import {
  4. echarts
  5. } from './echarts';
  6. export function register() {
  7. // 如果不存在echarts,则先下载
  8. // 否则使用用户已经加载的echarts
  9. if (!(window as any).echarts) {
  10. loadJS('https://cdn.bootcss.com/echarts/4.3.0/echarts.min.js', null, true);
  11. }
  12. // echarts封装图标库函数已经写好的前提下,直接调用registerNode注册函数注册好,使用更简单。
  13. // 参数1 - 定义图形库组件名为: 'echarts'
  14. // 参数2 - 绘画函数为echarts
  15. // 参数3,4,5 - 锚点和文字等计算采用默认计算函数
  16. registerNode('echarts', echarts, null, null, null);
  17. }

2. 实现绘图函数

  1. // 创建一个原生div,用于第三方图形库的装载容器
  2. import { createDiv } from 'topology-core/utils';
  3. // 存放echarts原生dom节点
  4. const echartsData: any = {};
  5. export function echarts(ctx: CanvasRenderingContext2D, node: Node) {
  6. // 绘制一个底图,类似于占位符。
  7. rectangle(ctx, node);
  8. // 如果未加载图形库,直接返回
  9. const echarts = (window as any).echarts;
  10. if (!node.data || !echarts) {
  11. return;
  12. }
  13. // 这里,我们把echarts需要的json数据放在node.data.echarts下面
  14. // 如果node.data为字符串,就序列号为json对象
  15. if (typeof node.data === 'string') {
  16. node.data = JSON.parse(node.data);
  17. }
  18. // 没有echarts数据,直接返回
  19. if (!node.data.echarts) {
  20. return;
  21. }
  22. // echarts第三方图形库是元素dom元素,需要设置一个唯一的id,方便绘画引擎识别
  23. if (!node.elementId) {
  24. node.elementId = s8();
  25. }
  26. // 节点的elementLoaded用于判断第三方图形库是否第一次加载,是否需要初始化
  27. // 这是一个辅助变量,用户自己赋值使用或不用
  28. if (!node.elementLoaded) {
  29. // 创建一个div容器
  30. echartsData[node.id] = {
  31. div: createDiv(node)
  32. };
  33. node.elementLoaded = true;
  34. document.body.appendChild(echartsData[node.id].div);
  35. // 添加当前节点到div层,否则无法显示
  36. node.addToDiv();
  37. // 初始化echarts图形组件
  38. echartsData[node.id].chart = echarts.init(echartsData[node.id].div, node.data.echarts.theme);
  39. node.elementRendered = false;
  40. // 等待父div先渲染完成,然后resize为父容器大小,避免初始图表控件太大
  41. setTimeout(() => {
  42. echartsData[node.id].chart.resize();
  43. });
  44. }
  45. // 节点的elementRendered用于判断第三方图形库是否需要重绘
  46. // 绘画引擎需要重绘节点时,会把此属性设置为false
  47. if (!node.elementRendered) {
  48. // 初始化时,等待父div先渲染完成,避免初始图表控件太大。
  49. setTimeout(() => {
  50. echartsData[node.id].chart.setOption(node.data.echarts.option);
  51. echartsData[node.id].chart.resize();
  52. // 重绘完成,避免不必要的重复重绘
  53. node.elementRendered = true;
  54. });
  55. }
  56. }