头图

前言

作为一名在职岗位为【前端开发工程师】的程序员,我开发的应用程序经常需要获取用户位置信息,需要再某些场合下使用展示地图以及地图商的某些地点,需要获取行政区划列表(省市区)以及地址详情信息,需要在地图上规划一条(动态)路线,轨迹回放,小车移动,需要创建信息窗口,用于地点的摘要性信息的展示。

公司内做的是共享项目, 场景是这样的,一种常见共享充电宝(功能差不多和流行的共享单车一样),在做小程序首页时,需要做到的是扫码充电,联系客服(问题反馈),获取地理位置,开篇即是一副地理位置,在你附近获取到区域内店铺信息,点击该店的logo标志可以获取该店的地理位置,营业时间,店名,距离,是否当前该店里是否有可借的充电宝等信息。

共享充电电动车🚗,首页也是一副地理位置地图,可以获取你附近最近的共享电动车,获取车的地址,状态等信息。显示该车的剩余电量,使用记录,租借订单,获取行程轨迹,某时间段内的里程,动态显示轨迹等。

涉及到的共享其实内容很多(如除了电动车,充电宝,还可租借设备等),但大都功能几乎相同,需要交押金,租借费用,信用免押金等。开发过app,H5,web网站,小程序项目都与地图相关的位置服务息息相关,让我说说与位置服务有关的故事。

下面主要还是讲解其中的关于地图功能等功能,使用的也是腾讯位置开发服务。会一步一步说明,做一些案例展示,代码说明,使用教程。(注意这里我回去看开发教程,尽量把每个功能都熟悉地说明一下使用方法)
一、腾讯位置服务是什么?
腾讯位置服务无疑是获取位置服务等信息内容,该产品亮点:

  1. 定位:为合作伙伴和广大开发者提供完善的位置解决方案,已为社交、出行、游戏、商业、O2O、物流等领域提供专业精准的定位服务
  2. 地图:腾讯位置服务在多平台为开发者提供了丰富的地图展现形式,帮助从属于不同领域的开发人员轻松完成构建地图并在其基础上打造专属内容的工作。同时配合海量数据、个性化定制、可视化等能力满足各个行业场景下对地图的需求
  3. 地点搜索:基于海量鲜活地点(POI)数据,提供周边搜索,城市范围搜索,关键词输入提示、分类筛选等多种搜索能力,面向社交、物流、出行等行业打造专属搜索策略,体验更胜一筹
  4. 路线规划:根据出发地、目的地以及路线策略设置,结合精准的实时交通路况提供驾车、步行、骑行、公交路线规划能力,助力开发者为用户提供贴心、人性化的出行体验
  5. 微信小程序解决方案:腾讯位置服务全面拥抱小程序生态,从服务API、基础地图组件、插件、行业方案等多个层面服务不同场景需求的小程序开发者,助力小程序插上地图的“翅膀”!
  6. 个性化地图:个性化样式:千行千面,助力开发者根据自身产品的使用场景、界面色调, 选取或者创建风格匹配的地图样式,体验更胜一筹;个性化图层:真实酷炫,助力开发者将精美绘图生成地图瓦片并置于地图之上,让旅游景点、大学高校等区域的展示效果与众不同

二、使用步骤

1.uniapp开发map说明

使用uniapp是因为它是一个使用vue.js开发所有前端应用的框架,开发者编写一套代码,可以发布到ios,android,web以及各种小程序,快应用等多个平台。
使用map地图组件开发,地图组件用于展示地图(使用的时腾讯地图),说一下它的属性有:

longitude(类型为Number,没有默认值,表示中心经度)
latitude(类型为Number,没有默认值,表示中心纬度)
scale(类型为Number,默认值为16,缩放级别取值范围为5-18)
markers(类型为Array数组,类型为数组即表示地图上可以有多个,没有默认值,表示标记点)
polyline(类型为Array数组,没有默认值,表示路线,数组上的所有点连成线)
circles(类型Array数组,表示圆)
controls(类型Array数组,表示控件)
include-points(类型Array数组,表示缩放视野已包含所有给定的坐标点)
enable-3D(类型为Boolean,默认值为false,表示是否显示3D搂块)
show-compass(类型为Boolean,默认值为false,表示为是否显示指南针)
enable-overlooking(类型为Boolean,默认值为false,表示为是否开启俯视)
enable-satellite(类型为Boolean,默认值为false,表示为是否开启卫星图)
enable-traffic(类型为Boolean,默认值为false,表示为是否开启实时路况)
show-location(类型为Boolean,表示显示带有方向的当前定位点)
polygons(类型Array,表示为多边形)

点击属性

  1. @markertap-表示点击标记点时触发,e.detail={markerId}
  2. @labeltap-表示点击label时触发,e.detail = {markerId}
  3. @callouttap-表示点击标记点对应的气泡时触发,e.detail = {markerId}
  4. @controltap-表示点击控件时触发,e.detail = {controlId}
  5. @regionchange-表示视野发生变化时触发
  6. @tap-表示点击地图时触发; App-nuve、微信小程序2.9支持返回经纬度
  7. @updated-表示在地图渲染更新完成时触发
我们在写map组件时,组件的宽/高推荐写直接量,比如说是 750rpx,不要设置百分比值,在uni-app中只支持gcj02坐标。

介绍markers属性-类型为数组Array

