最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    正文概述 掘金(我这暴脾气)   2021-05-04   966

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    引言

    前端er必备技能之一:地图开发。也不能说是开发,只是拿百度地图大牛们开发好的插件,做一个简单使用。建议阅读本文前,先尝试一下在线地图的开发,如:申请AK码,了解百度地图相关api,Echarts中地图模块。

    效果预览

    去年在JS中做的离线版,为了兼容IE,使用的老版本Echarts: 需要兼容ie的可以使用这个版本的Echarts

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。 这是最近做的vue版:

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    实现方式

    1.引入文件

    我的实现方式是需要4样东西:echarts,apiv1.3.min.js,modules_ditu.js,瓦片图。

    地图开发最关键的一步就是:如何引入百度地图的api文件。 在线地图中的引用很简单,只需要script引入一个url即可,即可引入相关API的文件。<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你的AK码"></script>

    那么离线地图也是一样的思路,我们只需要引入api相关的JS文件即可。引入文件步骤(以需要的apiv1.3.min为例)。我之前是学习的这位博主的博客

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    在离线地图中,我们需要引入的JS文件只有2个JS,文中说的那个CSS可以不引,无影响。

    最后就是我们的核心=>瓦片图的获取。离线地图就是靠JS中动态拼接路径,来调取瓦片图,以此来实现的可视化地图。我们用的瓦片图只有5个层级,但是图片数量也已经有2W多张了,

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    2.文件中路径改动

    文件引入之后呢,我们还需要根据我们的文件存放位置,来调整一下两个JS中的路径。以我的这一版api--.js为例:

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    3.引入文件出现的bug

    文本无法选中

    在引入地图相关文件的该页面中,会出现文本无法选中,使得用户无法复制。这个是因为modules_ditu.js引起的,因为有的modules--.js版本中,会加onselectstart = fasle 禁止选中文字。然后呢,我试着在源码中,改变其值,反正是木得效果,没起作用。

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。 最后的解决方法,百度的是,重新找几个老版本的modules--.js文件替上去即可。

    vue中的代码实现

    1.相关代码

    index.html中引入

    注:脚手架创建的项目中,因为webpack中打包静态文件路径默认是在static中,所以我们的静态文件也要放在static下。

    <script type="text/javascript" src="./static/map/js/apiv1.3.min.js"></script>
    modules_ditu不用在这引入,因为该JS是在api---.js中有引入,无需重复引入。
    
    <template>
      <div class="ip_query query clearfix">
        <div id="map"></div>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          geo_data: {
            city: null,
            coord: null,
            radius: null
          }
        };
      },
      created() {
        let this_ = this;
        let ipLocation = {
          city: null,
          coord: null,
          radius: 600
        };
        // 赋值
        this.geo_data = {
          city: ipLocation.city ? ipLocation.city : "北京",
          coord: [
            ipLocation.lngwgs ? ipLocation.lngwgs : 116.397469,
            ipLocation.latwgs ? ipLocation.latwgs : 39.908821
          ],
          radius: ipLocation.radius
        };
        // 绘制地图
        this.$nextTick(() => {
          let IpMap_ec = this.echarts.init(document.getElementById("map"));
          let map_render = function(params, api) {
            let x_y = api.coord(this_.geo_data.coord);
            let r = api.size([0, 1])[1] * (this_.geo_data.radius / 80);
            let color = "#A7C2DF";
            return {
              type: "circle",
              shape: {
                cx: x_y[0],
                cy: x_y[1],
                r: r
              },
              style: api.style({
                fill: color,
                stroke: this_.echarts.color.lift(color)
              })
            };
          };
          IpMap_ec.setOption(
            {
              bmap: {
                center: this.geo_data.coord,
                zoom: 5,
                roam: "scale"
              },
              series: [
                {
                  type: "scatter",
                  coordinateSystem: "bmap",
                  symbol: "circle",
                  symbolSize: 30,
                  data: [
                    {
                      name: this.geo_data.city,
                      value: this.geo_data.coord
                    }
                  ]
                },
                {
                  type: "custom",
                  coordinateSystem: "bmap",
                  renderItem: map_render,
                  itemStyle: {
                    opacity: 0.5
                  },
                  animation: false,
                  silent: true,
                  data: [0],
                  z: -10
                }
              ]
            },
            true
          );
          // map API事件相关
          let bmap = IpMap_ec.getModel()
            .getComponent("bmap")
            .getBMap();
          bmap.setMinZoom(3);
          bmap.setMaxZoom(7);
          // 解决滚动触发2次zoomstart时的情形
          let zoom_arr = [];
          bmap.addEventListener("zoomstart", function() {
            let zoom_level = bmap.getZoom();
            zoom_arr.push(zoom_level);
          });
          let zoom_map = function() {
            let point = new BMap.Point(
              this_.geo_data.coord[0],
              this_.geo_data.coord[1]
            );
            if (zoom_arr.length > 1) {
              let end_level = bmap.getZoom();
              let differ = end_level - zoom_arr[0];
              let res_level = differ > 0 ? zoom_arr[0] + differ - 1 : zoom_arr[0] + differ + 1;
              zoom_arr = [];
              bmap.centerAndZoom(point, res_level);
            } else {
              bmap.centerAndZoom(point, bmap.getZoom());
              zoom_arr = [];
            }
          };
          // 缩扩固定中心点
          bmap.addEventListener("zoomend", zoom_map);
        });
      }
    };
    </script>
    <style lang="stylus" scoped>
    .ip_query {
      #map {
        width: 900px;
        height: 600px;
        position: relative;
        margin: 30px auto;
      }
    }
    </style>
    
    

    实现效果:

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    2.相关bug或优化点

    1.如果2次或多次实例化echarts,滑轮滚动一次,缩扩2个级别

    因为我做的这一版地图主要是运用到IP查询中,可能会出现查询失败,查询时的input框及查询内容的动态过渡效果的实现,然后我这里是简单粗暴的多次实例化echarts来达到效果。这样会出现一个问题,就是多次搜索IP,地图中缩扩时会出现滑轮滚动一次,缩扩2个级别,然后做了个判断,来手动让他恢复缩放正常情况下。

          // 解决滚动触发2次zoomstart时的情形
          let zoom_arr = [];
          bmap.addEventListener("zoomstart", function() {
            let zoom_level = bmap.getZoom();
            zoom_arr.push(zoom_level);
          });
          let zoom_map = function() {
            let point = new BMap.Point(
              this_.geo_data.coord[0],
              this_.geo_data.coord[1]
            );
            if (zoom_arr.length > 1) {
              let end_level = bmap.getZoom();
              let differ = end_level - zoom_arr[0];
              let res_level;
              if (differ > 0) {
                res_level = zoom_arr[0] + differ - 1;
              } else {
                res_level = zoom_arr[0] + differ + 1;
              }
              zoom_arr = [];
              bmap.centerAndZoom(point, res_level);
            } else {
              bmap.centerAndZoom(point, bmap.getZoom());
              zoom_arr = [];
            }
          };
          // 缩扩固定中心点
          bmap.addEventListener("zoomend", zoom_map);
    

    2.拖拽出边界时的优化

    地图实质上就是瓦片图的拼接,但是离线地图受制于瓦片图的完善度,拖拽出边界后,我们实质上是没有图片可以引了。所以,会出现灰边(咋们的背景色),体验不好。

    最好的效果就是:用户拖拽至边界时,禁用拖拽。往回拖时,再启用拖拽。或者 是做成球形的效果,拖拽至左侧边界时,出现右侧边界,但难度较大。我这里完成的是类似第一种效果,也并不完美。

    去年在做的时候,本意是想在每次拖拽开始时(dragstart)先判断当前是否在边界处,在边界处就继续禁用拖拽,dragging中判断滑动至边界时,直接禁用拖拽map.disableDragging();,然后dragend中再启用拖拽。但是,实际中禁用拖拽后,比如dragging中禁用拖拽,他就不走dragend了,直接在dragging这一状态便停止了,然后其他的回调情况也是类似这种,我没有找到完善的触发这套流程的回调,所以就没能实现。

    因为离线地图的资料比较少,百度地图的API中也并不完善,没有相关的回调,我又没能力自己封装,所以就采用的是下边这种。 这里的思路就是:

    因为我们只有4个缩放层级,然后通过百度地图的相关API手动测出临界值时所对应的中心点经纬度,在拖拽出边界时,给他拖回当前临界值对应的中心点。然后呢,这里的问题就是:当你拖拽出边界时,再拖回边界所对应的中心点时,实际上是有一个过程的,会有一定的时间来完成这个流程。然后这种情况呢,就会触发多次拖拽回当前中心点,用户的体验就是下图中:拖拽出左边界时,会下滑一定距离。只会回到当前左边界中心点对应的x处,y是会下滑一些的。关于这个问题的解决,我在后来学习了防抖节流之后,可以用节流的思路去完善一下。

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

     let x = 0;
     let y = 0;
     map.addEventListener('dragging', function () {
                    console.log(map.getBounds().getCenter());
                    //移动后的可视区域
                    var movew = map.getBounds().getSouthWest();   //可视区域左下角
                    var movee = map.getBounds().getNorthEast();   //可视区域右上角
    
                    var moveL = movew.lng;//可视区域左边界的经度
                    var moveR = movee.lng;//可视区域右边界的经度
                    var moveB = movew.lat;//可视区域下边界的纬度
                    var moveT = movee.lat;//可视区域上边界的纬度
    
                    var boundaryleftlng;//左边界临界值经度
                    var boundaryrightlng;//右边界临界值经度
                    var boundarytoplat;//上边界临界值纬度
                    var boundarydownlat;//下边界临界值纬度
    
                    if (zoom == 4) {
                        boundaryleftlng = -179.204242;
                        boundarydownlat = -82.202266;
                        boundaryrightlng = 180.910992
                        boundarytoplat = 84.602547;
                        if (moveR > boundaryrightlng) {
                            x = 60;
                        } else if (moveL < boundaryleftlng) {
                            x = -58;
                        } else {
                            x = map.getBounds().getCenter().lng;
                        }
                        if (moveT > boundarytoplat) {
                            y = 65;
                        } else if (moveB < boundarydownlat) {
                            y = -55;
                        } else {
                            y = map.getBounds().getCenter().lat;
                        }
                    } else if (zoom == 5) {
                        boundaryleftlng = -179.940134;
                        boundarydownlat = -81.533889;
                        boundaryrightlng = 179.690224;
                        boundarytoplat = 84.602547;
                        if (moveR > boundaryrightlng) {
                            x = 120;
                        } else if (moveL < boundaryleftlng) {
                            x = -120;
                        } else {
                            x = map.getBounds().getCenter().lng;
                        }
                        if (moveT > boundarytoplat) {
                            y = 79;
                        } else if (moveB < boundarydownlat) {
                            y = -55;
                        } else {
                            y = map.getBounds().getCenter().lat;
                        }
                    } else if (zoom == 6) {
                        boundaryleftlng = -179.976929;
                        boundarydownlat = -81.133421;
                        boundaryrightlng = 179.984581;
                        boundarytoplat = 84.581712;
                        if (moveR > boundaryrightlng) {
                            x = 150;
                        } else if (moveL < boundaryleftlng) {
                            x = -150;
                        } else {
                            x = map.getBounds().getCenter().lng;
                        }
                        if (moveT > boundarytoplat) {
                            y = 82;
                        } else if (moveB < boundarydownlat) {
                            y = -73;
                        } else {
                            y = map.getBounds().getCenter().lat;
                        }
                    } else if (zoom == 7) {
                        boundaryleftlng = -179.811353;
                        boundarydownlat = -80.952417;
                        boundaryrightlng = 179.910992;
                        boundarytoplat = 84.607743;
                        if (moveR > boundaryrightlng) {
                            x = 164;
                        } else if (moveL < boundaryleftlng) {
                            x = -164;
                        } else {
                            x = map.getBounds().getCenter().lng;
                        }
                        if (moveT > boundarytoplat) {
                            y = 83;
                        } else if (moveB < boundarydownlat) {
                            y = -78;
                        } else {
                            y = map.getBounds().getCenter().lat;
                        }
                    }
    
                    if(moveR > boundaryrightlng || moveL < boundaryleftlng || moveT > boundarytoplat || moveB < boundarydownlat){
                        // map.disableDragging();
                        var point = new BMap.Point(x,y);
                        map.centerAndZoom(point, map.getZoom());
                    }
                });
    

    3.mousemove事件耗时久使得拖拽体验不好(未解决)

    vue版的代码中我禁止了拖拽,因为我用的两个JS文件和上面的JS版的是一样的,但是用最新版的echarts加vue引入后,拖拽时会报这个警告,会很卡顿,正好我们的需求也不用拖拽,我就禁了给。如果你需要拖拽的话可以试试多找几个版本的api--.js和module--.js替上去试试看能否解决。

    关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    尾言

    感谢您能看到这里,如果觉得有些许收获的话,请动动你发财的小手,给小编点个赞吧~ !

    因为目前是五一假期,瓦片图那个文件太大了,我就没拷,之后我会把我这一版地图的相关文件,上传到百度云,后续会放个链接,大家感兴趣的可以下载一下,试试看。


    起源地下载网 » 关于Echarts与百度地图相结合,在内网环境下开发离线地图,实现描点,连线,范围值。

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元