700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 微信小程序 - 腾讯地图使用和选点连线计算距离

微信小程序 - 腾讯地图使用和选点连线计算距离

时间:2022-05-26 11:33:35

相关推荐

微信小程序 - 腾讯地图使用和选点连线计算距离

GitHub Demo 地址:jh-weapp-demo实现一些常用效果、封装通用组件和工具类

代码不定时更新,请前往github查看最新代码

小程序码

最近练习了下腾讯地图的使用,包含地图展示、定位、自定义标注和气泡、点聚合、拖动地图选点、逆地址解析、地图连线计算距离,标注编辑和删除,具体可扫码或在demo查看。

注意:

·6月1日发布了新的公告地理位置相关接口的调用规则公告

·因为相关接口调整,请前往github查看最新代码

增加了getFuzzyLocationgetLocation限制了调用频率,

需要在app.json中配置requiredPrivateInfos

接口调用前需申请开通(「开发」-「开发管理」-「接口设置」中自助开通该接口权限)

使用定位时注意

1、接口调用前需申请开通(「开发」-「开发管理」-「接口设置」中自助开通该接口权限)

2、requiredPrivateInfos中的模糊位置和精确位置是互斥的,即声明了模糊位置信息就无法声明精确位置信息

3、getFuzzyLocation基础库2.25.0开始支持

4、需在app.json中配置requiredPrivateInfos

"requiredPrivateInfos": ["getFuzzyLocation","chooseLocation"],"permission": {"scope.userLocation": {"desc": "你的位置信息将用于小程序定位"},"scope.userFuzzyLocation": {"desc": "你的模糊位置信息将用于小程序定位"}},

效果图

实现方式

地图展示

地图使用的是腾讯地图Map组件。官方文档

逆地址解析

逆地址解析使用的是腾讯位置服务,可以通过拿到的经纬度获取到位置的一些信息

地图选点

地图选点有两种实现方式

一种是使用小程序API wx.chooseLocation

另一种通过小程序地图选点插件

根据经纬度计算距离

计算距离有两种实现方式

一种是使用腾讯位置服务的距离算法

一种根据经纬度计算地球两个经纬度的距离(haversine公式)

注:

腾讯位置服务需要注册,使用时需要在后台配置,需要下载对应js库文件,有调用频率限制

小程序插件需要在小程序后台和小程序代码配置

经纬度计算距离

//给定的经度1,纬度1;经度2,纬度2. 计算2个经纬度之间的距离。//<returns>距离 (单位:米)</returns>//util的方法是通过读取类文件,然后通过映射获取的,所以需要在使用的page中加入//var util = require('../../../utils/util.js');相当于一个导入的过程。function distance(p1, p2) {//用haversine公式计算球面两点间的距离。//经纬度转换成弧度var lat1 = p1.latitude * Math.PI / 180;var lon1 = p1.longitude * Math.PI / 180;var lat2 = p2.latitude * Math.PI / 180;var lon2 = p2.longitude * Math.PI / 180;//差值var vLon = Math.abs(lon1 - lon2);var vLat = Math.abs(lat1 - lat2);//h is the great circle distance in radians, great circle就是一个球体上的切面,它的圆心即是球心的一个周长最大的圆。var v = Math.sin(vLat / 2);var v1 = Math.sin(vLon / 2);var h = v * v + Math.cos(lat1) * Math.cos(lat2) * v1 * v1;// 地球半径 平均值,米var distance = 2 * 6371000 * Math.asin(Math.sqrt(h));return distance;}module.exports = {//用于映射函数distance: distance,}

地图展示和逆地址解析实现代码

wxml

<!-- <map id="myMap" style="width: 100%; height: 70vh;" latitude="40.040415" longitude="116.273511" scale="17"></map> --><view class="map-container"><map id="myMap" class="map" latitude="{{latitude}}" longitude="{{longitude}}" show-location="{{isShowPosition}}" show-compass="{{isShowCompass}}" show-scale="{{isShowScale}}" markers="{{markers}}" scale="{{scale}}" bindregionchange="onMapChange" bindtap="onMapTap" bindmarkertap="onMapMarkTap" bindcallouttap="onMapCalloutTap"><!-- <cover-image class="centerImg" src="./images/ic_mark2.png" /> --><!-- 带动画 --><cover-image class="centerImg {{animation ? 'locationpicker-animation' : ''}}" src="./images/ic_mark2.png" bindanimationend="onMarkerAnimationend" /><cover-view class="locationBg" catchtap='onClickLocation'><cover-image class="locationIcon" src="./images/ic_location.png" /></cover-view></map></view><van-cell-group title="拖动地图选中的位置"><van-cell title="地址描述" label="{{address}}" /><van-cell title="位置描述" label="{{recommend}}" /><van-cell title="大致位置" label="{{rough}}" /></van-cell-group><view style="padding-top: 50px;"></view>

