当前位置: 首页 > news >正文

微信小程序获取定位显示在百度地图上位置出现偏差

项目场景:

背景:

  1. 微信小程序端获取手机定位坐标,以及正确展示位置
  2. 通过详细地址解析为定位坐标显示在小程序端以及PC后台
  3. 小程序获取的地理坐标与百度地图坐标相互转化

相关知识

目前国内主要有以下三种坐标系:

  1. WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。
  2. GCJ02:又称火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
  3. BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。
    非中国地区地图,服务坐标统一使用WGS84坐标。
坐标系使用厂商
大地坐标系(WGS84)GPS定位系统及相关设备、谷歌地图
火星坐标(GCJ02)高德地图、阿里云地图、 腾讯搜搜地图 、高德MapABC地图API 、小程序百度地图
百度坐标(BD09)百度地图
图吧坐标图吧MapBar地图

问题描述

小程序端获取的坐标显示在百度地图上地理位置出现偏差:

解决问题

小程序获取的定位坐标可选type 有两种 wgs84 : gps定位坐标, gcj02: 火星定位坐标。

  • type:wgs84返回gps坐标,gcj02 返回可用于wx.openLocation的坐标;
  • altitude:传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度;
    isHighAccuracy:开启高精度定位;
  • highAccuracyExpireTime:高精度定位超时时间(ms),指定时间内返回最高精度,该值3000ms以上高精度定位才有效果;
wx.getLocation({// type: 'wgs84', // gps定位 坐标系type: 'gcj02', // 重点就是在这里,最好使用这种,对接百度小程序端地址解析 success: function(){},fail: function(){}
})
  1. 小程序端使用百度地图api 地址解析为详细地址 ,传入的坐标系需要为 gcj02类型,并不是百度坐标系
const bmap = require("../../utils/bmap-wx.js"); // 引入bmap-wx文件var BMap = new bmap.BMapWX({ak:  "你申请的小程序百度地图的ak"})BMap.regeocoding({location: res.latitude + ',' + res.longitude,  // 百度api 地址解析,使用的坐标点类型为 gcj02success: function (res) {console.log(res.originalData.result.sematic_description)},fail: function () {}})
  1. 小程序端获取的定位需要转化为百度系坐标用于后端展示,则需要通过一定的算法将gcj02转化为百度坐标,这里有写好的算法, 大家直接粘贴

WSCoordinate.js