由之前描述可知,markers属性类型为Array,表示标记点用于在地图上显示标记的位置。这个数组属性,它里面有它的对象配置属性,分别是:

  1. id,表示标记点id,类型为Number,必填项,marker点击事件回调会返回此id,建议为每个marker设置上Number类型id,保证更新marker时有更好的性能。
  2. latitude,纬度,类型Number,必填项,浮点数,范围 -90 ~ 90
  3. longitude,经度,类型Number,必填项,浮点数,范围 -180 ~ 180
  4. title,标注点名,类型String,不是必填,点击时显示,callout存在时将被忽略
  5. iconPath,显示的图标,类型String,必填项,项目目录下的图片路径
  6. rotate,旋转角度,类型Number,不是必填,顺时针旋转的角度,范围 0 ~ 360,默认为 0
  7. alpha,标注的透明度,类型Number,不是必填,默认1,无透明,范围 0 ~ 1
  8. width,标注图标宽度,类型Number,不是必填,默认为图片实际宽度
  9. height,标注图标高度,类型Number,不是必填,默认为图片实际高度
  10. callout,自定义标记点上方的气泡窗口,类型Object,不是必填 - 可识别换行符
  11. label,为标记点旁边增加标签,类型Object,不是必填 - 可识别换行符
  12. anchor,经纬度在标注图标的锚点,默认底边中点,不是必填,{x, y},x表示横向(0-1),y表示竖向(0-1)。{x: .5, y: 1} 表示底边中点

marker 上的气泡 callout(Object类型)
marker数组 上属性 callout 对象使用属性:

  1. content,文本,String
  2. color,文本颜色,String
  3. fontSize,文字大小,Number
  4. borderRadius,callout边框圆角,Number
  5. bgColor,背景色,String
  6. padding,文本边缘留白,Number
  7. display,'BYCLICK':点击显示; 'ALWAYS':常显,String
  8. textAlign,文本对齐方式。有效值: left, right, center,String

marker 上的标签 label(Object类型)

  1. content,文本,String
  2. color,文本颜色,String
  3. fontSize,文字大小,Number
  4. x,label的坐标,原点是 marker 对应的经纬度,Number
  5. y,label的坐标,原点是 marker 对应的经纬度,Number
  6. borderWidth,边框宽度,Number
  7. borderColor,边框颜色,String
  8. borderRadius,边框圆角,Number
  9. bgColor,背景色,String
  10. padding,文本边缘留白,Number
  11. textAlign,文本对齐方式。有效值: left, right, center,String

polyline

polyline表示指定一系列坐标点,从数组第一项连线至最后一项

  • points,经纬度数组,类型为Array,必填,如:[{latitude: 0, longitude: 0}]
  • color,线的颜色,类型为String,不必填,如:#0000AA
  • width,线的宽度,类型为Number,不必填
  • dottedLine,是否虚线,类型为Boolean,不必填,默认值false
  • arrowLine,带箭头的线,类型为Boolean,不必填,默认值为false
  • arrowIconPath,更换箭头图标,类型为String,不必填,在arrowLine为true时,默认带箭头的线时生效
  • borderColor,线的边框颜色,类型为String,不必填
  • borderWidth,线的厚度,类型为Number,不必填

polygon
polygon指定一系列坐标点,根据points坐标数据生成闭合多边形

  • points,经纬度数组,array,必填,如:[{latitude: 0, longitude: 0}]
  • strokeWidth,描边的宽度,Number,否
  • strokeColor 描边的颜色,String,否
  • fillColor,填充颜色,String,否
  • zIndex,设置多边形 Z 轴数值,Number,否

circles
circles在地图上显示圆

  • latitude,纬度,Number,必填,浮点数,范围 -90 ~ 90
  • longitude,经度,Number,必填,浮点数,范围-180 ~ 180
  • color,描边的颜色,String,不必填,如:#0000AA
  • fillColor,填充颜色,String,不必填,如:#0000AA
  • radius,半径,Number,必填
  • strokeWidth,描边的宽度,Number,不必填

controls
controls在地图上显示控件,控件不随着地图移动

  • id,控件id,Number,不必填,在控件点击事件回调会返回此id
  • position,控件在地图的位置,Object,必填,控件相对地图位置
  • iconPath,显示的图标,String,必填,项目目录下的图片路径,支持相对路径写法,以'/'开头则表示相对项目根目录;也支持临时路径
  • clickable,是否可点击,Boolean,不必填,默认不可点击
    position
  • left,距离地图的左边界多远,Number,不必填,默认为0
  • top,距离地图的上边界多远,Number,不必填,默认为0
  • width,控件宽度,Number,不必填,默认为图片宽度
  • height,控件高度,Number,不必填,默认为图片高度
注意在uniapp中地图组件的经纬度必填,如果不填,经纬度则默认值是北京的经纬度。

2.uniapp使用map组件

基本使用方法

使用uniapp开发中的map组件,基本使用方法:
代码如下(示例):

<map :scale="scale" style="width: 100%; height: 100%;"
enable-3D="false" show-compass="false" enable-overlooking="false"
:enable-satellite="false" :enable-traffic="false" show-location="false"
:latitude="latitude" :longitude="longitude" :markers="covers">
</map>

markers属性的使用,代码如下(示例):

markers: [{
    id: 1, // Number
    title: '1', // String-标注点名
    rotate: 180, // Number - 顺时针旋转的角度,范围 0 ~ 360,默认为 0
    alpha: 0.5, // 默认1,无透明,范围 0 ~ 1
    latitude: 39.899,
    longitude: 116.39742,
    width: 30,
    height: 30,
    // callout: {
    //     display: "BYCLICK",
    //     padding: 10,
    //     borderRadius: 5,
    //     content: '',
    // },
    // anchor: {},
    iconPath: '../../../static/location.png', // 显示的图标
}, {
    id: 2,
    title: '2', // String
    latitude: 39.90,
    longitude: 116.39,
    callout: {
        color: '#007AFF', // 文本颜色
        bgColor: '#563BFF', // 背景色
        display: "ALWAYS", // 'BYCLICK':点击显示; 'ALWAYS':常显
        fontSize: 15,
        textAlign: 'left', // 文本对齐方式。有效值: left, right, center
        padding: 10, // 文本边缘留白
        borderRadius: 5,
        content: '腾讯地图',
    },
    label: {
        content: 'Jeskson',
        color: '#000000',
        fontSize: 12,
        borderWidth: 12,
        borderColor: '#007AFF',
        borderRadius: 5,
        padding: 5,
        textAlign: 'center',
        bgColor: '#563BFF',
    },
    iconPath: '../../../static/location.png'
}]

