【Openlayers】V5.0.2 单点追踪、实时监控、历史轨迹、地图绘制全代码实例

1.说明:

  • 该实例是可以用到地图的常用功能,对付一般和类似的业务场景都绰绰有余,在图层的选择上还是建议选择天地图的在线地地图,选择4326--84坐标系,地图上没有偏差。
  • 所有的功能都在一个demo下展示了,就涉及到功能的切换时定时器的关闭和开启,一般情况下,这些功能都是在单独的页面的,所有demo中的定时器的关闭和开启,有需要的朋友可以看看。
  • 下面的效果只是部分gif展示,因为上传不了很大GIF动图。

2.效果展示:

2.1单点追踪:

【Openlayers】V5.0.2 单点追踪、实时监控、历史轨迹、地图绘制全代码实例_第1张图片

2.2实时监控:

【Openlayers】V5.0.2 单点追踪、实时监控、历史轨迹、地图绘制全代码实例_第2张图片

2.3历史轨迹:

【Openlayers】V5.0.2 单点追踪、实时监控、历史轨迹、地图绘制全代码实例_第3张图片

2.4地图绘制:

3.代码:

3.1要知道:

  • 以前一直没有用过ol,一直觉得ol是个很神奇的东西,以前全部的业务逻辑都是用高德,百度,谷歌。这次借着公司的前端di地图改变,学习了下ol,其实ol没有那么难。
  • 用高德或者百度的说法:我们最常用的功能就是往地图上打一个marker,OK!在OL这里全部都是有层的概念,数据容器的概念。名字是我自己起的就是便于理解。加上合理的代码抒写方式,便于我们管理很多层的数据,无论是怎么样的业务需求。
  • 因为OL用的是大量的面向对象的写法,很多地方需要大量的对象实例化,因为我们要本着有些实例可以共用,就实例化一次的原则写代码,这样内存的压力会少很多。我的个人推荐写法就是提前把共用的实例配置到全局,用的时候,调用下实例就可以。

