使用高德地图实现地理围栏
什么是地理围栏(Geo-fencing)?
地理围栏(Geo-fencing)是LBS的一种新应用,就是用一个虚拟的栅栏围出一个虚拟地理边界。当手机进入、离开某个特定地理区域,或在该区域内活动时,手机可以接收自动通知和警告。有了地理围栏技术,位置社交网站就可以帮助用户在进入某一地区时自动登记。
地理坐标系
我们通常用经纬度来表示一个地理位置,但是由于一些原因,我们从不同渠道得到的经纬度信息可能并不是在同一个坐标系下。
- 高德地图、腾讯地图以及谷歌中国区地图使用的是GCJ-02坐标系
- 百度地图使用的是BD-09坐标系
- 底层接口(HTML5 Geolocation或ios、安卓API)通过GPS设备获取的坐标使用的是WGS-84坐标系
不同的坐标系之间可能有几十到几百米的偏移,所以在开发基于地图的产品,或者做地理数据可视化时,我们需要修正不同坐标系之间的偏差。
WGS-84 - 世界大地测量系统
WGS-84(World Geodetic System, WGS)是使用最广泛的坐标系,也是世界通用的坐标系,GPS设备得到的经纬度就是在WGS84坐标系下的经纬度。通常通过底层接口得到的定位信息都是WGS84坐标系。
GCJ-02 - 国测局坐标
GCJ-02(G-Guojia国家,C-Cehui测绘,J-Ju局),又被称为火星坐标系,是一种基于WGS-84制定的大地测量系统,由中国国测局制定。此坐标系所采用的混淆算法会在经纬度中加入随机的偏移。
国家规定,中国大陆所有公开地理数据都需要至少用GCJ-02进行加密,也就是说我们从国内公司的产品中得到的数据,一定是经过了加密的。绝大部分国内互联网地图提供商都是使用GCJ-02坐标系,包括高德地图,谷歌地图中国区等。
BD-09 - 百度坐标系
BD-09(Baidu, BD)是百度地图使用的地理坐标系,其在GCJ-02上多增加了一次变换,用来保护用户隐私。从百度产品中得到的坐标都是BD-09坐标系。