预览效果如下:

controls:[{
    // 在地图上显示控件,控件不随着地图移动
    id: 1, // 控件id
    iconPath:'../../static/icon.png', // 显示的图标
    position:{
     // 控件在地图的位置
     left: 15,
     top: 15,
     width: 50,
     height: 50
   },    
}],

地址搜索

uni-app 只支持 gcj02 坐标

uni.getLocation(OBJECT)中的object参数

获取当前的地理位置、速度。 在微信小程序中,当用户离开应用后,此接口无法调用,除非申请后台持续定位权限;当用户点击“显示在聊天顶部”时,此接口可继续调用。

OBJECT参数说明

  • type,String,不必填,默认为 wgs84 返回 gps 坐标,gcj02 返回国测局坐标,可用于
    uni.openLocation 的坐标,app平台高德SDK仅支持返回gcj02
  • altitude,Boolean,不必填,传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度
  • geocode,Boolean,不必填,默认false,是否解析地址信息
  • success,Function,必填,接口调用成功的回调函数,返回内容详见返回参数说明
  • fail,Function,不必填,接口调用失败的回调函数
  • complete,Function,不必填,接口调用结束的回调函数(调用成功、失败都会执行)

对于success返回参数说明:

  • latitude,纬度,浮点数,范围为-90~90,负数表示南纬
  • longitude,经度,浮点数,范围为-180~180,负数表示西经
  • speed,速度,浮点数,单位m/s
  • accuracy,位置的精确度
  • altitude,高度,单位 m
  • verticalAccuracy,垂直精度,单位 m(Android 无法获取,返回 0)
  • horizontalAccuracy,水平精度,单位 m
  • address,地址信息(仅App端支持,需配置geocode为true)

address 地址信息说明

  • country,String,国家 如“中国”,没有则返回undefined
  • province,String,省份名称 如“北京市”,没有则返回undefined
  • city,String,城市名称,如“北京市”,没有则返回undefined
  • district,String,区,县名称 如“朝阳区”,没有则返回undefined
  • street,String,街道信息,如“酒仙桥路”,没有则返回undefined
  • streetNum,String,获取街道门牌号信息,如“3号”,没有则返回undefined
  • poiName,String POI信息,如“电子城.国际电子总部”,没有则返回undefined
  • postalCode,String,邮政编码,如“100016”,没有则返回undefined
  • cityCode,String,城市代码,如“010”,没有则返回undefined

uni.chooseLocation(OBJECT)打开地图选择位置。

  • latitude,String,不必填,目标地纬度
  • longitude,String,不必填,目标地经度
  • keyword,String,不必填,搜索关键字,仅App平台支持
  • success,Function,必填
  • fail,Function,不必填
  • complete,Function,不必填

success返回参数说明:

  • name,位置名称
  • address,详细地址
  • latitude,纬度,浮点数,范围为-90~90,负数表示南纬,使用 gcj02 国测局坐标系。
  • longitude,经度,浮点数,范围为-180~180,负数表示西经,使用 gcj02 国测局坐标系。

代码如下(示例):

chooseLocation(e) { //打开地图选择位置
    uni.chooseLocation({
        success: res => {
            console.log('位置名称:' + res.name);
            console.log('详细地址:' + res.address);
            console.log('纬度:' + res.latitude);
            console.log('经度:' + res.longitude);
            uni.getLocation({
                type: 'gcj02',
                altitude:true,
                geocode:true,
                success: function(res) {
                    console.log('当前位置的经度:' + res.longitude);
                    console.log('当前位置的纬度:' + res.latitude);
                }
            });
            console.log('省:' + res.address.slice(0, res.address.indexOf('省') + 1));
            console.log('市:' + res.address.slice(res.address.indexOf('省') + 1, res.address.indexOf('市') + 1));
            console.log('区:' + res.address.slice(res.address.indexOf('市') + 1, res.address.indexOf('区') + 1));
            this.query.address = res.address;
            this.query.latitude = res.latitude;
            this.query.longitude = res.longitude;
            this.query.province = res.address.slice(0, res.address.indexOf('省') + 1)
            this.query.city = res.address.slice(res.address.indexOf('省') + 1, res.address.indexOf('市') + 1)
            this.query.district = res.address.slice(res.address.indexOf('市') + 1, res.address.indexOf('区') + 1)
        }
    });
},

预览效果:

获取附近的动态,点聚合

uni.getNetworkType(OBJECT)获取网络类型。

uni.createMapContext(mapId,this)创建并返回 map 上下文 mapContext 对象。在自定义组件下,第二个参数传入组件实例this,以操作组件内 <map> 组件。

mapContext-mapContext 通过 mapId 跟一个 <map> 组件绑定,通过它可以操作对应的 <map> 组件。

该对象得方法列表:

  • getCenterLocation OBJECT 获取当前地图中心的经纬度,返回的是 gcj02 坐标系,可以用于 uni.openLocation
  • moveToLocation OBJECT 将地图中心移动到当前定位点,需要配合map组件的show-location使用
  • translateMarker OBJECT 平移marker,带动画
  • includePoints OBJECT 缩放视野展示所有经纬度
  • getRegion OBJECT 获取当前地图的视野范围
  • getScale OBJECT 获取当前地图的缩放级别
  • $getAppMap 获取原生地图对象 plus.maps.Map

