【echarts】用地图模块做动态流程图2.0(根据后台数据自动均匀排布,且实时更新节点状态)

1.效果

0

2.说明

  • 这个升级版几乎就是我们公司用的这个功能了,设计到的功能就是可以根据后台数据重新进行位置排布,且实时刷新节点的数据。用ec写出这个效果不难,参考demo1
  • 这个主要是设计到如何根据数据进行重新排布,实时刷数据,这些都是ec插件没有的,需要我们去苦逼手写的。

3.代码:

3.1要知道的:

  • 其实在敲代码前,就应该意识到和后台要的数据是什么样的,要知道我们是用地图模块实现的,所以节点的定位就要设计到坐标,而这个坐标是后台不会给我们的,他只会给我们这些个节点的基本信息,状态,来自哪个节点,要去哪个节点。换句话说,就是这个节点的定位是需要我们算的。
  • OK,既然是我们算,就要知道,我们算的这个地图的模块的边界大小和起始点。这里我用的世界地图,没有用中国地图,是有原因的。这就是说到我们的边界和起始点。世界地图的边界和起始点比较好设置和计算,都是整数,而中国地图首先得合理的把中国地图放大,找到起始点坐标和边界大小,虽然说后面的计算方法和世界地图的计算是一样的,但是找起始点就恶心的很,所以强烈建议用世界地图。
  • 世界地图的起始点和边界:

aa

  • 数据也不难找 中心点坐标是[0,0],宽度是东经到西经360,高度不是北纬到南纬180,是北纬80度到南纬50度的样子,这个也没有具体是怎么样的数值,原因就是地图会向上偏移点,北纬80度到南纬50度的范围更合适点。所以可以得出: 
me.conf = {
   // 起始点
   start: [-180, 80],
   w: 360,
   h: 130,

   padding: 5,

   // 列宽
   _lie_w: 0,
}

3.2主要过程:

  • 主要流程:1.确定了起始点和边界范围  2.根据数据确定每列数据的宽度;3.初始化节点数据,4.初始化航线数据,5.注入数据 6.设置实时更新 
        _init: function() {
          // 起始点确定
          me._flow_start_p();

          // 确认列宽
          me._flow_lie_w();

          // 
          me._flow();
        },
        _flow: function() {


          // **************************************模拟数据
          for (var lie_key in all_data) {
            all_data[lie_key].forEach(function(ele, index) {
              ele.id = `${lie_key}_${index+1}`;
              ele.name = `lie_${lie_key}_${index+1}`;
              ele.status = (Math.random() > 0.5 ? 0 : 1);
            });
          }
          // **********************************************

          

          // 初始化节点
          me._flow_node();

          // **************************************模拟数据
          for (var lie_key in all_data) {
            all_data[lie_key].forEach(function(ele, index) {
              // console.log();
              ele.to = me._flow_lines_to_test(ele.id);
            });
          }
          // **********************************************

          // 初始化线
          me._flow_lines();

          // 生成数据
          me._flow_init();


          //  
          setTimeout(function() {
            // **************************************模拟数据
            // for (var lie_key in all_data) {
            //   all_data[lie_key].forEach(function(ele, index) {
            //     // console.log();
            //     ele.to = me._flow_lines_to_test(ele.id);
            //   });
            // }
            // **********************************************
            // me.all_obj.ec.clear();

            me.all_obj.pt_p_arr.length = 0;
            me.all_obj.alarm_p_arr.length = 0;

            me.all_obj.pt_lines_arr.length = 0;
            me.all_obj.alarm_lines_arr.length = 0;
            me._flow();
          }, 5000)
        },
  • 认识下数据格式,要知道后台是不给我们坐标的,所以猜下大概的数据格式应该是:id是节点的坐标,statu节点的状态,to就是表示我们这个节点要去哪个节点的坐标。这些都是我作为前端想到的。到时候有其他字段再加就行了。
