浅谈前端的定位实现

前端常见的定位大致有如下几种方案

geolocation 定位

地理位置 API 允许用户向 Web 应用程序提供他们的位置。出于隐私考虑,报告地理位置前会先请求用户许可,只用用户允许定位才能够获取到定位信息。

在使用之前需要对该对象进行判断

1
2
3
if (navigator.geolocation) {
// doSomething
}

通过 getCurrentPosition() 获取当前定位位置,若用户允许进行定位,则会返回一个集合位置相关信息的对象集合

1
2
3
4
navigator.geolocation.getCurrentPosition(pos => {
console.log(pos.coords.latitude)
console.log(pos.coords.longitude)
})

geolocation API 同时还提供了获取用户移动时的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
// 可以使用 clearWatch 移除事件
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.watchPosition(showPosition);
} else {
console.log("Geolocation is not supported by this browser")
}
}

function showPosition(position) {
console.log("Latitude: " + position.coords.latitude +
"<br />Longitude: " + position.coords.longitude)
}

第三方地图定位

以腾讯地图为例,使用之前引入依赖
https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js

获取精确定位信息

1
2
3
4
5
6
let geolocation = new qq.maps.Geolocation("your key", "myapp")
geolocation.getLocation(pos => {
// doSomething
}, err => {
// doSomething
})

获取粗糙定位信息

1
2
3
4
5
6
let geolocation = new qq.maps.Geolocation("your key", "myapp")
geolocation.getIpLocation(pos => {
// doSomething
}, err => {
// doSomething
})

如需使用腾讯地图,可以使用如下方式进行引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function TMap () {
return new Promise(function (resolve, reject) {
if (window.qq) {
resolve(window.qq)
return false
}

window.init = function () {
resolve(window.qq)
}

let script = document.createElement('script')
// 如需使用几何运算工具,需要加上参数 &libraries=geometry
script.src = `https://map.qq.com/api/js?v=2.exp&callback=init&key=${key}`
script.onerror = reject
document.head.appendChild(script)
})
}

腾讯地图提供了丰富的 API 及组件:

1.初始化地图

1
2
3
4
5
6
7
8
9
10
let center = new qq.maps.LatLng(latitude, longitude)
let map = new qq.maps.Map($element, {
center: center,
zoom: 12,
minZoom: 7,
zoomControl: true,
zoomControlOptions: {
position: qq.maps.ControlPosition.BOTTOM_LEFT
}
})

2.添加覆盖物

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let marker = new qq.maps.Marker({
position: center,
map: map
})
let size = new qq.maps.Size(120, 180)
let origin = new qq.maps.Point(0, 0)
let anchor = new qq.maps.Point(15, 20)
let scaleSize = new qq.maps.Size(15, 15)
let markerIcon = new qq.maps.MarkerImage(
redIcon,
size,
origin,
anchor,
scaleSize
)
marker.setIcon(markerIcon)
// 删除覆盖物
marker.setMap(null)

3.添加信息窗及事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let infoWin = new qq.maps.InfoWindow({
map: map
})

qq.maps.event.addListener(marker, 'click', () => {
infoWin.open()
infoWin.setContent(`<div style="text-align:center;white-space:nowrap;margin:10px;">${title}</div>`)

infoWin.setPosition(center)
})

qq.maps.event.addListener(map, 'bounds_changed', () => {
map.setCenter(center)
marker.setMap(null)
// doSomething
})

4.地图选点组件

1
2
3
4
export default (backUrl) => {
window.location.href = `https://apis.map.qq.com/tools/locpicker?search=1&type=0&backurl=${backUrl}&key=${key}&referer=my-app`
}

5.添加 label

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let label = new qq.maps.Label({
position: center,
map: map,
offset: new qq.maps.Size(-40, 10),
content: 'label'
})

let cssStyle = {
color: '#FFFFFF',
fontSize: '12px',
fontWeight: 'bold'
transform: 'translateX(-50%)'
}