3.2 追踪模式:

  • 全局设置一个追踪的对象体
    me.all_obj = {

      // =======================追踪
      monitor: {
        // 
        layer: null,
        // 数据层
        data_c: null,
        // marker
        p_data: null,

        // 定时器标识
        timer: null,
        // 刷新标识
        key: true,
      },

    };
  • 选择nav项的单点追踪,走下面的函数,具体可以看代码。
  • 初始化函数  1:设置下进入该功能的一些参数设置;2:构建下层对象和数据容器对象。(我自己的习惯) 
        _monitor: function() {
          // 初始化参数
          me._monitor_set();
          // 层构建
          me._monitor_layer();
          // 打点
          me._monitor_p();



          // 开始移动
          me._monitor_init();
        },
        // 层数据
        _monitor_layer: function() {

          // 层
          me.all_obj.monitor.layer = new ol.layer.Vector();

          // 数据容器
          me.all_obj.monitor.data_c = new ol.source.Vector();

          // 注入层
          me.all_obj.monitor.layer.setSource(me.all_obj.monitor.data_c);

          // 打到地图上
          me.map.addLayer(me.all_obj.monitor.layer);
        },
  • 3:进行数据打点渲染,看下面的代码是全部过程。在前端模拟数据的时候,把模拟的走过的路线数据注入我们设置的数据层,就渲染到地图上了。

        // 层数据
        _monitor_layer: function() {

          // 层
          me.all_obj.monitor.layer = new ol.layer.Vector();

          // 数据容器
          me.all_obj.monitor.data_c = new ol.source.Vector();

          // 注入层
          me.all_obj.monitor.layer.setSource(me.all_obj.monitor.data_c);

          // 打到地图上
          me.map.addLayer(me.all_obj.monitor.layer);
        },
        // 点
        _monitor_p: function() {
          // console.log(mk_data_c);
          // 创建一个活动图标需要的Feature,并设置位置
          var p_data = new ol.Feature({
            // 就一个参数啊,定义坐标
            geometry: new ol.geom.Point(me.conf.monitor.p)
          });

          p_data.setStyle(new ol.style.Style({
            // 设置一个标识
            image: new ol.style.Icon({
              src: './img/user.png',

              // 这个是相当于是进行切图了
              // size: [50,50],

              // 注意这个,竟然是比例 左上[0,0]  左下[0,1]  右下[1,1]
              anchor: [0.5, 0.5],
              // 这个直接就可以控制大小了
              scale: 0.5
            }),

            text: new ol.style.Text({
              // 对其方式
              textAlign: 'center',
              // 基准线
              textBaseline: 'middle',
              offsetY: -30,
              // 文字样式
              font: 'normal 16px 黑体',
              // 文本内容
              text: "name:admin",
              // 文本填充样式
              fill: new ol.style.Fill({
                color: 'rgba(255,255,255,1)'
              }),
              padding: [5, 5, 5, 5],
              backgroundFill: new ol.style.Fill({
                color: 'rgba(0,0,255,0.6)'
              }),
            })
          }));

          // 数据层收集marker
          me.all_obj.monitor.data_c.addFeature(p_data);

          // 最优一次
          // 最优一次
          me._map_fit(me.all_obj.monitor.data_c);

          // 拿到全局
          me.all_obj.monitor.p_data = p_data;
        },
        // 开始追踪
        _monitor_init: function() {
          // 追踪
          var old_p = null;
          var new_p = [0, 0];


          me.all_obj.monitor.timer = setTimeout(function() {
            // 得到旧的点
            old_p = me.all_obj.monitor.p_data.getGeometry().flatCoordinates;


            // ***********************************模拟数据
            if (Math.random() > 0.5) {
              new_p[0] = old_p[0] + Math.random() * me.conf.monitor.set_num;
            } else {
              new_p[0] = old_p[0] - Math.random() * me.conf.monitor.set_num;
            }


            if (Math.random() > 0.5) {
              new_p[1] = old_p[1] + Math.random() * me.conf.monitor.set_num;
            } else {
              new_p[1] = old_p[1] - Math.random() * me.conf.monitor.set_num;
            }
            // *******************************************



            if (me.all_obj.monitor.key) {
              // 移动点--改变这个数据就行了
              me.all_obj.monitor.p_data.setGeometry(new ol.geom.Point(new_p));

              // 线的数据
              me._monitor_init_line(new_p, old_p);

              // 
              me._monitor_init();

              console.log('monitor');
            }
          }, me.conf.monitor.time);
        },
  • 注意这里在渲染走过的路线的数据的样式,就是我前面说到的全局配置好的样式。me.conf.monitor.line_style
        // 初始化线
        _monitor_init_line: function(new_p, old_p) {

          var line_data = new ol.Feature({
            geometry: new ol.geom.LineString([old_p, new_p])
          });
          line_data.setStyle(me.conf.monitor.line_style);

          // 注入容器
          me.all_obj.monitor.data_c.addFeature(line_data);
        },
  • 追踪功能的全局配置项:线的样式,我是提前配置的。
    me.conf = {
      // 追踪模式
      monitor: {
        // 起点坐标
        p: [116.06, 39.67],
        // 波动系数
        set_num: 0.05,
        // 线的样式
        line_style: new ol.style.Style({
          stroke: new ol.style.Stroke({
            width: 3,
            color: [255, 0, 0, 1],
            lineDash: [10, 10],
          })
        }),
        // 刷新时间
        time: 1000,
      },

    };

