最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • tony的高德地图api爬坑之路...

    正文概述 掘金(Tony)   2021-08-02   638

    前言

    由于项目里面涉及到高德地图web端相关业务需求,自己也是从不会到看文档慢慢学会,诚惶诚恐,这篇文章说与其是技术分享,其实是给没接触过高德地图jsapi的前端开发者分享一些小小的建议以及自己的一些经验之谈,说的有不对的地方欢迎大家指正~

    接下来我会从【新手怎么看文档】【怎么根据业务需求合理使用api】【怎么封装业务组件】【那些年Tony爬过的坑】这几个方面来具体聊一聊

    1.新手怎么看文档

    个人认为高德地图api文档相对百度地图、bing地图而言更加清晰明了,对新手比较友好,我拿到需求如果不熟悉也要先看一下文档,只需要看web端jsapi即可,主要看这几个板块:

    1. 示例中心(这里有一些前人写好的demo,拿来稍微改动一下就可以变成业务代码)
    2. 参考手册(如果示例中心还不能满足需求,或者对某个类某个方法不熟悉,可以移步到这里定位到相关类或者方法仔细观察一下)
    3. AMapUi组件(这个是高德自己封装好的一些组件,可以实现一些复杂业务,比如用巡航器结合el-slider组件实现带进度条的轨迹回放效果)

    2.怎么根据业务需求合理使用api

    2.1.地图

    2.2.1.创建地图

    main.js
    // 引入vue-amap
    import VueAMap from 'vue-amap';
    Vue.use(VueAMap);
    // 初始化vue-amap
    VueAMap.initAMapApiLoader({
      // 高德的key
      key: '你申请的key',
      // 插件集合
      plugin: ['Autocomplete', 'PlaceSearch', 'Scale', 'HawkEye', 'ToolBar', 'ControlBar', 'MapType', 'PolyEditor', 'AMap.CircleEditor', 'AMap.MarkerClusterer', 'AMap.Geocoder'],
      // api版本
      v: '2.0',
      // AMapUi组件库版本
      uiVersion: '1.1.1'
    });
    
    单文件组件内使用
    import { lazyAMapApiLoaderInstance } from 'vue-amap'
    
    initMap () {
          lazyAMapApiLoaderInstance.load().then(() => {
            this.map = new AMap.Map('map', {
              viewMode: '2D',
              center: this.center,
              zoom: this.zoom
            })
            let toolBar = new AMap.ToolBar({
              position: {
                top: '110px',
                left: '40px'
              }
            })
            let controlBar = new AMap.ControlBar({
              position: {
                top: '10px',
                left: '10px'
              }
            })
            let scale = new AMap.Scale()
            this.map.addControl(toolBar)
            this.map.addControl(controlBar)
            this.map.addControl(scale)
          })
        }  // 这个是2.0版本写法,1.x版本写法稍微有所不同
    

    2.2.点标记

    2.2.1.创建点标记

    或者

    建议使用第二种方法,用户体验比较好

    2.2.2.点标记添加弹跳动画

    /deep/.bounce-marker {
              animation: bounce 0.5s cubic-bezier(0.1, 0.25, 0.1, 1) 0s infinite
                alternate both;
            }
            @keyframes bounce {
              from {
                transform: translateY(0px);
              }
              to {
                transform: translateY(-40px);
              }
            }
    

    2.2.3.点标记轨迹回放

    2.2.4.点标记聚合显示

    2.3.折线

    使用AMap.Polyline构建函数创建实例--->调用map的add方法将实例添加到地图上

    2.4.多边形

    2.4.1创建多边形

    或者

    建议使用第二种方法,用户体验比较好

    2.5.圆

    2.5.1.创建圆

    使用AMap.Circle(opt:CircleOptions)构建函数创建实例--->调用map的add方法将实例添加到地图上

    2.5.2.编辑圆

    首先根据后端返回的圆心经纬度和半径回显圆--->然后使用AMap.CircleEditor(Map,Circle)创建实例--->调用open方法开启编辑--->监听move、adjust事件

    2.5.3.根据id唯一标识查看(放大)圆

    遍历后端返回的圆形覆盖物列表数据(array),将唯一标识id绑定到AMap.Circle的extData参数上面,这样点击表格数据的每一行就可以根据这个唯一标识结合Circle类的getExtData()方法找到这个圆形覆盖物,然后调用map.setFitView()方法将该圆形覆盖物放大到合适的视野级别

    2.5.4.判断圆和圆的位置关系

    这个高德好像没有提供相关方法,自己实现,思路也很简单,大致思路就是判断圆心距离和半径之和的大小关系。怎么计算圆心距离可以参考api文档里面的【参考手册 数学计算库】

        doesCircleIntersect() {
          const circlesData = this.allCircleData.filter(item => item.type !== 3)
          if (!circlesData.length) {
            return
          }
          const isIntersect = circlesData.some(item => {
            const marker1 = new window.AMap.LngLat(item.lon, item.lat)
            const marker2 = new window.AMap.LngLat(this.circleOptions.lon, this.circleOptions.lat)
            const circleCenterDistance = marker1.distance(marker2)
            const circleRadiusSum = item.radius + this.circleOptions.radius
            return circleCenterDistance < circleRadiusSum
          })
          return isIntersect
        },
    

    2.5.5.判断圆和点标记的位置关系

    直接调用Circle类的contains(point:LngLat)方法,这个方法返回一个boolean,用于判断圆形覆盖物是否包含点标记

    2.6.信息窗体

    2.6.1.打开信息窗体

        // 方法一:html字符串拼接思路实现
        // 打开信息窗体
        openInfoWindow(info) {
          var infoList = ['<div class="info-container">']
          infoList.push(`<div class="info-container__header">飞手信息</div>`)
          infoList.push(`<div class="info-container__body">`)
          infoList.push(`<div>飞手姓名:${info.pilotName}</div>`)
          infoList.push(`<div>身份证号:${info.identityCard}</div>`)
          infoList.push(`<div>飞行时长:${info.duration}h</div>`)
          infoList.push(`<div>地址:${info.address}</div>`)
          infoList.push(`<div>经度:${info.pilotLon} 纬度:${info.pilotLat}</div>`)
          infoList.push(`</div></div>`)
          this.infoWindow = new window.AMap.InfoWindow({
            content: infoList.join(''), // 使用默认信息窗体框样式,显示信息内容
            offset: new window.AMap.Pixel(-5, -35)
          })
          this.infoWindow.open(
            this.map,
            new window.AMap.LngLat(info.pilotLon, info.pilotLat)
          )
        }
        
        // 方法二:使用组件的思路去实现,设置isCustom属性为true就可以随心所欲的去用组件去实现一个自定义的信息窗体
        // 打开信息窗体
        openInfoWindow(info) {
          this.showInfoWindow = true
          this.infoWindowContent = info
          const infoWindow = new window.AMap.InfoWindow({
            isCustom: true, // isCustom设置true 自定义信息窗体
            content: this.$refs.infoWindowRef.$el, // 指向自定义信息窗体dom元素
            offset: new window.AMap.Pixel(0, 0)
          })
          this.infoWindow = infoWindow
          this.infoWindow.open(this.map, new window.AMap.LngLat(info.lon, info.lat))
        }
    

    2.7.覆盖物群组

    2.8.LBS服务

    2.8.1.地理编码(地址->经纬度)

        /**
         * 根据关键词查询经纬度
         */
        getLngLatByKeywords(keywords) {
          const geocoder = new window.AMap.Geocoder()
          geocoder.getLocation(keywords, (status, result) => {
            if (status === 'complete' && result.geocodes.length) {
              const center = result.geocodes[0].location
              this.map.setCenter(center)
              this.map.setZoom(18)
            } else {
              this.$message.info('根据地址查询位置失败,请输入详细地址搜索')
            }
          })
        },
    

    2.8.2.逆地理编码(经纬度->地址)

     /**
         * 根据经纬度查询位置
         */
        getAddressByLngLat(lnglat) {
          const geocoder = new window.AMap.Geocoder({
            city: '全国'
          })
          geocoder.getAddress(lnglat, (status, result) => {
            if (status === 'complete' && result.regeocode) {
              const address = result.regeocode.formattedAddress
              this.form.remarks = `以${address}为中心,以${this.circleOptions.radius}米为半径的圆形区域`
            } else {
              this.$message.info('根据经纬度查询地址失败')
            }
          })
        },
    

    2.8.3.行政区划查询

    3.怎么封装业务组件

    4.那些年Tony爬过的坑

    tony的高德地图api爬坑之路...

    什么...Tony???没错,不要怀疑,我以前不是理发的,只是英语不好所以取了这个简单又好记的名字,我很喜欢,毕竟已经伴随我好几年的职业生涯了

    4.1.绘制多边形使用第一种方法点标记不按套路出牌,不按顺时针连接,也不按逆时针连接,却是交叉连接。这么说可能还是有些懵逼,我手绘几张图对比看一下就明白了

    tony的高德地图api爬坑之路... 期望的连接顺序是1-2-3-4-1 或者 1-4-3-2-1 然而 他偏偏不给面子逆天而行 1-2-4-3-1 或者 1-3-4-2-1

        // start表示中心点  end表示多边形顶点
        getAngle (start, end) {
          // 首先将经纬度坐标转换为平面坐标
          const p_start = this.map.lngLatToContainer(start)
          const p_end = this.map.lngLatToContainer(end)
          const diff_x = p_end.x - p_start.x
          const diff_y = p_end.y - p_start.y
          return (360 * Math.atan2(diff_y, diff_x)) / (2 * Math.PI) + 180
        }
        
        // 遍历顶点集合,调用getAngle方法获取每个顶点和中心点成的角度(<90°),根据角度对顶点进行排序,排好序再绘制多边形即可,后续代码省略
    

    4.2.列表页新增圆形(多边形)覆盖物成功之后,立即点击编辑这条新增记录,打开el-dialog对话框,对话框里面的地图会出现首次渲染失败的神奇bug

    结语

    行文至此,想聊的基本都聊了,可能还有一些高级用法,不常见的bug我还没接触过,算不上干货满满,也算不上废话连篇,只能说是给新人一点小小的指引,希望看了我的文章可以少走一点弯路,有什么想法也可以留言相互交流。

    下载网 » tony的高德地图api爬坑之路...

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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