2、app端由于本身自带的定位不太准确,使用了高德的key(key需要自己申请),并且用了gcoord来转换坐标系
3、由于app端的地图限制,以下涉及地图的方法是写在视图层的,即在里面,而不是在逻辑层里面
2、缩放到地图中间(zoomMapToPoint)或者地图上半部分(zoomMapToPointTop)
在地图基础框架已经搭好的前提下,即window._map已存在
注:app端只测试了安卓系统,不知道ios是否适用
一、实现逻辑
1、点击定位按钮,调用locatedRender方法
2、app端由于本身自带的定位不太准确,用了原生方法plus.geolocation.watchPosition,并用了高德的key(key需要自己申请),且用了gcoord来转换坐标系
连续定位,uniapp官方(https://uniapp.dcloud.net.cn/api/location/location-change.html)也有对应的方法,但是在我本地实测,会出现延迟的情况,就是走了好几米,但是定位还是不动,不实时变化,会在10~30秒后,定位跳一下
3、由于app端的地图限制,以下涉及地图的方法是写在视图层的,即在<script module="maptalksJS" lang="renderjs"></script>里面,而不是在逻辑层<script></script>里面
我这儿主要是为了做app端,只是作了h5的兼容,如果只是h5,正常在<script></script>里面写就行
html
this.locationlayer = new maptalks.VectorLayer('locationLayer').addTo(window._map);
/**
* 定位用户当前位置
*/
locatedRender() {
if (this.point.length > 0) {
// 放大到当前用户位置(地图上半部分)
// zoomMapToPointTop(window._map, this.point);
// 放大到当前用户位置(居中位置)
zoomMapToPoint(window._map, this.point);
// 在地图上创建标记
createMarker(window._map, this.locationlayer, this.point[0], this.point[1], false);
} else {
// 启动位置追踪
this.startTrackingWz();
}
},
/**
* 启动追踪用户位置
*/
startTrackingWz() {
// #ifdef APP-PLUS
this.watchId = trackUserLocationApp(
position => {
// 使用 gcoord 转换 → WGS84
const wgs84 = gcoord.transform(
[position.coords.longitude, position.coords.latitude], // 必须是 [经度, 纬度]
gcoord.GCJ02, // 来源坐标系
gcoord.WGS84 // 目标坐标系
)
this.point = wgs84
if (this.point && this.dwOpen == false) {
// zoomMapToPointTop(window._map, this.point);
zoomMapToPoint(window._map, this.point);
this.dwOpen = true
}
createMarker(window._map, this.locationlayer, this.point[0], this.point[1], false); // 在地图上添加标记
},
error => {
console.error('追踪用户位置出错', error);
}
);
// #endif
// #ifdef H5
this.watchId = trackUserLocation(
position => {
this.point = [position.coords.longitude, position.coords.latitude];
if (this.point && this.dwOpen == false) {
// zoomMapToPointTop(window._map, this.point);
zoomMapToPoint(window._map, this.point);
this.dwOpen = true
}
createMarker(window._map, this.locationlayer, this.point[0], this.point[1], false); // 在地图上添加标记
},
error => {
console.error('追踪用户位置出错', error);
}
);
// #endif
},
/**
* 清除位置追踪
*/
watchIdClearRender(){
if(this.watchId){
// #ifdef APP-PLUS
plus.geolocation.clearWatch(this.watchId);
// #endif
// #ifdef H5
navigator.geolocation.clearWatch(this.watchId);
// #endif
}
},
二、引用的方法
1、在地图上创建点标记(createMarker)
html
/**
* 在地图上创建标记
* @param {Object} map 地图实例
* @param {Object} locationLayer 标注图层
* @param {number} lng 经度
* @param {number} lat 纬度
* @param {boolean} isZoom 是否缩放到该点
*/
export const createMarker = (map, locationLayer, lng, lat, isZoom = false, oldMarker = null) => {
const marker = new maptalks.Circle([lng, lat], 0, {
symbol: {
markerType: 'ellipse',
markerWidth: 10,
markerHeight: 10,
markerFill: 'red',
markerLineColor: '#fff',
markerLineWidth: 2,
opacity: 1
}
});
const markerCenter = new maptalks.Marker([lng, lat], {
symbol: {
markerType: 'ellipse',
markerWidth: 10,
markerHeight: 10,
markerFill: 'red',
markerLineColor: '#fff',
markerLineWidth: 2
}
});
locationLayer.clear();
locationLayer.addGeometry(marker);
locationLayer.addGeometry(markerCenter);
if (isZoom) {
map.setZoom(18);
map.setCenter([lng, lat]);
}
animateRipple(marker);
};
/**
* 为标记添加波纹动画效果
* @param {Object} marker 标记实例
*/
const animateRipple = (marker) => {
const maxMarkerSize = 40;
const minMarkerSize = 10;
const duration = 1500;
let startTime = null;
function animate(timestamp) {
if (!startTime) startTime = timestamp;
const progress = timestamp - startTime;
const scaleFactor = progress / duration;
const currentSize = minMarkerSize + (maxMarkerSize - minMarkerSize) * scaleFactor;
const currentOpacity = 1 - scaleFactor;
marker.updateSymbol({
markerWidth: currentSize,
markerHeight: currentSize,
opacity: currentOpacity
});
if (progress >= duration) {
startTime = timestamp;
}
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
};
2、缩放到地图中间(zoomMapToPoint)或者地图上半部分(zoomMapToPointTop)
html
/**
* 缩放地图到指定坐标(居中定位)
* @param {Object} map 地图实例
* @param {Array} coordinates 坐标数组
*/
export const zoomMapToPoint = (map, coordinates) => {
map.animateTo({
center: coordinates,
zoom: 18,
pitch: 0,
bearing: 0
}, {
duration: 1500,
easing: 'out'
});
};
/**
* 缩放地图到指定坐标(定位到地图的上半部分)
* @param {Object} map 地图实例
* @param {Array} coordinates 坐标数组
*/
export const zoomMapToPointTop = (map, coordinates) => {
map.animateTo({
center: coordinates,
zoom: 18,
pitch: 0,
bearing: 0
}, {
duration: 1500,
easing: 'out'
});
setTimeout(() => {
//计算需要向上平移的像素距离( 例如, 向上平移 1/3 地图高度)
const mapSize = map.getSize();
const dy = mapSize.height * -0.3; // 向上平移 1/3 高度
// 平移地图
map.panBy([0, dy], {
animation: {
duration: 1000
}
});
}, 1500); // 等待1500ms
};
3、追踪用户位置
html
/**
* 追踪用户位置:h5
* @param {function} successCallback 成功获取位置的回调
* @param {function} errorCallback 失败回调
*/
export const trackUserLocation = (successCallback, errorCallback) => {
if (navigator.geolocation) {
return navigator.geolocation.watchPosition(successCallback, errorCallback, {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
});
} else {
console.log('浏览器不支持地理位置。');
}
};
/**
* 追踪用户位置:app
* @param {function} successCallback 成功获取位置的回调
* @param {function} errorCallback 失败回调
*/
export const trackUserLocationApp = (successCallback, errorCallback) => {
if (plus.geolocation) {
return plus.geolocation.watchPosition(successCallback, errorCallback, {
provider: 'amap', // 强制高德(关键!)
type: 'gcj02', // 高德坐标系
enableHighAccuracy: true, // 高精度
maximumAge: 1000, // 1秒缓存
timeout: 5000
});
} else {
console.log('浏览器不支持地理位置。');
}
};