3.3 实时监控:

  • 实时监控和单点追踪这个业务场景大同小异。适用于实时ji监控某些点的状态(例如:报警状态,实时位置,实时推送的信息)。该demo的实时监控就是监控了一些点的报警状态,我这里简单的做了两个状态,红色为报警,绿色为正常。
  • 这里没有优化的地方,也是我目前想不出怎么优化的地方就是,因为每个点的名字都不一样,所以我每个点只能实例化一个样式对象,然后分别注入到数据中。在下次数据过来时,可以找每个点的对象的样式对象,修改点的状态的图片。
  • 该次demo没有尝试上面的优化方法,有已经尝试的同学可以留言讨论。这里我用的OL v5.0的版本,比3.0的版本在样式上存在很多优化,还是建议同学们用最新的API和版本。
  • 代码实现的风格都是统一的:(前面设置可以配置的参数和监控的对象体,全部监控的函数内部仍然是:初始化参数,构建层和数据容器,开启数据渲染)
        // 实时监控所有
        _all_monitor: function() {

          // 参数设置
          me._all_monitor_set();

          // 设置层
          me._all_monitor_layer();

          // 初始化
          me._all_monitor_init(ps_arr);

          // 最优一次
          me._map_fit(me.all_obj.all_monitor.data_c);
        },

3.4 历史轨迹:

  • OL是没有高德和百度那么丰富的API的,所以历史轨迹的还的自己实现。历史轨迹业务的实现思想就是 定时器加递归,在每次到达下一个点的时候,等待一秒移动到下一个点。移动到终点的时候,可以做个友好提示:
        // 开始运动
        _history_start: function(index) {
          // 开始运动

          setTimeout(function() {
            index++;
            if (index == lines_arr.length) {
              // 运动完毕
              me.conf.history.move_key = false;
              layer.msg('运动完毕');
              $('#his_s').show();
              return;
            }
            // 
            else {

              console.log('moving---')
              me.all_obj.history.p_data.setGeometry(new ol.geom.Point(lines_arr[index]));
              me._history_start(index);
            }
          }, me.conf.history.time);
        },
  • 历史轨迹就比较简单了,点的样式和线的样式因为只有一次渲染,可以配置到全局,也可以在用的时候实例化,个人建议把这些UI性的东西配置到全局,以防你的产品经理~~~嘿嘿嘿~~