getCenterLocation 的 OBJECT 参数列表

success Function 不必填,接口调用成功的回调函数 ,res = { longitude: "经度", latitude: "纬度"}

moveToLocation 的 OBJECT 参数列表 - 可不必填

translateMarker 的 OBJECT 参数列表

  • markerId Number 必填 指定 marker
  • destination Object 必填 指定 marker 移动到的目标点
  • autoRotate Boolean 不必填 移动过程中是否自动旋转 marker
  • rotate Number 不必填 marker 的旋转角度
  • duration Number 不必填 动画持续时长,默认值1000ms,平移与旋转分别计算
  • animationEnd Function 不必填 动画结束回调函数
  • fail Function 不必填 接口调用失败的回调函数

代码如下(示例):

<view id="activeMap">
    <view @tap="activeMarker={}">
        <view class="page-body map-view" style="z-index: 1;position: relative;">
            <view class="page-section page-section-gap map-view">
                <map :markers="shops" id="map1" :show-location="true" :latitude="latitude" :longitude="longitude" @regionchange="regionChange"
                 @markertap="markerTap" @tap="activeMarker={}">
                    <!-- @markertap 点击标记点时触发,e.detail = {markerId}-->
                    <!-- @tap 点击地图时触发-->
                    <!-- @regionchange 视野发生变化时触发-->
                </map>
                <cover-image class="map-image" src="../static/address.png"></cover-image>
            </view>
        </view>
    </view>
</view>
regionChange() { // 移动地图后重新获取门店
    uni.createMapContext('map1', this).getCenterLocation({
        success: res => {
            console.log(res.latitude)
            console.log(res.longitude)
            this.shopTimeout = setTimeout(_ => {
                this.shops = [{
                    address: "广东省汕头市xxx区xx大道1",
                    distance: 122,
                    end_time: "1",
                    id: 2,
                    latitude: "22.72078500009999",
                    longitude: "114.36090200009999",
                    shop: {
                        iconPath: '/static/logo.png',
                        id: 3,
                        latitude: "22.72078500009999",
                        longitude: "114.36090200009999",
                        height: 34,
                        width: 34,
                        shop: {return: 0}
                    },
                    return: 0,
                    height: 34,
                    width: 34,
                    start_time: "1",
                    store_name: "三星大酒店",
                    iconPath: '/static/shop.png',
                }]
            }, 500)
        },
        fail: res => {
            uni.showModal({
                content: '获取位置失败',
                showCancel: false
            })
        }
    })
},

预览效果图如下:

地图上标注附近的人

代码如下(示例):

list: [{
    id: 1264640,
    user_id: 335187,
    place: "Jeskson市",
    text: "dadaqianduan.cn",
    latitude: "27.267520",
    longitude: "111.727120",
    status: "normal",
    nickname: "dada",
    avatar: "https://image.aishencn.com/2020/10/20/002207441_40845724-user.jpg",
    distance: 13419,
}, {
    id: 1272720,
    user_id: 36950,
    place: "dadaqianduan市",
    text: "dadaqianduan.cn",
    latitude: "27.257640",
    longitude: "111.747910",
    deletetime: null,
    status: "normal",
    nickname: "dadaqianduan",
    avatar: "https://image.aishencn.com/2020/04/09/004135379_37869100-user.jpg",
    distance: 27070,
}, {
    id: 1316740,
    user_id: 366172,
    place: "dadaqianduan.cn",
    text: "dadaqianduan.cn",
    images: "https://image.aishencn.com/2020/11/04/215134979_98197351-bbs.jpg",
    latitude: "27.257430",
    longitude: "111.732960",
    status: "normal",
    nickname: "dada",
    avatar: "https://image.aishencn.com/2020/11/04/182622730_98197351-user.venus/cache/ext/crop/1604518314542_jpg",
    distance: 27190,
    images_arr: ["https://image.aishencn.com/2020/11/04/215134979_98197351-bbs.jpg"]
}],

预览效果如图:

定位附近门店

代码如下(示例):

// 两点间距离
distance(la1, lo1, la2, lo2) {
    var La1 = (la1 * Math.PI) / 180.0
    var La2 = (la2 * Math.PI) / 180.0
    var La3 = La1 - La2
    var Lb3 = (lo1 * Math.PI) / 180.0 - (lo2 * Math.PI) / 180.0
    var s =
        2 *
        Math.asin(
            Math.sqrt(
                Math.pow(Math.sin(La3 / 2), 2) +
                Math.cos(La1) * Math.cos(La2) * Math.pow(Math.sin(Lb3 / 2), 2)
            )
        )
    s = s * 6378.137 //地球半径
    s = Math.round(s * 10000) / 10000
    return s
},
// 计算最近的距离
nearDistance(array, centerLatitude, centerLongitude) {
    let temp = []
    for (let i = 0, l = array.length; i < l; i++) {
        const element = array[i]
        let d = this.distance(
            element.latitude,
            element.longitude,
            centerLatitude,
            centerLongitude
        )
        temp.push(d)
    }
    this.distanceL = Math.min.apply(null, temp)
}

效果如下图:

滑动轨迹

代码如下(示例):

<map :polyline="polyline" :scale="scale" id="maps" :markers="markers" :latitude="center.latitude"
:longitude="center.longitude">
</map>
// 播放标记点
playMarkars() {
    if (this.polyline.length == 0) {
        uni.showModal({
            content: '当前时间范围内没有轨迹,无法播放!',
        })
        this.isPlay = false // 无
        this.playIndex = 0 // 第一个
        return
    }
    this.playIndex = Math.min(this.points.length - 1, this.playIndex)
    this.markers = [this.formatMarker(this.points[this.playIndex++], 'ALWAYS')]
    this.timer = setInterval(_ => {
        var i = this.playIndex++
        this.nextAdaress(i);
        if (i >= this.points.length) {
            clearInterval(this.timer)
            this.isPlay = false
            this.playIndex = 0
            this.initMarkers()
            return
        }
        this.markers = [this.formatMarker(this.points[i], 'ALWAYS')]
    }, 1000)
},