label.setStyle(cssStyle)

6.绘制直线

1
2
3
4
5
6
7
new qq.maps.Polyline({
path: [start, end],
strokeColor: '#000',
strokeWeight: 5,
editable: false,
map: map
})

7.绘制圆形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
new qq.maps.Circle({
//圆形的中心点坐标。
center: center,
//圆形是否可点击。
clickable: true,
//是否可以编辑
editable: true,
//鼠标在圆形内的光标样式。
cursor: 'pointer',
//圆形的填充色,可通过Color对象的alpha属性设置透明度。
// fillColor: "#00f",
fillColor: new qq.maps.Color(0,15,255, 0.2),
//要显示圆形的地图。
map: this.map,
//圆形的半径。
radius: 500,
//圆形的边框颜色,可通过Color对象的alpha属性设置透明度。
strokeColor: "#fff",
//圆形的边框样式。实线是solid,虚线是dash。
strokeDashStyle: "solid",
//圆形的边框线宽。
strokeWeight: 2,
//圆形是否可见。
visible: true,
//圆形的zIndex值。
zIndex: 1000
})

8.绘制多边形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
new qq.maps.Polygon({
//多边形是否可点击。
clickable: true,
//鼠标在多边形内的光标样式。
cursor: 'crosshair',
//多边形是否可编辑。
editable: true,
//多边形的填充色,可通过Color对象的alpha属性设置透明度。
// fillColor: '#5f9ea0',
fillColor: fillColor || new qq.maps.Color(0, 0, 0, 0.2),
//要显示多边形的地图。
map: this.map,
//多边形的路径,以经纬度坐标数组构成。
path: path,
//多边形的线条颜色,可通过Color对象的alpha属性设置透明度。
strokeColor: '#0ad',
//多边形的边框样式。实线是solid,虚线是dash。
strokeDashStyle: 'solid',
//多边形的边框线宽。
strokeWeight: 3,
//多边形是否可见。
visible: true,
//多边形的zIndex值。
zIndex: 1000
})

9.计算直线距离

1
qq.maps.geometry.spherical.computeDistanceBetween(path1, path2)

更多 API 移步 腾讯地图 JavaScript API
需要注意的是,使用腾讯地图的一些开放 API 必须进行 Key鉴权:

    > Key用途
    Key用于识别开发者身份、验证权限,并在某些情况下方便联系到您。不使用Key会导致部分功能无法正常使用。

    > Key使用限制
    目前Key申请完全免费,基础功能使用免费,且没有调用次数限制。

    > Key使用方法
    在加载API服务时通过key参数传入您申请的Key。

    > Key如何申请
    使用QQ账号登录,点击控制台—密钥管理—申请创建密钥,填写应用名及应用描述即可申请。一个账号最多可以申请5个Key

微信 JSSDK 定位

微信提供了 JSSDK 供开发者在微信环境下使用,其中包含获取当前位置的 api,若要使用微信 JSSDK,需要通过 wx.config 进行权限验证,验证通过后使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
wx.config({
debug: false,
appId: json.appid,
timestamp: json.timestamp,
nonceStr: json.nonceStr,
signature: json.signature,
jsApiList: [
'getLocation'
]
});

wx.error(function (res) {
console.log(res.errMsg);
options.callback();
});

wx.ready(function () {
wx.getLocation({
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation 用的火星坐标,可传入'gcj02'
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
console.log('微信定位成功;');
},
fail: function(){
console.log('微信定位失败;');
}
});
});

App 定位

对于嵌入在 App 中的 H5 页面,通常会由 App 进行定位,并通过地址栏传参给 H5 页面,在 App 中,优先使用 App 的定位。

参考

  1. 腾讯地图 JavaScript API
  2. 微信JS-SDK说明文档
作者

晓策

发布于

2019-04-26

更新于

2022-06-09

许可协议

评论