var all_data = {
  1: [
    // 
    {
      id: 1,
      status: 0,
      name: 'lie-1-1',
      to:'2_1',
    },
    // 
    {
      id: 1,
      status: 1,
      name: 'lie-1-2',
      to:'2_1',
    },
    // 
    {
      id: 1,
      status: 1,
      name: 'lie-1-3',
      to:'2_2',
    },
  ],
  2:...
}
  • 这里是5列数据,所以走第一步,先确定列的宽度:(在配置起始坐标和边界时,我同时设置了一个padding值,就是以防我们经理说撑的太满了要往里面收下的这个low的要求。)
       // 宽度确定
        _flow_lie_w: function() {
          // 数据处理
          var index = 0;
          for (var lie in all_data) {
            index++;
          }
          // 初始化列宽
          me.conf._lie_w = Math.floor(me.conf.w / index);
        },
  •  然后就是初始化每一列数据:核心就是要确定每一列第一个节点的经纬度,知道如歌通过遍历得到同列下面节点的经纬度,这里要注意的是:1.在最后要收集每个节点的ID和坐标的对应关系,因为我们在初始化巡航线的时候要用到这些点的坐标。2.根据不同的状态收集不同的数据,这里主要是有普通点就是没有动态效果,报警点有报警效果的区别,我也是担心经理有这个要求,没等他说我就直接这样写了,如果是报警直接节点颜色变了,没有动画效果,就没必要通过两个数组进行收集数据了,因为看ec的API颜色也是可以用个回调函数进行颜色的设置。
        // 初始化节点
        _flow_node: function() {
          for (var lie in all_data) {
            me._flow_node_init(all_data[lie], lie);
          }
        },
        _flow_node_init: function(arr, lie) {
          // console.log(arr, lie);
          var lie_index = null;
          switch (lie) {
            case "1":
              lie_index = 1;
              break;
            case "2":
              lie_index = 2;
              break;
            case "3":
              lie_index = 3;
              break;
            case "4":
              lie_index = 4;
              break;
            case "5":
              lie_index = 5;
              break;
          }
          // 每一列的项目高
          var _item_h = Math.floor(me.conf.h / arr.length);


          // 每列起始经度
          var lng = me.conf.start[0] + (lie_index - 0.5) * me.conf._lie_w;
          // 纬度
          var lat = 0;

          // 
          arr.forEach(function(ele, index) {
            lat = me.conf.start[1] - (index + 1 - 0.5) * _item_h;

            // PT
            if (ele.status) {
              // 普通点收集
              me.all_obj.pt_p_arr.push({
                id: ele.id,
                name: ele.name,
                value: [lng, lat]
              });
            }
            // 报警点收集
            else {
              me.all_obj.alarm_p_arr.push({
                id: ele.id,
                name: ele.name,
                value: [lng, lat]
              });
            }

            // 生成字典
            me.all_obj.p_obj[ele.id] = [lng, lat];
          });
        },
  • 初始化巡航线:就是更加节点数据里的to字段。知道我们要去哪个节点的ID,根据前面收集的ID的坐标的对应关系,拿到要去的节点的坐标。
        // 初始化线
        _flow_lines: function() {
          for (var lie in all_data) {
            all_data[lie].forEach(function(ele, index) {
              if (ele.to) {
                // PT
                if (ele.status) {
                  me.all_obj.pt_lines_arr.push({
                    "coords": [
                      me.all_obj.p_obj[ele.id],
                      me.all_obj.p_obj[ele.to],
                    ]
                  });
                }
                // 报警
                else {
                  me.all_obj.alarm_lines_arr.push({
                    "coords": [
                      me.all_obj.p_obj[ele.id],
                      me.all_obj.p_obj[ele.to],
                    ]
                  });
                }

              }



            });
          }
        },
  • 说下我和后台要的数据格式 ,注意这里写的我和后台要,意思就是后台给我的数据格式是我前端定的,我和他约定要什么格式,他就得按照这个格式来。不然没法配合。对吧?
  • 最后就是设置定时刷了,核心就是递归加定时器,保证数据在上一次没有请求完成不会发出下次请求,唉,我们的老业务场景了。
  • 源码:点star,不迷路

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要使用 HTML 节点作为 echarts 地图的纹理,可以使用 echarts 中的 image 和 SVG 标签。但是,因为 HTML 节点的加载速度较慢,可能会导致每次进入页面都无法正确显示。 为了解决这个问题,可以使用 echarts 的 loading 动画来占位,等到 HTML 节点加载完成后再显示地图。下面是一个简单的例子: ```javascript option = { tooltip: {}, series: [{ type: 'map', map: 'china', label: { show: true }, itemStyle: { normal: { borderColor: '#fff', borderWidth: 1, shadowColor: 'rgba(0, 0, 0, 0.5)', shadowBlur: 10 }, emphasis: { areaColor: '#f00' } }, data: [{ name: '北京', value: 100 }, { name: '上海', value: 50 }, { name: '广州', value: 80 }, { name: '深圳', value: 60 }, { name: '重庆', value: 70 }], z: 1 }, { type: 'image', z: 0, bounding: 'raw', origin: [75, 10], style: { image: 'https://www.echartsjs.com/examples/data/thumb-map.png' } }] }; // 使用 loading 动画占位 myChart.showLoading(); // 监听 image 标签的 load 事件,加载完成后隐藏 loading 动画 var img = new Image(); img.onload = function() { myChart.hideLoading(); }; img.src = 'https://www.echartsjs.com/examples/data/thumb-map.png'; ``` 在上面的例子中,使用了一个 image 标签来作为地图的纹理,同时使用了 loading 动画占位。在代码的最后,监听 image 标签的 load 事件,等到加载完成后再隐藏 loading 动画。 你也可以根据自己的需求调整 loading 动画的样式和位置,比如设置文字提示、加载图标等。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值