formatMarker(point, display = "BYCLICK") {
    let content = [
        "时间:" + parseTime(point.create_time),
        "运动状态:" + (point.sport == 1 ? '运动' : '静止'),
        "地址:" + point.address || ''
    ]
    return {
        id: point.id,
        iconPath: '/static/dada.png',
        width: 35,
        height: 35,
        latitude: point.latitude,
        longitude: point.longitude,
        callout: {
            display: display,
            padding: 10,
            borderRadius: 5,
            content: content.join("\n")
        }
    }
},
nextAdaress(index) {
    const len = 10;
    if (this.isGetAddress) {
        return
    }
    for (let i = 0; i < len; i++) {
        if (!this.points[i + index]) {
            break
        }
        if (this.points[i + index].address === undefined) {
            this.isGetAddress = true
            this.getAddress(i + index, len * 2, _ => {
                this.isGetAddress = false
            });
            break
        }
    }
},

图片效果如下:

vue接入腾讯地图接口

腾讯(推荐)

https://apis.map.qq.com/ws/location/v1/ip={$ip}&key={$key}

需要申请key,速度快,有基本信息

首页点击可以进行注册,申请一个获取key:

key管理,创建新密钥,填写相应信息即可
1.创建地图预览效果图如下:

<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=申请的key"></script>

 <script type="text/javascript">
    function initMap() {
        var center = new TMap.LatLng(39.984104, 116.307503);
        //初始化地图
        var map = new TMap.Map("container", {
            rotation: 20,//设置地图旋转角度
            pitch:30, //设置俯仰角度(0~45)
            zoom:12,//设置地图缩放级别
            center: center//设置地图中心点坐标
        });
    }
</script>

2.地图加载完成效果图:

<script>
    function initMap() {
        //初始化地图
        var map = new TMap.Map("container", {
            center: new TMap.LatLng(39.984104, 116.307503)
        });
        //监听地图瓦片加载完成事件
        map.on("tilesloaded", function () {
            document.getElementById("tip").innerHTML = "地图瓦片已加载完成"
        })
    }
</script>

3.异步加载地图

<script>
        function initMap() {
            var map = new TMap.Map("container", {
                pitch: 45,
                zoom: 12,
                center: new TMap.LatLng(39.984104, 116.307503)
            });
        }
        function loadScript() {
            //创建script标签,并设置src属性添加到body中
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "https://map.qq.com/api/gljs?v=1.exp&key=申请key";
            document.body.appendChild(script);
        }
        window.onload = loadScript;
    </script>

4.同时加载两个地图效果图如下:

<script>
    function initMap() {
        //初始化地图一
        var mapOne = new TMap.Map("containerOne", {
            pitch:45,
            center: new TMap.LatLng(39.984104, 116.307503)
        });
        //初始化地图二
        var mapTwo = new TMap.Map("containerTwo", {
            center: new TMap.LatLng(39.984104, 116.307503)
        });
    }
</script>

5.获取地图中心效果如下图:

<script>
    var centerInfo = document.getElementById("center-info");

    var center = new TMap.LatLng(39.984104, 116.307503);//设置中心点坐标
    //初始化地图
    var map = new TMap.Map("container", {
        center: center
    });
    //获取地图中心点事件
    function getCenter() {            
        var mapCenter = map.getCenter(); //获取地图中心点坐标
        centerInfo.innerHTML = "当前地图中心为: " + mapCenter.getLat().toFixed(6) + "," + mapCenter.getLng().toFixed(6);
    }
    //设置地图中心点事件
    function setCenter() {
        map.setCenter(new TMap.LatLng(39.908802,116.397502));//坐标为天安门
        centerInfo.innerHTML = "当前地图中心为: 39.908802,116.397502";
    }
</script>

6.地图平移效果图如下:

<script>
    function initMap() {
        var position = document.getElementById("position");
        var txt = document.getElementById("txt");
        var center = new TMap.LatLng(39.984104, 116.307503);//设置中心点坐标
        //初始化地图
        var map = new TMap.Map("container", {
            center: center
        });
        location.innerHTML = map.getCenter().toString();
        //监听地图开始平移
        map.on("panstart", function () {
            txt.innerHTML = "地图开始平移"
        })
        //监听地图平移
        map.on("pan",function(){
            txt.innerHTML = "地图正在平移";
            position.innerHTML = map.getCenter().toString();//获取地图中心点
        })
        //监听地图平移结束
        map.on("panend",function(){
            txt.innerHTML = "地图结束平移";
        })
    }
</script>

3.vue接入腾讯地图

<template>
  <div>
    <div id="map" style="width:500px;height:500px;"></div>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      longitude: "",
      latitude: ""
    };
  },
  
  methods: {
    init() {
      let address = "";
      let that = this;
      var center = new qq.maps.LatLng(34.754152, 113.667636);
      var map = new qq.maps.Map(document.getElementById('map'), {
        center: center,
        zoom: 13,
        disableDefaultUI: true
      });
      var marker = new qq.maps.Marker({
        position: center,
        map: map
      });
      var infoWin = new qq.maps.InfoWindow({
        map: map
      });
      var geocoder = new qq.maps.Geocoder({
        complete: function(res) {
          console.log(res);
          address = res.detail.nearPois[0].name;
        }
      });
      qq.maps.event.addListener(map, "click", function(event) {
        this.longitude = event.latLng.getLat();
        this.latitude = event.latLng.getLng();
        console.log(event);
        let lat = new qq.maps.LatLng(this.longitude, this.latitude);
        geocoder.getAddress(lat);
        setTimeout(() => {
          infoWin.open();
          infoWin.setContent(
            '<div style="text-align:center;white-space:nowrap;">' +
              address +
              "</div>"
          );
          infoWin.setPosition(event.latLng);
        }, 200);
      });
    }
  },
  mounted() {
    this.init();
  }
};
</script>
<style scoped>
</style>

