uniapp-地图定位

<template>
  <view>
    <map
      style="width: 100vw; height: 100vh;"
      :latitude="latitude"
      :longitude="longitude"
      :scale="scale"
      :markers="markers"
    ></map>
  </view>
</template>

<script>
export default {
  data() {
    return {
      latitude: 39.909, // 默认定在首都
      longitude: 116.39742,
      scale: 12, // 默认16
      markers: [],
      markerHeight: 30,
    };
  },
  methods: {
    //   初次位置授权
    getAuthorize() {
      return new Promise((resolve, reject) => {
        uni.authorize({
          scope: "scope.userLocation",
          success: () => {
            resolve(); // 允许授权
          },
          fail: () => {
            reject(); // 拒绝授权
          },
        });
      });
    },
    // 确认授权后,获取用户位置
    getLocationInfo() {
      const that = this;
      uni.getLocation({
        type: "gcj02",
        success: function (res) {
          // 暂时
          that.longitude = res.longitude; //118.787575;
          that.latitude = res.latitude; //32.05024;
          that.markers = [
            {
              id: "",
              latitude: res.latitude,
              longitude: res.longitude,
              iconPath: "../../static/mark.png",
              width: that.markerHeight, //宽
              height: that.markerHeight, //高
            },
          ];
          that.getList();
        },
      });
    },
    // 拒绝授权后,弹框提示是否手动打开位置授权
    openConfirm() {
      return new Promise((resolve, reject) => {
        uni.showModal({
          title: "请求授权当前位置",
          content: "我们需要获取地理位置信息,为您推荐附近的美食",
          success: (res) => {
            if (res.confirm) {
              uni.openSetting().then((res) => {
                if (res[1].authSetting["scope.userLocation"] === true) {
                  resolve(); // 打开地图权限设置
                } else {
                  reject();
                }
              });
            } else if (res.cancel) {
              reject();
            }
          },
        });
      });
    },
    // 彻底拒绝位置获取
    rejectGetLocation() {
      uni.showToast({
        title: "你拒绝了授权,无法获得周边信息",
        icon: "none",
        duration: 2000,
      });
    },
    getList() {
      console.log("获取周围美食");
    },
  },
  onReady() {
    //   wx请求获取位置权限
    this.getAuthorize()
      .then(() => {
        //   同意后获取
        this.getLocationInfo();
      })
      .catch(() => {
        //   不同意给出弹框,再次确认
        this.openConfirm()
          .then(() => {
            this.getLocationInfo();
          })
          .catch(() => {
            this.rejectGetLocation();
          });
      });
  },
};
</script>
### 解决 uniapp 中 `uni.getLocation` 定位偏差的方案 在 UniApp 中,`uni.getLocation` 的定位偏差问题可能由多种因素引起,包括坐标系选择、定位精度设置以及缓存数据等。以下为解决定位偏差的具体方法: #### 1. **选择合适的坐标系** `uni.getLocation` 支持两种坐标系:`wgs84` 和 `gcj02`。其中: - `wgs84` 是全球标准坐标系,但其精度较低,仅能提供粗略的经纬度[^2]。 - `gcj02` 是国测局坐标系,精度较高,适用于国内应用,并且支持解析地址信息(需配置三方定位 SDK)[^2]。 因此,推荐使用 `gcj02` 坐标系以获得更高的定位精度。 #### 2. **开启高精度定位** 在调用 `uni.getLocation` 时,可以设置参数 `isHighAccuracy` 为 `true`,以启用高精度定位模式。例如: ```javascript uni.getLocation({ type: 'gcj02', isHighAccuracy: true, success: function (res) { console.log('经度:' + res.longitude); console.log('纬度:' + res.latitude); }, fail: function (err) { console.error('定位失败:', err); } }); ``` 高精度定位需要设备支持 GPS 或网络辅助定位[^4]。 #### 3. **避免缓存导致的偏差** `uni.getLocation` 是一次性定位接口,频繁调用可能会返回缓存数据,从而导致定位偏差。建议使用 `uni.onLocationChange` 实现实时监听位置变化。例如: ```javascript uni.startLocationUpdate({ type: 'gcj02', success(res) { console.log('开始监听位置变化'); }, fail(err) { console.error('监听失败:', err); } }); uni.onLocationChange(function (res) { console.log('实时纬度:' + res.latitude); console.log('实时经度:' + res.longitude); }); ``` 这种方式能够确保获取到最新的位置信息,减少因缓存导致的偏差[^3]。 #### 4. **处理坐标偏移** 如果定位结果仍然存在偏差,可以手动对坐标进行偏移校正。以下是一个简单的偏移计算示例: ```javascript function addOffset(longitude, latitude) { const x_pi = (3.14159265358979324 * 3000.0) / 180.0; const z = Math.sqrt(longitude * longitude + latitude * latitude) + 0.00002 * Math.sin(latitude * x_pi); const theta = Math.atan2(latitude, longitude) + 0.000003 * Math.cos(longitude * x_pi); const lngs = z * Math.cos(theta) + 0.0065; const lats = z * Math.sin(theta) + 0.006; return { lng: lngs, lat: lats }; } uni.getLocation({ type: 'gcj02', success: function (res) { const { lng, lat } = addOffset(res.longitude, res.latitude); console.log('加偏移后经度:' + lng); console.log('加偏移后纬度:' + lat); }, fail: function (err) { console.error('获取定位失败:', err.errMsg); } }); ``` 该方法通过数学公式调整坐标值,进一步提高定位精度。 #### 5. **配置三方定位 SDK** 如果需要更精确的定位,可以引入第三方地图 SDK(如高德地图)。例如,在使用 `gcj02` 坐标系时,需确保 App 平台已正确配置三方定位 SDK。具体配置步骤可参考相关文档。 --- ### 注意事项 - 确保设备已开启 GPS 和网络定位功能。 - 在 H5 平台上,`gcj02` 模式需要额外配置定位 SDK 信息。 - 使用高德地图 API 时,需申请 Web 服务 API 类型 Key[^2]。 --- ### 示例代码 以下为封装后的 `getLocation` 工具函数,结合上述解决方案: ```javascript export function getLocation() { return new Promise((resolve, reject) => { uni.getLocation({ type: 'gcj02', isHighAccuracy: true, success: (res) => { // 处理坐标偏移 const { lng, lat } = addOffset(res.longitude, res.latitude); resolve({ longitude: lng, latitude: lat }); }, fail: (err) => { reject(err); } }); }); } function addOffset(longitude, latitude) { const x_pi = (3.14159265358979324 * 3000.0) / 180.0; const z = Math.sqrt(longitude * longitude + latitude * latitude) + 0.00002 * Math.sin(latitude * x_pi); const theta = Math.atan2(latitude, longitude) + 0.000003 * Math.cos(longitude * x_pi); const lngs = z * Math.cos(theta) + 0.0065; const lats = z * Math.sin(theta) + 0.006; return { lng: lngs, lat: lats }; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值