收藏
回答

addGroundOverlay加载瓦片地图在ios设备上可以显示,但是在安卓上不行

框架类型 问题类型 API/组件名称 终端类型 微信版本 基础库版本
小程序 Bug addGroundOverlay 微信安卓客户端 8.0.58 3.8.3
import util from "@/common/util.js";
import conf from "@/common/config.js"
export default {
    data() {
        return {
            mapCtx: null,
            // 地图中心
            mapCenter: {
                longitude: 117.4897043557885,
                latitude: 30.08812622949965,
            },
            // 地图边界,这里使用矩形边界
            bounds: {
                northEast: {
                    latitude: 30.0927032267595,
                    longitude: 117.495632609787
                },
                southWest: {
                    latitude: 30.0835492322398,
                    longitude: 117.48377610179
                }
            },
            // 我的位置
            myLocation: {
                longitude: 0,
                latitude: 0,
            },
            scale: 17, // 初始缩放级别
            minScale: 17, // 最小缩放级别
            maxScale: 20, // 最大缩放级别
            tileSize: 256, // 瓦片图分辨率,通常为256x256像素
            tileCache: [], // 缓存需要加载的瓦片图 URL
            showLocation: false, // 显示当前定位
            enablePoi: false, // 是否展示 POI 点
            markerInfo: {}, //当前选择基础设施
            markers: [], // 地图标注集合
            linePoints: [], // 路线点集
            gridSize: 30, // 聚合算法的可聚合距离,即距离小于该值的点会聚合至一起,以像素为单位
            scenicLimit: 10, //景区范围阈值
            spotLimit: 10, //景区范围阈值
            isAutoGuide: false, //开启导游
        }
    },
    computed: {
        markerIds() {
            return this.markers.map(v => v.id)
        },
        polyline() {
            return [{
                color: '#61afef',
                width: 10,
                points: this.linePoints
            }]
        },
        showLines() {
            return this.linePoints.length
        }
    },
    methods: {
        initMap() {
            this.mapCtx = uni.createMapContext('customMap')
            // 开启点聚合
            this.mapCtx.initMarkerCluster({
                gridSize: this.gridSize
            })
            // 加载手绘地图
            this.loadTileMap(this.scale)
        },
        // 我的位置
        setLocation(showLocation) {
            uni.getLocation({
                type: 'gcj02',
                success: (res) => {
                    const {
                        latitude,
                        longitude
                    } = res;
                    // 计算当前位置是否在景区范围,在-显示我的位置并将地图中心点修改我的位置,不在-只显示我的位置
                    const distance = util.GetDistance(longitude, latitude, this.mapCenter.longitude, this.mapCenter
                        .latitude);
                    this.myLocation.longitude = longitude
                    this.myLocation.latitude = latitude
                    if (distance < this.scenicLimit) {
                        this.mapCenter.longitude = longitude
                        this.mapCenter.latitude = latitude
                    } else {
                        this.showToast('您当前不在景区范围内!')
                    }
                }
            });
            if (showLocation) {
                this.showLocation = false
            } else {
                this.showLocation = true
            }
        },
        onRegionChange(e) {
            if (e.type === 'end') {
                const scale = Math.round(e.detail.scale)
                setTimeout(() => {
                    
                    this.loadTileMap(scale)
                }, 300);
                // 边界限制
                this.checkMapBounds(e.detail.centerLocation)
            }
        },
        // 地图边界限制
        checkMapBounds(center) {
            const {
                latitude,
                longitude
            } = center;
            // 处理逻辑
            // 检查地图中心是否超出边界
            if (
                latitude < this.bounds.southWest.latitude ||
                latitude > this.bounds.northEast.latitude ||
                longitude < this.bounds.southWest.longitude ||
                longitude > this.bounds.northEast.longitude
            ) {
                console.log(latitude+','+longitude,'-------',this.mapCenter.latitude+','+this.mapCenter.longitude)
                // 如果超出边界,将地图中心移动到原中心
                this.mapCtx.moveToLocation({
                    latitude: this.mapCenter.latitude,
                    longitude: this.mapCenter.longitude,
                    success: () => {},
                    fail: (err) => {}
                });
            }
        },
        loadTileMap(scale) {
            this.mapCtx.getRegion({
                success: (res) => {
                    const {
                        northeast,
                        southwest
                    } = res;
                    // 计算需要加载的瓦片图行列号范围
                    const minX = this.lngToTileX(southwest.longitude, scale);
                    const maxX = this.lngToTileX(northeast.longitude, scale);
                    const minY = this.latToTileY(northeast.latitude, scale);
                    const maxY = this.latToTileY(southwest.latitude, scale);


                    const tileUrls = [];
                    for (let x = minX; x <= maxX; x++) {
                        for (let y = minY; y <= maxY; y++) {
                            const bounds = this.getTileBounds(x, y, scale)
                            // 这里需要替换为实际的瓦片图 URL 模板
                            const url =
                                `${conf.mapurl}/${scale}/${x}_${y}.png`;
                            tileUrls.push({
                                url,
                                bounds,
                                id: Date.now()
                            });
                        }
                    }
                    // 加载并显示瓦片图
                    this.loadAndDrawTiles(tileUrls);
                },
                fail: (err) => {
                    console.error('获取地图范围失败:', err);
                }
            });
        },
        // 经度转列号
        lngToTileX(lng, zoom) {
            return Math.floor((lng + 180) / 360 * Math.pow(2, zoom));
        },
        // 纬度转行号
        latToTileY(lat, zoom) {
            const latRad = lat * Math.PI / 180;
            return Math.floor((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * Math.pow(2,
                zoom));
        },
        // 获取瓦片图边界
        getTileBounds(tileX, tileY, zoom) {
            const {
                tileSize
            } = this;
            // 计算当前瓦片在地图中的像素坐标
            const xPixel = tileX * tileSize;
            const yPixel = tileY * tileSize;
            // 计算地图左上角和右下角的像素坐标
            const left = xPixel;
            const top = yPixel;
            const right = xPixel + tileSize;
            const bottom = yPixel + tileSize;
            // 将像素坐标转换为经纬度坐标
            const nw = this.pixelToLatLng(left, top, zoom);
            const se = this.pixelToLatLng(right, bottom, zoom);
            return {
                southwest: {
                    longitude: nw.lng,
                    latitude: se.lat
                },
                northeast: {
                    longitude: se.lng,
                    latitude: nw.lat
                }
            };
        },
        // 像素坐标转经纬度坐标
        pixelToLatLng(x, y, zoom) {
            const n = Math.PI - (2 * Math.PI * y) / Math.pow(2, zoom + 8);
            return {
                lat: (180 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))),
                lng: (x / Math.pow(2, zoom + 8)) * 360 - 180
            };
        },
        // 瓦片地图加载
        loadAndDrawTiles(tileUrls) {
            console.log(tileUrls,'tileUrls')
            const cache = this.tileCache.slice(0)
            if (cache && cache.length > 0) {
                tileUrls.forEach((mp) => {
                    this.mapCtx.removeGroundOverlay({
                        id: mp.id,
                        success: (res) => {},
                        fail: (res) => {},
                    })
                })
            }
            this.tileCache = []
            tileUrls.forEach((mp) => {
                this.mapCtx.addGroundOverlay({
                    id: mp.id,
                    src: mp.url,
                    bounds: mp.bounds,
                    zIndex: 9,
                    success: (res) => {console.log(res,'success')},
                    fail: (res) => {console.log(res,'fail')},
                    complete: () => {
                        this.tileCache.push(mp)
                    }
                });
            })
        },
        setMarkers(points, mapIcon) {
            this.markers = []
            if (points && points.length > 0) {
                setTimeout(() => {
                    const ps = [...points]
                    ps.forEach((p, i) => {
                        const [longitude, latitude] = util.bMapToQQMap(p.lon, p.lat);
                        this.markers.push(
                            Object.assign({}, {
                                id: Number(p.id),
                                iconPath: mapIcon,
                                width: 36,
                                height: 43,
                                joinCluster: true, // 指定了该参数才会参与聚合
                                label: {
                                    fontSize: 10,
                                    padding: 5,
                                    borderWidth: 1,
                                    borderRadius: 10,
                                    textAlign: 'center',
                                    bgColor: '#ffffff',
                                    content: p.title
                                },
                                longitude,
                                latitude,
                                info: p
                            })
                        )
                    })
                    this.setIncludePoints()
                }, 300)
            }
        },
        // 
        setIncludePoints() {
            // 收集所有 markers 的经纬度
            let points = this.markers.map(marker => {
                return {
                    latitude: marker.latitude,
                    longitude: marker.longitude
                }
            });
            // 边界点
            // points.push(this.bounds.northEast)
            // points.push(this.bounds.southWest)
            this.mapCtx.includePoints({
                points: points,
                success: (res) => {
                    console.log('所有 markers 已居中显示', res);
                },
                fail: (err) => {
                    console.error('居中显示 markers 失败:', err);
                }
            });
        },
        // 路线标记
        setPolyline(points) {
            if (points.length > 0) {
                const ps = [...points]
                this.linePoints = ps.map((p, i) => {
                    const {
                        lon,
                        lat
                    } = p
                    const [longitude, latitude] = util.bMapToQQMap(p.lon, p.lat);
                    return {
                        longitude,
                        latitude,
                    }
                })
            }
        },
        // 点击标注
        clickMarker(e) {
            const target = this.markers.find(v => v.id == e.markerId)
            this.markerInfo = target ? target.info : {};
            this.openPopup('markerPopup')
        },
        // 开启导游(边走边听)
        handleGuide(isAutoGuide) {
            const _this = this
            if (!isAutoGuide) {
                uni.showModal({
                    title: '提示',
                    content: '启动后,小程序会在接近景点时,自动进行讲解!',
                    success: function(res) {
                        if (res.confirm) {
                            // 开启
                            _this.isAutoGuide = true
                            uni.authorize({
                                scope: 'scope.userLocation',
                                success: () => {
                                    // 授权成功,开启实时位置更新
                                    uni.startLocationUpdate({
                                        success: () => {
                                            console.log('开启位置更新成功,开始记录行程');
                                            uni.onLocationChange(_this.checkSpotLimit)
                                        },
                                        fail: (err) => {
                                            console.error('开启位置更新失败:', err);
                                        },


                                    });
                                },
                                fail: (err) => {
                                    console.error('获取地理位置授权失败:', err);
                                }
                            });
                        }
                    }
                });


            } else {
                uni.showModal({
                    title: '提示',
                    content: '关闭自动导游!',
                    success: function(res) {
                        if (res.confirm) {
                            // 关闭
                            _this.isAutoGuide = false
                            uni.authorize({
                                scope: 'scope.userLocation',
                                success: () => {
                                    // 授权成功,关闭实时位置更新
                                    uni.stopLocationUpdate({
                                        success: () => {
                                            console.log('关闭位置更新成功');
                                        },
                                        fail: (err) => {
                                            console.error('关闭位置更新失败:', err);
                                        },
                                        complete: () => {
                                            _this.stopAudio()
                                            uni.offLocationChange(_this.checkSpotLimit)
                                        }
                                    });
                                },
                                fail: (err) => {
                                    console.error('获取地理位置授权失败:', err);
                                }
                            });
                        }
                    },
                })
            }
        },
        // 计算当前位置是否在景点范围内
        checkSpotLimit(res) {
            console.log(res, '实时位置信息')
            const {
                longitude,
                latitude
            } = res
            if (this.spotList && this.spotList.length > 0) {
                const newSpotList = this.spotList.map((p) => {
                    p.distance = util.GetDistance(longitude, latitude, p.lon, p.lat);
                    return p
                })
                // 按distance进行升序排列
                newSpotList.sort(function(a, b) {
                    return a.distance - b.distance
                })
                const sd = newSpotList[0]
                if (sd.distance <= this.spotLimit) {
                    // 播报
                    this.audioPlay(sd, sd['chineseVoice'])
                }
            }
        }


    }
}
回答关注问题邀请回答
收藏

1 个回答

  • 遵纪守法好公民
    遵纪守法好公民
    2025-05-07

    真机调试以后发现这个方法直接失败了,这个是因为什么啊,也没有报错信息,就直接进了失败的回调,也没有报错信息

    2025-05-07
    有用
    回复 1
    • 言恒
      言恒
      2025-11-10
      你的地图瓦片是怎么切的呢
      2025-11-10
      回复
登录 后发表内容