使用前需要在index.html里引入<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=YOUR_KEY"></script>才可以使用地图。

<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=yourkey"></script>
<template>
    <div>
        <div id="container" style="width:500px;height:500px;"></div>
    </div>
</template>

<script>
    export default{
        data() {
            return {
                longitude:39.956987, // 经度
                latitude:116.235128 // 纬度
            }
        },
        mounted () {
            this.init();
        },
        methods:{
            init() {
                var myLatlng = new qq.maps.LatLng(39.945687,116.3976968);
                var myOptions = {
                  zoom: 8,               // 设置地图缩放级别
                  center: myLatlng,      // 设置中心点样式
                  mapTypeId: qq.maps.MapTypeId.ROADMAP   
                }
                var map = new qq.maps.Map(document.getElementById("container"), myOptions);
            }
        }
    }
</script>
创建地图实例
var map=new qq.maps.Map(document.getElement('container'),{
center,//坐标,即最初显示的地图中心
zoom    //缩放级别,即显示的比例
})
给地图添加事件
qq.maps.event.addListener(map,'click',function(res){
// res即点击后的位置信息
})
添加标记
var marker=new qq.maps.Marker({
position, // 标记点的位置,也可以是通过IP获取到的坐标
map, // 标记在哪个地图上
animation, // 标记显示时的动画效果
title, // 鼠标悬浮到标记上时的标题
draggable // 是否可拖拽
})
创建信息窗口
var info=new qq.maps.InfoWindow({
map, // 标记在哪个地图上
content // 信息窗口的内容
})
覆盖物
var polyline=new qq.maps.Polyline({
map, // 标记在哪个地图上
path, // 一个坐标数组,折线、多边形就是依靠这些坐标数组来成形的
strokeColor, // 折线颜色
strokeDashStyle, // 折线样式
strokeWeight, // 折线宽度
editable, // 折线是否可编辑
clickable // 是否可点击
})

单个标注点

在mounted生命周期或者从后台接口获得信息后调用初始化地图方法

initMap (latitude, longitude, message) {
    var center = new qq.maps.LatLng(latitude, longitude);
    var map = new qq.maps.Map(
        document.getElementById("container"),
        {
            center: center,
            zoom: 13
        }
    );

    var marker = new qq.maps.Marker({
        position: center,
        map: map
    });

    var info = new qq.maps.InfoWindow({
        map: map
    });
    
    // 悬浮标记显示信息
    qq.maps.event.addListener(marker, 'mouseover', function() {        
        info.open();
        info.setContent(`<div style="margin:10px;">${message}</div>`);
        info.setPosition(center);
    });
    qq.maps.event.addListener(marker, 'mouseout', function() {
        info.close();
    });
},

多个标注点

markers: [  ]; // 标记点数组

mounted () {
    this.initMap(this.markers)
},

initMap (arr) {
    // 默认以数组第一项为中心
    var center = new qq.maps.LatLng(arr[0].latitude, arr[0].longitude);
    
    var map = new qq.maps.Map(
        document.getElementById("container"),
        {
            center: center,
            zoom: 13
        }
    );
    
    // 提示窗
    var info = new qq.maps.InfoWindow({
        map: map
    });
    
    for (var i = 0; i < arr.length; i++) {
        var data = arr[i];

        var marker = new qq.maps.Marker({ 
            position: new qq.maps.LatLng(data.latitude, data.longitude), 
            map: map 
        });

        marker.id = data.id;
        marker.name = data.name;
        // 点击事件
        qq.maps.event.addListener(marker, 'mouseover', function() {
            info.open();
            // 设置提示窗内容
            info.setContent(`<div><p>${this.name}</p></div>`);
            // 提示窗位置 
            info.setPosition(new qq.maps.LatLng(this.position.lat, this.position.lng));
        });
        qq.maps.event.addListener(marker, 'mouseout', function() {
            info.close();                    
        });
    }
}

4.个性化地图样式

为什么要用个性化地图,提高不同场景下地图的展现效果和用户体验。

为什么选择腾讯位置服务个性化地图:

  • 全平台通用
  • 开发成本极小
  • 个性化样式支持动态更新
  • 支持全局配置和分级配置
  • 编辑平台UI控件全面优化
  • 每个元素可配置的属性全部开放
  • 能够支持自定义的地图元素扩充为52种

5.腾讯位置入门步骤

1.登录腾讯位置服务

2.验证手机 与 邮箱
3.申请开发密钥(Key)
4.选择您需要的产品

位置展示组件
路线规划组件
地图选点组件
前端定位组件

三.微信小程序JavaScript SDK

1.我申请了开发者密钥key
2.开通webserviceAPI服务:控制台 -> key管理 -> 设置(使用该功能的key)-> 勾选webserviceAPI -> 保存
(小程序SDK需要用到webserviceAPI的部分服务,所以使用该功能的KEY需要具备相应的权限)
日调用量:1万次 / Key----并发数:5次 / key / 秒 。

onLoad() {
    console.log('页面加载了')
    // 实例化API核心类
    qqmapsdk = new QQMapWX({
        // key: '申请的key'
    });
},
onShow() {
    console.log('页面显示了')
    // 调用接口dadaqianduan
    qqmapsdk.search({
        keyword: '酒店',
        success: (res) => {
            console.log(res);
        },
        fail: (err) => {
            console.log(err);
        },
        complete: (cres) => {
            console.log(cres);
        }
    })
},