js

var QQMapWX = require('./lib/qqmap-wx-jssdk1.2/qqmap-wx-jssdk.min.js');var qqmapsdk;const INIT_CALLOUT = {content: '天安门广场',padding: 10,display: 'ALWAYS',anchorY: -30,bgColor: '#ffffff',anchorY: -30,fontSize: 14,textAlign: 'center',// borderWidth: 2,};const INIT_MARKER = {id: 2,latitude: 39.903734,longitude: 116.397845,iconPath: './images/Marker3_Activated@3x.png',width: '34px',height: '34px',rotate: 0,alpha: 1,callout: INIT_CALLOUT,};Page({/*** 页面的初始数据*/data: {latitude: 40.040415, // 纬度longitude: 116.273511, // 经度scale: 3, //默认16isShowScale: true,isShowCompass: true,isShowPosition: true,markers: [// 我的位置// {// id: 0,// iconPath: "./images/ic_mark1.png",// latitude: 40.040415,// longitude: 116.273511,// width: 30,// height: 30,// title: '我的位置' //点击时显示,callout存在时将被忽略// },// 其它{...INIT_MARKER},{id: 3,latitude: 40.040415,longitude: 116.273511,iconPath: './images/Marker1_Activated@3x.png',width: 30,height: 30,callout: {content: '腾讯总部大楼',padding: 10,borderRadius: 5,display: 'ALWAYS',},// 地图标记文字label: {content: '标记文字',color: '#f00',textAlign: 'center'}}],animation: false,address: '',recommend: '',rough: '',},/*** 生命周期函数--监听页面加载*/onLoad: function (options) {// 实例化API核心类// 开发文档:/miniProgram/jsSdk/jsSdkGuide/jsSdkOverviewqqmapsdk = new QQMapWX({key: '4M5BZ-ALKLU-BVXVL-B2HCC-DJSUS-WGFBH'});this.mapCtx = wx.createMapContext('myMap')// this.mapCtx.moveToLocation()// this.getCurrentLocation()// this.getCenterLngLat()// //更换定位图标。这个图标支持网络图片。// this.mapCtx.setLocMarkerIcon({// iconPath: "./images/ic_mark1.png",// })},/*** 生命周期函数--监听页面显示*/onShow: function () {},// 获取当前位置getCurrentLocation() {var that = thisconst lat = "markers[0].latitude";const log = "markers[0].longitude";// wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标wx.getLocation({type: 'gcj02',success: (res) => {console.log('当前位置');console.log(res);that.setData({latitude: res.latitude,longitude: res.longitude,[lat]: res.latitude,[log]: res.longitude});},fail: (err) => {// wx.showToast({// title: '为了不影响您的使用,请授权定位',// icon: 'none'// })}});},// 点击定位按钮onClickLocation() {var that = thisthis.setData({scale: 16,})setTimeout(() => {that.mapCtx.moveToLocation()}, 500);},// 视野发生变化时触发// 监听拖动地图,拖动结束根据中心点更新页面onMapChange(e) {if (e.type == 'end' && (e.causedBy == 'scale' || e.causedBy == 'drag')) {this.getCenterLngLat()this.setData({animation: true,});}},// 点击地图onMapTap(e) {console.log('点击地图');console.log(e);wx.showToast({title: '点击地图',icon: 'none'})},// 点击标记点时触发,e.detail = {markerId}onMapMarkTap(e) {console.log('点击标记点');console.log(e);console.log(e.detail.markerId);wx.showToast({title: '点击标记点',icon: 'none'})},// 点击标记点对应的气泡时触发e.detail = {markerId}onMapCalloutTap(e) {console.log('点击气泡');console.log(e);console.log(e.detail.markerId);wx.showToast({title: '点击标记点对应的气泡',icon: 'none'})},onMarkerAnimationend() {this.setData({animation: false});},// 获取地图中心点的经纬度getCenterLngLat: function () {var that = thisthis.mapCtx.getCenterLocation({success: function (res) {console.log('获取中间点');console.log(res);that.reverseGeocoder(res.latitude, res.longitude)}})},// 逆地址解析reverseGeocoder(latitude, longitude) {var that = thisqqmapsdk.reverseGeocoder({location: {latitude: latitude,longitude: longitude},success: function (res) {console.log('逆地址解析结果');console.log(res)var result = res.resultconsole.log(result)// 地址描述let address = result.address// 位置描述let formatted_addresses = result.formatted_addresses// 经过腾讯地图优化过的描述方式, 更具人性化特点let recommend = formatted_addresses.recommend// 大致位置, 可用于对位置的粗略描述let rough = formatted_addresses.roughconsole.log(address)console.log(recommend)console.log(rough)that.setData({address: address,recommend: recommend,rough: rough,})},});}})

地图标点连线计算距离实现代码

wxml

<view class="map-container"><map id="myMap" class="map" latitude="{{latitude}}" longitude="{{longitude}}" show-location="{{isShowPosition}}" show-compass="{{isShowCompass}}" show-scale="{{isShowScale}}" markers="{{markers}}" scale="{{scale}}" polygons="{{polygons}}" polyline="{{polyline}}" include-points="{{includePoints}}" enable-zoom bindregionchange="onMapChange" bindtap="onMapTap" bindmarkertap="onMapMarkTap" bindcallouttap="onMapCalloutTap"><!-- <cover-image class="centerImg" src="./images/ic_mark2.png" /> --><cover-view class="center-bg" catchtap="onClickAddMarkerBtn"><cover-view class="center-top">确定打标</cover-view><cover-view class="center-bottom"></cover-view></cover-view><!-- 定位按钮 --><cover-view class="locationBg" catchtap='onClickLocation'><cover-image class="locationIcon" src="./images/ic_location.png" /></cover-view><!-- 大头针中间文字 --><cover-view slot="callout"><cover-view wx:for="{{markers}}" wx:key='index' marker-id="{{item.id}}"><cover-view> {{(item.id + 1) }}</cover-view></cover-view></cover-view></map></view>

js

const util = require('./util')Page({/*** 页面的初始数据*/data: {latitude: 40.040415,longitude: 116.273511,scale: 16, //默认16isShowScale: true,isShowCompass: true,isShowPosition: true,markers: [// 我的位置// {// id: 0,// iconPath: "./images/ic_mark1.png",// latitude: 40.040415,// longitude: 116.273511,// width: 30,// height: 30,// title: '我的位置' //点击时显示,callout存在时将被忽略// },// 其它// {// id: 3,// latitude: 40.040415,// longitude: 116.273511,// iconPath: './images/Marker1_Activated@3x.png',// width: 30,// height: 30,// callout: {//content: '腾讯总部大楼',//padding: 10,//borderRadius: 5,//display: 'ALWAYS',// },// label: {//content: '标记文字',//color: '#f00',//textAlign: 'center'// }// }],curPoints: [],polyline: '', // 路线polygons: '', // 多边形includePoints: '', // 缩放视野以包含所有给定的坐标点isSelectMarker: false,selectMarkerId: '',},/*** 生命周期函数--监听页面加载*/onLoad: function (options) {this.mapCtx = wx.createMapContext('myMap')// this.mapCtx.moveToLocation()// this.getCurrentLocation()// this.getCenterLngLat()// //更换定位图标。这个图标支持网络图片。// this.mapCtx.setLocMarkerIcon({// iconPath: "./images/ic_mark1.png",// })},/*** 生命周期函数--监听页面显示*/onShow: function () {},// 获取当前位置getCurrentLocation() {var that = thisconst lat = "markers[0].latitude";const log = "markers[0].longitude";// wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标wx.getLocation({type: 'gcj02',success: (res) => {console.log('当前位置');console.log(res);that.setData({latitude: res.latitude,longitude: res.longitude,[lat]: res.latitude,[log]: res.longitude});},fail: (err) => {// wx.showToast({// title: '为了不影响您的使用,请授权定位',// icon: 'none'// })}});},// 点击定位按钮onClickLocation() {this.setData({scale: 17});setTimeout(() => {this.mapCtx.moveToLocation()}, 200);},// 视野发生变化时触发// 监听拖动地图,拖动结束根据中心点更新页面onMapChange(e) {if (e.type == 'end' && (e.causedBy == 'scale' || e.causedBy == 'drag')) {this.getCenterLngLat()if (this.data.isSelectMarker) {setTimeout(() => {this.moveMarker(this.data.selectMarkerId, this.data.latitude, this.data.longitude)}, 500);}}},// 点击地图onMapTap(e) {console.log('点击地图');console.log(e);},// 点击标记点时触发,e.detail = {markerId}onMapMarkTap(e) {console.log('点击标记点');console.log(e.detail.markerId);this.selectMarker(e.detail.markerId)},// 点击标记点对应的气泡时触发e.detail = {markerId}onMapCalloutTap(e) {console.log('点击气泡');console.log(e.detail.markerId);this.selectMarker(e.detail.markerId)},onClickAddMarkerBtn() {this.addMarker(this.data.latitude, this.data.longitude)},// 获取地图中心点的经纬度getCenterLngLat: function () {var that = thisthis.mapCtx.getCenterLocation({success: function (res) {console.log('获取中间点');console.log(res);that.setData({latitude: res.latitude,longitude: res.longitude,});}})},// 编辑或删除选中标记selectMarker(markerId) {let tempMarkers = this.data.markerstempMarkers.forEach(function (item, index) {item.iconPath = "./images/ic_mark1.png"item.isSelect = falseif (index == markerId) {item.isSelect = !item.isSelectitem.iconPath = item.isSelect ? './images/Marker1_Activated@3x.png' : "./images/ic_mark1.png"}});let marker = this.data.markers[markerId]this.setData({latitude: marker.latitude,longitude: marker.longitude,markers: tempMarkers,isSelectMarker: true,selectMarkerId: markerId,});var that = thiswx.showModal({title: '是否删除该标记点?',content: '确认将删除,取消可拖动地图更新标记点位置',success(res) {if (res.confirm) {console.log('用户点击确定')that.deleteMarker(markerId)} else if (res.cancel) {console.log('用户点击取消')}}})},cancelMarker() {let tempMarkers = this.data.markerstempMarkers.forEach(function (item, index) {item.iconPath = "./images/ic_mark1.png"item.isSelect = false});this.setData({markers: tempMarkers,isSelectMarker: false,selectMarkerId: "",});},// 添加一个标记点addMarker(latitude, longitude) {// 判断是否存在,相同经纬度不再添加let isExist = falsethis.data.markers.forEach(item => {if (item.latitude == latitude && item.longitude == longitude) {console.log('已存在,相同经纬度不再添加');isExist = truereturn}});if (isExist == true) {return}// 不存在。新增var mark = new Object(); //声明一个mark对象mark.id = this.data.markers.length;mark.longitude = longitude; //经度mark.latitude = latitude;mark.iconPath = "./images/ic_mark1.png";mark.width = 40;mark.height = 40;// mark.label = {// fontSize: 14,// anchorX: 0,// anchorY: -35,// content: mark.id + '',// textAlign: 'center',// color: '#000000',// }// mark.callout = {// content: '腾讯总部大楼',// padding: 10,// borderRadius: 5,// display: 'ALWAYS',// }// 自定义气泡窗口mark.customCallout = {anchorX: 0,anchorY: 25,display: 'ALWAYS',}mark.isSelect = falsethis.data.markers.push(mark)this.setData({markers: this.data.markers})// 在data中声明一个curPoints 来记录点击所有的点,在完成绘制的时候清空点。this.data.curPoints.push({longitude: longitude,latitude: latitude})// 添加线上的超过一个的点,每次把距离叠加上去if (this.data.curPoints.length > 1) {// console.log(this.data.curPoints)// 地图上用的polyline是一个线集合对象,如果只放一条线是无法看见的。var pl = [{points: this.data.curPoints,color: "#0066FF",width: 2,dottedLine: false,}];//更改界面数据this.setData({polyline: pl})}// 计算距离this.calculateDistance()},// 编辑标记点(移动位置)moveMarker(markerId, latitude, longitude) {console.log('编辑标记点(移动位置)');this.mapCtx.translateMarker({// 要平移的marker的idmarkerId: markerId,// 移动过程中是否自动旋转 markerautoRotate: false,// 动画持续时长,平移与旋转分别计算duration: 10,// 平移到的目的地,参数为经纬度destination: {latitude: latitude,longitude: longitude,},//平移动画后的回调函数animationEnd() {}})let tempMarkers = this.data.markerslet marker = this.data.markers[markerId]let curPoints = this.data.curPointscurPoints.forEach(function (item, index) {if (item.latitude == marker.latitude && item.longitude == marker.longitude) {curPoints.splice(index, 1, {longitude: longitude,latitude: latitude})}});tempMarkers[markerId].latitude = latitudetempMarkers[markerId].longitude = longitude// 地图上用的polyline是一个线集合对象,如果只放一条线是无法看见的。var pl = [{points: curPoints,color: "#0066FF",width: 2,dottedLine: false,}];this.setData({polyline: curPoints.length > 1 ? pl : '',curPoints: curPoints,markers: tempMarkers,})// 计算距离this.calculateDistance()// 移动结束取消选中this.cancelMarker()},// 删除一个标记点deleteMarker(markerId) {let tempMarkers = this.data.markerslet delMarker = tempMarkers[markerId]// console.log(delMarker);if (tempMarkers.length > markerId) {// 删除tempMarkers.splice(markerId, 1)// 重新排序,设置顺序tempMarkers.forEach(function (item, index) {item.id = index});let curPoints = this.data.curPointscurPoints.forEach(function (item, index) {if (item.latitude == delMarker.latitude && item.longitude == delMarker.longitude) {curPoints.splice(index, 1)}});// 地图上用的polyline是一个线集合对象,如果只放一条线是无法看见的。var pl = [{points: curPoints,color: "#0066FF",width: 2,dottedLine: false,}];this.setData({polyline: curPoints.length > 1 ? pl : '',curPoints: curPoints,markers: tempMarkers})// 计算距离this.calculateDistance()}},// 每次更新markers之后重新计算距离calculateDistance() {// this.calculateEachDistance()this.calculateAllDistance()},// 计算两个点之间的距离,个数大于1每个点下都显示距离,不显示总距离calculateEachDistance() {let curPoints = this.data.curPointsif (curPoints.length > 1) {var p2 = curPoints[curPoints.length - 1]var p1 = curPoints[curPoints.length - 2]// console.log(p1);// console.log(p2);let dis = 0dis += util.distance(p1, p2);let datas = Number(dis); //转为字符串let datas2 = datas.toFixed(2) + "米"; //保留两位小数var x = -(datas2.length * 1) //设置文字向左偏移let label = {fontSize: 14,anchorX: x,anchorY: 0,content: datas2,textAlign: 'center',color: '#000000',}let last = "markers[" + (this.data.markers.length - 1) + "].label";this.setData({[last]: label})} else if (curPoints.length == 1) {let label = {fontSize: 14,anchorX: x,anchorY: 0,content: '',textAlign: 'center',color: '#000000',}this.setData({['markers[0].label']: label})}},// 计算所有点之间的总距离,按添加顺序依次计算两点之间距离,并在最后一个点上显示总距离calculateAllDistance() {// 添加线上的超过一个的点,每次把距离叠加上去let curPoints = this.data.curPointsif (curPoints.length > 1) {let dis = 0curPoints.forEach(function (item, index) {if (index < (curPoints.length - 1)) {var p1 = curPoints[index]var p2 = curPoints[index + 1]dis += util.distance(p1, p2);}});let datas = Number(dis); //转为字符串let datas2 = datas.toFixed(2) + "米"; //保留两位小数var x = -(datas2.length * 1) //设置文字向左偏移let label = {fontSize: 14,anchorX: x,anchorY: 0,content: datas2,textAlign: 'center',color: '#000000',}let last2 = "markers[" + (this.data.markers.length - 2) + "].label";let last = "markers[" + (this.data.markers.length - 1) + "].label";this.setData({[last2]: {},[last]: label})} else if (curPoints.length == 1) {let label = {fontSize: 14,anchorX: x,anchorY: 0,content: '',textAlign: 'center',color: '#000000',}this.setData({['markers[0].label']: label})}}})

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。