3.5 地图绘制:

  • 地图绘制其实API不难,难是业务的屡清楚。
  • 下面是我自己屡的一些功能节点,不合理的地方请留言。
  • 进入地图绘制功能后,先和后台请求数据,把原来已经画好的数据先打在地图上。现在是进入选择绘画模式,这个模式下你可以进行 【选择样式】、选择后绘画完成后的【绘画完成】,对当前已经画的数据【进入编辑】,下面有全部清除数据的【清除画布】,和对当前层的数据进行【保存画布】。
        // 围栏事件的模式选择
        _fence_ev_mode: function() {
          // me._fence_sel();

          // 有数据--可以清除画布 可以编辑画布
          if (me.conf.fence.mode == 1) {

            $('#tool')
              .show()
              .html(`
                
开启编辑
编辑完成
退出编辑
`) .off() // 开启编辑 .on('click', '#f_edit_ing', function() { me._fence_edit_ing(); }) // 编辑完成 .on('click', '#f_edit_done', function() { me._fence_edit_done(); }) .on('click', '#f_edit_out', function() { me._fence_edit_out(); }); // 编辑完成先影藏 $('#f_edit_ing').show(); $('#f_edit_done').hide(); } // 没有数据--选择样式/绘画完成 else if (me.conf.fence.mode == 2) { $('#tool') .show() .html(`
选择样式
绘画完成
进入编辑
**
清除画布
保存画布
`) .off() // 选择样式 .on('click', '#f_sel', function() { me._fence_sel(); }) // 绘制完成 .on('click', '#f_draw_done', function() { me._fence_draw_done(); }) // 进入编辑 .on('click', '#f_in_edit', function() { me._fence_in_edit(); }) // 清除 .on('click', '#f_clear', function() { me._fence_clear(); }) // 保存数据 .on('click', '#f_save', function() { me._fence_save(); }); } },

【Openlayers】V5.0.2 单点追踪、实时监控、历史轨迹、地图绘制全代码实例_第4张图片

  • 【选择样式】进行绘制,我这里把我img文件夹下面所有的图片都作为一个样式可以进行绘制:

【Openlayers】V5.0.2 单点追踪、实时监控、历史轨迹、地图绘制全代码实例_第5张图片

  •  提供的样式有 5中,图标、点、线 、圆、多边形。需要注意的是,图片的样式需要每次实例化,点、线 、圆、多边形的样式都可以提前设置。写博客的时候发现还可以对图标的样式代码进行优化,就是每次用图标的样式先判断有没有,没有的话就实例化一个,配置到我们的全局,有的话也是上次实例化的直接用就可以。
  • 还需要注意的就是在初始化图片的时候,就把图片代表的类型作为属性付过去,再绘制完成要把这些属性挂载到数据上,以便在提交的数据的时候,我们知道我们提交的是什么类型的数据,分别要数据内容的哪些参数。
        // ==========================绘画模式
        // 绘制选择
        _fence_sel: function() {

          layer.open({
            type: 1,
            title: false,
            area: ['520px', '600px'],
            skin: 'cc_layer',
            anim: 1,
            shade: 0.6,
            closeBtn: 0,
            btn: false,
            content: `
            
选择样式
cancel save
`, success: function(layero, index) { // 取消事件 me._fence_sel_cancel(index); // 加载图片 me._fence_sel_img(); // 绘画初始化 me._fence_sel_init(index); }, }); }, // 取消事件 _fence_sel_cancel: function(index) { // 取消 $('#cancel') .off() .on('click', function() { layer.close(index); }); }, // 开始绘制的加载图片 _fence_sel_img: function() { var str = ''; // 加载图标 for (var name in me.conf.fence.icon) { str += `
${name}
`; } $('#sel_box').html(str); var key = null; $('#sel_box') .off() .on('click', '.box', function(e) { key = $(e.currentTarget).hasClass('ac'); // 点击其他项目 if (!key) { $('#sel_box .box').removeClass('ac'); $(e.currentTarget).addClass('ac'); // 全局拿到绘制的样式的ID me.conf.fence.type = $(e.currentTarget).attr('type'); me.conf.fence.type_id = $(e.currentTarget).attr('type_id'); } }); }, // 开始绘制初始化 _fence_sel_init: function(index) { $('#save') .off() .on('click', function() { // 初始化工具 me._fence_sel_tool_drawing(); // 关闭图层 layer.close(index); }); }, // 初始化绘画工具绘画中 _fence_sel_tool_drawing: function() { // 清除工具 if (me.all_obj.fence.draw_tool != null) { me.map.removeInteraction(me.all_obj.fence.draw_tool); } // 不是icon if (me.conf.fence.type != 'icon') { // 工具 me.all_obj.fence.draw_tool = new ol.interaction.Draw({ type: me.conf.fence.type, // 注意设置source,这样绘制好的线,就会添加到这个source里 source: me.all_obj.fence.data_c, // 设置绘制时的样式 style: me.conf.fence.style[me.conf.fence.type], }); } // icon else { // 设置样式 me.conf.fence.style[me.conf.fence.type] = new ol.style.Style({ // 绘制的那个标记 image: new ol.style.Icon({ src: me.conf.fence.icon[me.conf.fence.type_id].src, // 注意这个,竟然是比例 左上[0,0] 左下[0,1] 右下[1,1] anchor: [0.5, 0.5], // 这个直接就可以控制大小了 scale: 0.5 }), }); // 工具 me.all_obj.fence.draw_tool = new ol.interaction.Draw({ type: "Point", // 注意设置source,这样绘制好的线,就会添加到这个source里 source: me.all_obj.fence.data_c, // 设置绘制时的样式 style: me.conf.fence.style[me.conf.fence.type], }); } // 添加工具 me.map.addInteraction(me.all_obj.fence.draw_tool); // 每次绘制完成 me.all_obj.fence.draw_tool .on('drawend', function(event) { // event.feature 就是当前绘制完成的线的Feature event.feature.setStyle(me.conf.fence.style[me.conf.fence.type]); // 挂载属性 event.feature.type = me.conf.fence.type; event.feature.type_id = me.conf.fence.type_id; // console.log(me.conf.fence.type,me.conf.fence.type_id) }); },
  • 源码: 源码(谢谢star)
  • 线上地址:http://ol.armincc.com

你可能感兴趣的:(openlayers)