我返回的数据如图:

QQMapWX – 小程序JavaScriptSDK核心类 – new QQMapWX(options:Object)

// 引入SDK核心类
var QQMapWX = require('xxx/qqmap-wx.js');
 
// 实例化API核心类
var demo = new QQMapWX({
    key: '开发密钥(key)' // 必填
});

地点搜索:

// 地点搜索
nearbySearchBtn() {
    qqmapsdk.search({
        keyword: 'kfc', //搜索关键词
        location: '39.980014,116.313972', //设置周边搜索中心点
        success: (res) => {
            var mks = []
            for (var i = 0; i < res.data.length; i++) {
                mks.push({ // 获取返回结果,放到mks数组中
                    title: res.data[i].title,
                    id: res.data[i].id,
                    latitude: res.data[i].location.lat,
                    longitude: res.data[i].location.lng,
                    iconPath: "/location.png", //图标路径
                    width: 20,
                    height: 20
                })
            }
            this.markers = mks
        },
        fail: (res) => {
            console.log(res);
        },
        complete: (res) => {
            console.log(res);
        }
    });
},

效果如图:

<script>
    // 引入SDK核心类,js文件根据自己业务,位置可自行放置
    // var QQMapWX = require('../../js_sdk/wxmp-qqmap/qqmap-wx-jssdk.js');
    import QQMapWX from '../../js_sdk/wxmp-qqmap/qqmap-wx-jssdk.js';
    var qqmapsdk;
    export default {
        components: {},
        data() {
            return {
                backfill: '',
                markers: [],
                suggestion: [],
            }
        },
        onLoad() {
            console.log('页面加载了') // 实例化API核心类
            qqmapsdk = new QQMapWX({ // key: '申请的key'
                key: '自己申请,我的就不放出来了'
            });
        },
        onShow() {
            console.log('页面显示了') // 调用接口dadaqianduan
            qqmapsdk.search({
                keyword: '酒店',
                success: (res) => {
                    console.log(res);
                },
                fail: (err) => {
                    console.log(err);
                },
                complete: (cres) => {
                    console.log(cres);
                }
            })
        },
        onReady() {
            console.log('页面初次渲染完成了')
        },
        methods: {
            getsuggest(e) {
                console.log(e.detail.value)
                qqmapsdk.getSuggestion({
                  keyword: e.detail.value, //用户输入的关键词,可设置固定值,如keyword:'KFC'
                  //region:'北京', //设置城市名,限制关键词所示的地域范围,非必填参数
                  success: (res) => {//搜索成功后的回调
                    console.log(res);
                    var sug = [];
                    for (var i = 0; i < res.data.length; i++) {
                      sug.push({ // 获取返回结果,放到sug数组中
                        title: res.data[i].title,
                        id: res.data[i].id,
                        addr: res.data[i].address,
                        city: res.data[i].city,
                        district: res.data[i].district,
                        latitude: res.data[i].location.lat,
                        longitude: res.data[i].location.lng
                      });
                    }
                     this.suggestion = sug
                  },
                  fail: (error)=> {
                    console.error(error);
                  },
                  complete: (res)=> {
                    console.log(res);
                  }
                });
            },
            backfillBtn(e) {
                var id = e.currentTarget.id;
                for (var i = 0; i < this.suggestion.length; i++) {
                    if (i == id) {
                        this.backfill = this.suggestion[i].title
                    }
                }
            },
            // 地点搜索
            nearbySearchBtn() {
                qqmapsdk.search({
                    keyword: 'kfc', //搜索关键词
                    location: '39.980014,116.313972', //设置周边搜索中心点
                    success: (res) => {
                        var mks = []
                        for (var i = 0; i < res.data.length; i++) {
                            mks.push({ // 获取返回结果,放到mks数组中
                                title: res.data[i].title,
                                id: res.data[i].id,
                                latitude: res.data[i].location.lat,
                                longitude: res.data[i].location.lng,
                                iconPath: "/static/location.png", //图标路径
                                width: 20,
                                height: 20
                            })
                        }
                        this.markers = mks
                    },
                    fail: (res) => {
                        console.log(res);
                    },
                    complete: (res) => {
                        console.log(res);
                    }
                });
            },
        },
        onHide() {
            console.log('页面隐藏了')
        },
    }
</script>

预览效果如图下:

<script>
    import QQMapWX from '../../js_sdk/wxmp-qqmap/qqmap-wx-jssdk.js';
    var qqmapsdk;
    export default {
        components: {},
        data() {
            return {
                backfill: '',
                markers: [],
                poi: {
                    latitude: 39.984060,
                    longitude: 16.307520
                },
            }
        },
        onLoad() {
            console.log('页面加载了') // 实例化API核心类
            qqmapsdk = new QQMapWX({ // key: '申请的key'
                key: ''
            });
        },
        onShow() {
            console.log('页面显示了')
        },
        onReady() {
            console.log('页面初次渲染完成了')
        },
        methods: {
            formSubmit(e) {
                qqmapsdk.reverseGeocoder({
                    location: e.detail.value.reverseGeo || '',
                    //获取表单传入的位置坐标,不填默认当前位置,示例为string格式
                    //get_poi: 1, //是否返回周边POI列表:1.返回;0不返回(默认),非必须参数
                    success: (res) => {
                        console.log(res);
                        var res = res.result;
                        var mks = [];
                        /**
                         *  当get_poi为1时,检索当前位置或者location周边poi数据并在地图显示,可根据需求是否使用
                         *
                            for (var i = 0; i < result.pois.length; i++) {
                            mks.push({ // 获取返回结果,放到mks数组中
                                title: result.pois[i].title,
                                id: result.pois[i].id,
                                latitude: result.pois[i].location.lat,
                                longitude: result.pois[i].location.lng,
                                iconPath: './resources/placeholder.png', //图标路径
                                width: 20,
                                height: 20
                            })
                            }
                        *
                        **/
                        //当get_poi为0时或者为不填默认值时,检索目标位置,按需使用
                        mks.push({ // 获取返回结果,放到mks数组中
                            title: res.address,
                            id: 0,
                            latitude: res.location.lat,
                            longitude: res.location.lng,
                            iconPath: '/static/location.png', //图标路径
                            width: 20,
                            height: 20,
                            callout: { //在markers上展示地址名称,根据需求是否需要
                                content: res.address,
                                color: '#000',
                                display: 'ALWAYS'
                            }
                        });
                        this.markers = mks;
                        // this.poi = {
                        //     latitude: res.location.lat,
                        //     longitude: res.location.lng
                        // }
                    },
                    fail: (error) => {
                        console.error(error);
                    },
                    complete: (res) => {
                        console.log(res);
                    }
                })
            }
        },
        onHide() {
            console.log('页面隐藏了')
        },
    }