/***  判断经纬度是否超出中国境内*/
function isLocationOutOfChina(latitude, longitude) {if (longitude < 72.004 || longitude > 137.8347 || latitude < 0.8293 || latitude > 55.8271)return true;return false;}/***  将WGS-84(国际标准)转为GCJ-02(火星坐标):*/function transformFromWGSToGCJ(latitude, longitude) {var lat = "";var lon = "";var ee = 0.00669342162296594323;var a = 6378245.0;var pi = 3.14159265358979324;if (isLocationOutOfChina(latitude, longitude)) {lat = latitude;lon = longitude;}else {var adjustLat = transformLatWithXY(longitude - 105.0, latitude - 35.0);var adjustLon = transformLonWithXY(longitude - 105.0, latitude - 35.0);var radLat = latitude / 180.0 * pi;var magic = Math.sin(radLat);magic = 1 - ee * magic * magic;var sqrtMagic = Math.sqrt(magic);adjustLat = (adjustLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);adjustLon = (adjustLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);latitude = latitude + adjustLat;longitude = longitude + adjustLon;}return { latitude: latitude, longitude: longitude };}/***  将GCJ-02(火星坐标)转为百度坐标:*/function transformFromGCJToBaidu(latitude, longitude) {  var pi = 3.14159265358979324 * 3000.0 / 180.0;var z = Math.sqrt(longitude * longitude + latitude * latitude) + 0.00002 * Math.sin(latitude * pi);var theta = Math.atan2(latitude, longitude) + 0.000003 * Math.cos(longitude * pi);var a_latitude = (z * Math.sin(theta) + 0.006);var a_longitude = (z * Math.cos(theta) + 0.0065);return { latitude: a_latitude, longitude: a_longitude };}/***  将百度坐标转为GCJ-02(火星坐标):*/function transformFromBaiduToGCJ(latitude, longitude) {var xPi = 3.14159265358979323846264338327950288 * 3000.0 / 180.0;var x = longitude - 0.0065;var y = latitude - 0.006;var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * xPi);var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * xPi);var a_latitude = z * Math.sin(theta);var a_longitude = z * Math.cos(theta);return { latitude: a_latitude, longitude: a_longitude };}/***  将GCJ-02(火星坐标)转为WGS-84:*/function transformFromGCJToWGS(latitude, longitude) {var threshold = 0.00001;// The boundaryvar minLat = latitude - 0.5;var maxLat = latitude + 0.5;var minLng = longitude - 0.5;var maxLng = longitude + 0.5;var delta = 1;var maxIteration = 30;while (true) {var leftBottom = transformFromWGSToGCJ(minLat, minLng);var rightBottom = transformFromWGSToGCJ(minLat, maxLng);var leftUp = transformFromWGSToGCJ(maxLat, minLng);var midPoint = transformFromWGSToGCJ((minLat + maxLat) / 2, (minLng + maxLng) / 2);delta = Math.abs(midPoint.latitude - latitude) + Math.abs(midPoint.longitude - longitude);if (maxIteration-- <= 0 || delta <= threshold) {return { latitude: (minLat + maxLat) / 2, longitude: (minLng + maxLng) / 2 };}if (isContains({ latitude: latitude, longitude: longitude }, leftBottom, midPoint)) {maxLat = (minLat + maxLat) / 2;maxLng = (minLng + maxLng) / 2;}else if (isContains({ latitude: latitude, longitude: longitude }, rightBottom, midPoint)) {maxLat = (minLat + maxLat) / 2;minLng = (minLng + maxLng) / 2;}else if (isContains({ latitude: latitude, longitude: longitude }, leftUp, midPoint)) {minLat = (minLat + maxLat) / 2;maxLng = (minLng + maxLng) / 2;}else {minLat = (minLat + maxLat) / 2;minLng = (minLng + maxLng) / 2;}}}function isContains(point, p1, p2) {return (point.latitude >= Math.min(p1.latitude, p2.latitude) && point.latitude <= Math.max(p1.latitude, p2.latitude)) && (point.longitude >= Math.min(p1.longitude, p2.longitude) && point.longitude <= Math.max(p1.longitude, p2.longitude));}function transformLatWithXY(x, y) {var pi = 3.14159265358979324;var lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));lat += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;lat += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;lat += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;return lat;}function transformLonWithXY(x, y) {var pi = 3.14159265358979324;var lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));lon += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;lon += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;lon += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;return lon;}module.exports = {isLocationOutOfChina: isLocationOutOfChina,transformFromWGSToGCJ: transformFromWGSToGCJ,transformFromGCJToBaidu: transformFromGCJToBaidu,transformFromBaiduToGCJ: transformFromBaiduToGCJ,transformFromGCJToWGS: transformFromGCJToWGS}
  1. 直接上代码转化 调用BMapWX.regeocoding方法进行逆地址解析(从经纬度转换为地址信息)
const utils = require("../../utils/WSCoordinate.js")
wx.getLocation({// type: 'wgs84', // gps定位 坐标系type: 'gcj02', // 重点就是在这里success: function (res) {// gcj02 转换成百度地图坐标,用于传给PC端 百度地图展示const marker = utils.transformFromGCJToBaidu(res.latitude, res.longitude)that.setData({locationFlag: false,map_latitude: marker.latitude,map_longitude: marker.longitude})BMap.regeocoding({location: res.latitude + ',' + res.longitude,success: function (res) {that.setData({desLocation: res.originalData.result.sematic_description})},fail: function () {wx.showToast({title: '请检查位置服务是否开启',})},});},fail: function () {console.log('fail:', '授权失败')}})

5 地址解析(从地址转换为坐标)

const bmap = require("../../lib/bmap-wx.js"); // 引入bmap-wx文件
const util = require('../../lib/WSCoordinate.js')  // 新建百度地图对象var BMap = new bmap.BMapWX({ak: "你的ak", // 你的ak});// 发起geocoding检索请求BMap.geocoding({address: address, // 输入详细地址            success: (data) => {  // 获取的坐标为 gcj02坐标,并不是百度坐标,需要转换为百度坐标const wxMarkerData = data.wxMarkerData[0]// 将GCJ-02(火星坐标)转为百度坐标let resultMarker = util.transformFromGCJToBaidu( wxMarkerData.latitude, wxMarkerData.longitude)// console.log(resultMarker, 'resultMarker')this.setData({latitude: resultMarker.latitude, // 纬度longitude: resultMarker.longitude // 经度})},fail: (error) => { console.log('error:', error)},
})

相关文章:

微信小程序获取定位显示在百度地图上位置出现偏差

项目场景&#xff1a; 背景&#xff1a; 微信小程序端获取手机定位坐标&#xff0c;以及正确展示位置通过详细地址解析为定位坐标显示在小程序端以及PC后台小程序获取的地理坐标与百度地图坐标相互转化 相关知识 目前国内主要有以下三种坐标系&#xff1a; WGS84&#xff1a…...

【LeetCode 0170】【哈希】两数之和(3) 数据结构设计

https://leetcode.com/problems/two-sum-iii-data-structure-design/ 描述 Design and implement a TwoSum class. It should support the following operations: add and find. add(input) – Add the number input to an internal data structure. find(value) – Find if …...

005、简单页面-容器组件

之——布局 目录 之——布局 杂谈 正文 1.布局基础知识 2.Column 3.Row 4.实践 杂谈 布局容器组件。 一个丰富的页面需要很多组件组成&#xff0c;那么&#xff0c;我们如何才能让这些组件有条不紊地在页面上布局呢&#xff1f;这就需要借助容器组件来实现。 容器组件是…...

stm32中断调用流程

USART1_IRQHandler(void)(中断服务函数) -> HAL_UART_IRQHandler(UART_HandleTypeDef *huart)(中断处理函数) -> UART_Receive_IT(UART_HandleTypeDef *huart) (接收函数) -> HAL_UART_RxCpltCallback(huart);(中断回调函数) HAL_UART_IRQHandler(UART_HandleTypeDef…...

18487.1 - 2015 电动汽车充电系统标准 第1部分 关键点梳理

一、部分知识介绍 1、连接方式 使用电缆和连接器将电动汽车接入电网&#xff08;电源&#xff09;的方法。 1.1、连接方式A 1.2、连接方式B 1.3、连接方式C 2、电动汽车控电设备 2.1、按照输出电压分类 1&#xff09;交流 单相 220V&#xff0c;三相 380V. 2&#xff09…...

WPF实战项目十八(客户端):添加新增、查询、编辑功能

1、ToDoView.xmal添加引用&#xff0c;添加微软的行为类 xmlns:i"http://schemas.microsoft.com/xaml/behaviors" 2、给项目添加行为 <i:Interaction.Triggers><i:EventTrigger EventName"MouseLeftButtonUp"><i:InvokeCommandAction Com…...

职位招聘管理与推荐系统Python+Django网页界面+协同过滤推荐算法

一、介绍 职位招聘管理与推荐系统。本系统使用Python作为主要开发语言&#xff0c;以WEB网页平台的方式进行呈现。前端使用HTML、CSS、Ajax、BootStrap等技术&#xff0c;后端使用Django框架处理用户请求。 系统创新点&#xff1a;相对于传统的管理系统&#xff0c;本系统使用…...

C#文件流二进制文件的读写

目录 一、BinaryWriter类 二、BinaryReader类 三、示例 1.源码 2.生成效果 二进制文件的写入与读取主要是通过BinaryWriter类和BinaryReader类来实现的。 一、BinaryWriter类 BinaryWriter类以二进制形式将基元类型写入流&#xff0c;并支持用特定的编码写入字符串&#…...

如何正确选择爬虫采集接口和API?区别在哪里?

在信息时代&#xff0c;数据已经成为了一个国家、一个企业、一个个人最宝贵的资源。而爬虫采集接口则是获取这些数据的重要手段之一。本文将从以下八个方面进行详细讨论&#xff1a; 1.什么是爬虫采集接口&#xff1f; 2.爬虫采集接口的作用和意义是什么&#xff1f; 3.爬虫…...

k8s部署jenkins

1.先决条件 1.因为国内的容器镜像加速器无法实时更新docker hub上的镜像资源.所以可以自己进行jenkins的容器镜像创建,. 2.这里用到了storageClass k8s的动态制备.详情参考: k8s-StoargClass的使用-基于nfs-CSDN博客 3.安装docker服务.(用于构建docker image) 2.构建jenki…...

HTTP相关

HTTP 什么是http - 蘑菇声活 http特点 1.基于TCP协议之上的应用层协议 2.基于请求--响应 3.无状态&#xff08;每次发送请求对服务端都是新的&#xff09; 4.无/短连接&#xff08;客户端不会一直跟服务端连接&#xff09; http请求协议与响应协议 请求协议 请求首行&…...

Armv8.x和Armv9.x架构扩展简介

目录 一、概述 二、Armv8.x和Armv9.x是什么意思? 三、为什么我们需要.x扩展? 四、处理器实现...

node的proxy-server使用

代理服务器是一种常见的网络工具&#xff0c;可以用来隐藏客户端的真实IP地址&#xff0c;保护客户端的隐私&#xff0c;也可以用来绕过一些网络限制&#xff0c;访问被封锁的网站。在这篇博客文章中&#xff0c;我们将讲解代理服务器的API基本使用流程和思路&#xff0c;以及代…...

FO-like Transformation in QROM Oracle Cloning

参考文献&#xff1a; [RS91] Rackoff C, Simon D R. Non-interactive zero-knowledge proof of knowledge and chosen ciphertext attack[C]//Annual international cryptology conference. Berlin, Heidelberg: Springer Berlin Heidelberg, 1991: 433-444.[BR93] Bellare M…...

Redis - 多数据源切换

问题描述 最近遇到一个 Redis 多数据源切换问题&#xff0c;不过我这个没有那么动态切换需求&#xff0c;所以就写了一种比较硬编码的方式来做『切换』 其实大概的场景是这样的&#xff1a;不同的开发环境调用 db0、生产环境调用 db1&#xff0c;但是因为业务原因&#xff0c…...

采集工具-免费采集器下载

在当今信息时代&#xff0c;互联网已成为人们获取信息的主要渠道之一。对于研究者和开发者来说&#xff0c;如何快速准确地采集整个网站数据是至关重要的一环。以下将从九个方面详细探讨这一问题。 确定采集目标 在着手采集之前&#xff0c;明确目标至关重要。这有助于确定采集…...

使用MD5当做文件的唯一标识,这样安全么?

使用MD5作为文件唯一标识符可靠么&#xff1f; 文章目录 使用MD5作为文件唯一标识符可靠么&#xff1f;什么是MD5&#xff1f;MD5的用途MD5作为文件唯一标识的优劣优势劣势 使用MD5作为文件唯一标识的建议其他文件标识算法结束语 什么是MD5&#xff1f; MD5&#xff08;Messag…...

【算法通关村】链表基础经典问题解析

【算法通关村】链表基础&经典问题解析 一.什么是链表 链表是一种通过指针将多个节点串联在一起的线性结构&#xff0c;每一个节点&#xff08;结点&#xff09;都由两部分组成&#xff0c;一个是数据域&#xff08;用来存储数据&#xff09;&#xff0c;一个是指针域&…...

【华为OD题库-056】矩阵元素的边界值-java

题目 给定一个N * M矩阵&#xff0c;请先找出M个该矩阵中每列元素的最大值&#xff0c;然后输出这M个值中的最小值 补充说明: N和M的取值范围均为: [0,100] 示例1: 输入: [[1,2],[3,4]] 输出: 3 说明: 第一列元素为:1和3&#xff0c;最大值为3 第二列元素为: 2和4&#xff0c;最…...

zabbix_sender——向zabbix交互的sdk

zabbix给我们提供了win32的交互方法。地址为src\zabbix_sender\win32\zabbix_sender.c zabbix_sender_send_values 函数声明为: int zabbix_sender_send_values(const char *address, unsigned short port, const char *source,const zabbix_sender_value_t *values...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...