地理坐标系列表
| 坐标系 | 坐标格式 | 说明 |
|---|---|---|
| WGS84 | [lng,lat] | WGS-84坐标系,GPS设备获取的经纬度坐标 |
| GCJ02 | [lng,lat] | GCJ-02坐标系,google中国地图、SoSo地图、AliYun地图、MapAbc地图和高德地图所用的经纬度坐标 |
| BD09 | [lng,lat] | BD-09坐标系,百度地图采用的经纬度坐标 |
| BD09LL | [lng,lat] | 同BD09 |
| BD09MC | [x,y] | BD-09米制坐标,百度地图采用的米制坐标,单位:米 |
| BD09Meter | [x,y] | 同BD09MC |
| Baidu | [lng,lat] | 百度坐标系,BD-09坐标系别名,同BD-09 |
| BMap | [lng,lat] | 百度地图,BD-09坐标系别名,同BD-09 |
| AMap | [lng,lat] | 高德地图,同GCJ-02 |
| WebMercator | [x,y] | Web Mercator投影,墨卡托投影,同EPSG3857,单位:米 |
| WGS1984 | [lng,lat] | WGS-84坐标系别名,同WGS-84 |
| EPSG4326 | [lng,lat] | WGS-84坐标系别名,同WGS-84 |
| EPSG3857 | [x,y] | Web Mercator投影,同WebMercator,单位:米 |
| EPSG900913 | [x,y] | Web Mercator投影,同WebMercator,单位:米 |
地理围栏 GeoJSON 数据
地理围栏或地理围栏集的数据由 rfc7946 中定义的、采用 GeoJSON 格式的 Feature 对象和 FeatureCollection 对象表示。 除此之外:
- GeoJSON 对象类型可以是
Feature对象或FeatureCollection对象。 - 几何对象类型可以是
Point、MultiPoint、LineString、MultiLineString、Polygon、MultiPolygon和GeometryCollection。 - 所有特征属性应该包含用于标识地理围栏的
geometryId。 - 具有
Point、MultiPoint、LineString、MultiLineString的特征必须在属性中包含radius。radius值的计量单位为米,radius值的范围为 1 到 10000。 - 具有
polygon和multipolygon几何类型的特征没有半径属性。 validityTime是可选属性,可让用户为地理围栏数据设置过期时间和有效时间。 如果未指定该属性,则数据永不过期,而是一直有效。expiredTime是地理围栏数据的过期日期和时间。 如果请求中userTime的值晚于此值,则将相应的地理围栏数据视为过期的数据,且不会查询这些数据。 基于这一点,此地理围栏数据的 geometryId 将包含在地理围栏响应中的expiredGeofenceGeometryId数组内。validityPeriod是地理围栏有效时段的列表。 如果请求中userTime的值超出有效时段,则将相应的地理围栏数据视为无效,且不会查询这些数据。 此地理围栏数据的 geometryId 包含在地理围栏响应中的invalidPeriodGeofenceGeometryId数组内。 下表显示了 validityPeriod 元素的属性。
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
| startTime | datetime | 是 | 有效时段的开始日期时间。 |
| endTime | datetime | 是 | 有效时段的结束日期时间。 |
| recurrenceType | 字符串 | false | 时段的重复类型。 值可为 Daily、Weekly、Monthly 或 Yearly。 默认值为 Daily。 |
| businessDayOnly | Boolean | false | 指示数据是否仅在工作日有效。 默认值为 false。 |
- 所有坐标值都表示为中定义的 “经度,纬度”
WGS84。 - 对于包含
MultiPoint、MultiLineString、MultiPolygon或GeometryCollection的每个特征,属性将应用到所有元素。 例如:中的所有点MultiPoint都将使用相同的半径形成多个圆形地域隔离区内。
标准GeoJSON
GeoJSON 规范仅支持以下几何图形:
- 点 (Point)
- 线 (LineString)
- 多边形 (Polygon)
- 点集合 (MultiPoint)
- 线集合 (MultiLineString)
- 多边形集合 (MultiPolygon)
- 空间数据集合 (GeometryCollection)
点 (Point)
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}
线 (LineString)
{
"type": "LineString",
"coordinates": [
[30.0, 10.0], [10.0, 30.0], [40.0, 40.0]
]
}
多边形 (Polygon)
{
"type": "Polygon",
"coordinates": [
[[30.0, 10.0], [40.0, 40.0], [20.0, 40.0], [10.0, 20.0], [30.0, 10.0]]
]
}
{
"type": "Polygon",
"coordinates": [
[[35.0, 10.0], [45.0, 45.0], [15.0, 40.0], [10.0, 20.0], [35.0, 10.0]],
[[20.0, 30.0], [35.0, 35.0], [30.0, 20.0], [20.0, 30.0]]
]
}
点集合 (MultiPoint)
{
"type": "MultiPoint",
"coordinates": [
[10.0, 40.0], [40.0, 30.0], [20.0, 20.0], [30.0, 10.0]
]
}
线集合 (MultiLineString)
{
"type": "MultiLineString",
"coordinates": [
[[10.0, 10.0], [20.0, 20.0], [10.0, 40.0]],
[[40.0, 40.0], [30.0, 30.0], [40.0, 20.0], [30.0, 10.0]]
]
}
多边形集合 (MultiPolygon)
{
"type": "MultiPolygon",
"coordinates": [
[
[[30.0, 20.0], [45.0, 40.0], [10.0, 40.0], [30.0, 20.0]]
],
[
[[15.0, 5.0], [40.0, 10.0], [10.0, 20.0], [5.0, 10.0], [15.0, 5.0]]
]
]
}
{
"type": "MultiPolygon",
"coordinates": [
[
[[40.0, 40.0], [20.0, 45.0], [45.0, 30.0], [40.0, 40.0]]
],
[
[[20.0, 35.0], [10.0, 30.0], [10.0, 10.0], [30.0, 5.0], [45.0, 20.0], [20.0, 35.0]],
[[30.0, 20.0], [20.0, 15.0], [20.0, 25.0], [30.0, 20.0]]
]
]
}
空间数据集合 (GeometryCollection)
{
"type": "GeometryCollection",
"geometries": [
{
"type": "Point",
"coordinates": [40.0, 10.0]
},
{
"type": "LineString",
"coordinates": [
[10.0, 10.0], [20.0, 20.0], [10.0, 40.0]
]
},
{
"type": "Polygon",
"coordinates": [
[[40.0, 40.0], [20.0, 45.0], [45.0, 30.0], [40.0, 40.0]]
]
}
]
}
扩展GeoJSON
圆形 (Circle)
Circle GeoJSON 规范不支持该几何图形。我们使用 GeoJSON Point Feature 对象来表示圆。
Circle使用对象表示的几何图形 GeoJSON Feature 必须 包含以下坐标和属性:
-
圆心 (Center)
圆心使用
GeoJSON Point对象表示。 -
半径 (Radius)
圆形的半径
radius使用GeoJSON Feature的属性表示。 半径值以米为单位,并且其类型必须为double。 -
子类型 (subType)
圆形几何图形还必须包含
subType属性。 此属性必须是的属性的一部分GeoJSON Feature,并且其值应为 Circle
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-122.126986, 47.639754]
},
"properties": {
"subType": "Circle",
"radius": 500
}
}
矩形 (Rectangle)
Rectangle GeoJSON 规范不支持该几何图形。我们使用 GeoJSON Polygon Feature 对象来表示矩形。 矩形扩展主要由 Web SDK 的 “绘图工具” 模块使用。
Rectangle使用对象表示的几何图形 GeoJSON Polygon Feature 必须 包含以下坐标和属性:
-
内角
使用对象的坐标表示矩形的角
GeoJSON Polygon。 应该有五个坐标,每个角一个。 与第五个坐标相同,用于关闭多边形环。 假定这些坐标对齐,开发人员可以根据需要对其进行旋转。 -
子类型
矩形几何图形还必须包含
subType属性。 此属性必须是的属性的一部分GeoJSON Feature,并且其值应为 Rectangle
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[5,25],[14,25],[14,29],[5,29],[5,25]]]
},
"properties": {
"subType": "Rectangle"
}
}
高德地图
高德地图提供了以下几组API可用于地理围栏:
- GeoJSON工具类
AMap.GeoJSON - 编辑器工具类
AMap.PolyEditorAMap.PolygonEditorAMap.CircleEditorAMap.RectangleEditorAMap.EllipseEditorAMap.BezierCurveEditor - 鼠标工具插件
AMap.MouseTool
1. GeoJSON工具类
它可以用来解析标准的GeoJSON,但是需要注意的是:它只支持FeatureCollection形式的数据.
const geoJson = new AMap.GeoJSON({
geoJSON: geoJsonObject,
getMarker: function (geoJson, lngLats) {
console.log('点', lngLats);
},
getPolyline: function (geoJson, lngLats) {
console.log('线', lngLats);
},
getPolygon: function (geoJson, lngLats) {
console.log('面', lngLats);
},
});
2. 矢量图形类
function createPolygon(path: any, addToMap: boolean, fitView: boolean) {
const polygon = new AMap.Polygon({
path: path,
strokeColor: '#FF33FF',
strokeWeight: 6,
strokeOpacity: 0.2,
fillOpacity: 0.4,
fillColor: '#1791fc',
zIndex: 50,
});
polygon.on('mouseover', () => {
polygon.setOptions({
fillOpacity: 0.7,
fillColor: '#7bccc4',
});
});
polygon.on('mouseout', () => {
polygon.setOptions({
fillOpacity: 0.5,
fillColor: '#ccebc5',
});
});
if (addToMap) {
map.add(polygon);
}
if (fitView) {
setFitView();
}
currentGeofence = polygon;
return polygon;
}
3. 编辑器工具类
它支持:圆形,折线,多边形,贝瑟尔曲线,椭圆,矩形.
虽然说,圆形,矩形绘制简单.但是,真正实用的只有:多边形.
// 编辑多边形
function editPolygon(path: any, open: boolean) {
closePolygonEditor();
// 创建编辑器
polygonEditor = new AMap.PolyEditor(map);
if (path.length > 0) {
const polygon = createPolygon(path, true, false);
// 吸附功能
polygonEditor.addAdsorbPolygons(polygon);
// 设置编辑目标
polygonEditor.setTarget(polygon);
polygon.on('dblclick', () => {
polygonEditor.setTarget(polygon);
polygonEditor.open();
});
} else {
polygonEditor.setTarget();
}
polygonEditor.on('add', function (event) {
console.log(event);
const polygon = event.target;
polygonEditor.addAdsorbPolygons(polygon);
polygon.on('dblclick', () => {
polygonEditor.setTarget(polygon);
polygonEditor.open();
});
});
polygonEditor.on('end', function (event) {
const paths = event.target.getPath();
console.log('结束多边形编辑', event.target, paths);
});
// 打开编辑
if (open) polygonEditor.open();
}
需要注意的是:
- 绘制出来的路径需要倒序读取,因为标准GeoJson使用的是右手法则.
- 绘制出来的路径并没有封口,即起始点和结束点必须是同一个点.
- 如果需要被
AMap.GeoJSON所解析,GeoJson的数据必须封装成FeatureCollection.
3. 鼠标工具插件
并不实用,弃用.
865

被折叠的 条评论
为什么被折叠?