</script>

geocoder – 提供由地址描述到所述位置坐标的转换,与逆地址解析reverseGeocoder()的过程正好相反。
预览效果如图:

formSubmit(e) {
    //调用地址解析接口
    qqmapsdk.geocoder({
      //获取表单传入地址 e.detail.value.geocoder
      address: e.detail.value, //地址参数,例:固定地址,address: '北京市海淀区彩和坊路海淀西大街74号'
      success: (res)=> {//成功后的回调
        console.log(res);
        var res = res.result;
        var latitude = res.location.lat;
        var longitude = res.location.lng;
        //根据地址解析在地图上标记解析地址位置
         this.markers = [{
            id: 0,
            title: res.title,
            latitude: latitude,
            longitude: longitude,
            iconPath: '/static/location.png',//图标路径
            width: 20,
            height: 20,
            callout: { //可根据需求是否展示经纬度
              content: latitude + ',' + longitude,
              color: '#000',
              display: 'ALWAYS'
            }
          }],
          this.poi= { //根据自己data数据设置相应的地图中心坐标变量名称
            latitude: Number(latitude),
            longitude:  Number(longitude),
          }
      },
      fail: (error)=> {
        console.error(error);
      },
      complete: (res)=> {
        console.log(res);
      }
    })
}

预览效果图如下:

formSubmit(e){
        //调用距离计算接口
        console.log(this.start,'dadaqianduan')
        qqmapsdk.calculateDistance({
            //mode: 'driving',//可选值:'driving'(驾车)、'walking'(步行),不填默认:'walking',可不填
            //from参数不填默认当前地址
            //获取表单提交的经纬度并设置from和to参数(示例为string格式)
            // from: e.detail.value.start || '', //若起点有数据则采用起点坐标,若为空默认当前地址
            from: this.start || '',
            to: this.end,
            // to: e.detail.value.dest, //终点坐标
            success: (res)=> {//成功后的回调
              console.log(res);
              var res = res.result;
              var dis = [];
              for (var i = 0; i < res.elements.length; i++) {
                dis.push(res.elements[i].distance); //将返回数据存入dis数组,
              }
              this.distance=dis
            },
            fail: (error)=> {
              console.error(error);
            },
            complete: (res)=> {
              console.log(res);
            }
        });
    }
},

调用获取城市列表接口,效果图如下:

onShow() {
    console.log('页面显示了')
    //调用获取城市列表接口
    qqmapsdk.getCityList({
        success: (res) => { //成功后的回调
            console.log(res);
            console.log('省份数据:', res.result[0]); //打印省份数据
            this.a = res.result[0]
            console.log('城市数据:', res.result[1]); //打印城市数据
            this.b = res.result[1]
            console.log('区县数据:', res.result[2]); //打印区县数据
            this.c = res.result[2]
        },
        fail: (error) => {
            console.error(error);
        },
        complete: (res) => {
            console.log(res);
        }
    });
},

获取城市区县,效果图如下:

onShow() {
    console.log('页面显示了')
    //调用获取城市列表接口
    qqmapsdk.getCityList({
        success: (res) => { //成功后的回调
            console.log(res);
            console.log('省份数据:', res.result[0])
            var city = res.result[0];
            //根据对应接口getCityList返回数据的Id获取区县数据(以北京为例)
            qqmapsdk.getDistrictByCityId({
                // 传入对应省份ID获得城市数据,传入城市ID获得区县数据,依次类推
                id: city[0].id, //对应接口getCityList返回数据的Id,如:北京是'110000'
                success: (res) => { //成功后的回调
                    console.log(res);
                    console.log('对应城市ID下的区县数据(以北京为例):', res.result[0]);
                },
                fail: (error) => {
                    console.error(error);
                },
                complete: (res) => {
                    console.log(res);
                }
            });
        },
        fail: (error) => {
            console.error(error);
        },
        complete: (res) => {
            console.log(res);
        }
    });
},

腾讯位置服务为微信小程序提供了基础的标点能力、线和圆的绘制接口等地图组件和位置展示、地图选点等地图API位置服务能力支持,使得开发者可以自由地实现自己的微信小程序产品。 在此基础上,腾讯位置服务微信小程序JavaScript SDK是专为小程序开发者提供的LBS数据服务工具包,可以在小程序中调用腾讯位置服务的POI检索、关键词输入提示、地址解析、逆地址解析、行政区划和距离计算等数据服务,让您的小程序更强大!

原文作者:程序员哆啦A梦
原文链接:https://blog.csdn.net/qq_3623...

腾讯位置服务
1.7k 声望132 粉丝

立足生态,连接未来