best pracetice of GIS coding in front end with AMAP api

背景简介


综合前篇是为了做一个光伏应用的网站,展示一些屋顶信息。计划以卫星地图为底图背景,
同时方便交互。

考虑到地图更新频率、区域屏蔽以及国内GIS坐标偏移等问题,优先方案是google map api.
但是在实施过程中实际的问题是前端代码在客户浏览器执行,因此google map在国内就根本加载
不出来。再次我编程调试使用的电脑也没有完全翻墙,当时也还没有选定在国内还是国外部署。
考虑到以上各种不确定性,最后采用风险较低,地图质量较好的高德地图。

PS: 早先有编程进行过批量的逆地理编码查询,google, baidu, 高德三家的map api均有涉猎。
就服务的质量判断,google最好。国内的高德好于百度,无论是web, js api, 测绘地图质量,技术文档还是
人工服务。

坐标漂移一直存在,从经纬度(WSG89)换算到国内的经纬度仍然会有0~500 m的随机偏移无法避免
因此该案例中使用google坐标系(WSG89)识别的物体换算国内经纬度一定会存在漂移。
即使用AMAP自家的经纬度转换API进行处理。

代码分析


其中部分代码详见下文,在第三行的YOUR_API_KEY中对应的是开发者自己申请的API KEY.
各家的js api key都是无配额限制,但是无法理解的一点是无法隐藏该API KEY,
即无法在script src字段内使用变量。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<script src="http://cache.amap.com/lbs/static/es5.min.js"></script>
<script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>
<script type="text/javascript" src="http://webapi.amap.com/maps?v=1.3&key=YOUR_API_KEY&plugin=AMap.MouseTool"></script>
<script type="text/javascript">
// set up map canvas.
var map = new AMap.Map('container', {
resizeEnable: true,
center: [121.405034,31.164609],
zoom: 16
});
map.setDefaultCursor("crosshair");
// set up marker.
var marker = new AMap.Marker({
position: [121.405034,31.164609]
});
marker.setMap(map);
// click event to open marker.
marker.on('click',function(e){
infowindow.open(map,e.target.getPosition());
})
// advanced marker, more info.
AMap.plugin('AMap.AdvancedInfoWindow',function(){
infowindow = new AMap.AdvancedInfoWindow({
content: '<div class="info-title">XXX</div><div class="info-content">'+
'<img src="http://webapi.amap.com/images/amap.jpg">'+
'XXX!<br/>'+
'<a class="glyphicon glyphicon-envelope" href = "mailto:info@XXXcn.com">moreinfo</a></div>',
offset: new AMap.Pixel(0, -30)
});
infowindow.open(map,[121.405034,31.164609]);
})
// enable tool kits.
AMap.plugin(['AMap.ToolBar','AMap.Scale','AMap.OverView','AMap.MapType'],
function(){
map.addControl(new AMap.ToolBar());
map.addControl(new AMap.Scale());
map.addControl(new AMap.OverView({isOpen:true})); //遮挡button-group
map.addControl(new AMap.MapType({defaultType:1}));
});
// right button functions.
var mouseTool = new AMap.MouseTool(map);
AMap.event.addDomListener(document.getElementById('areaMeasure'), 'click', function() {
//鼠标工具插件添加draw事件监听
AMap.event.addListener(mouseTool, "draw", function callback(e) {
var eObject = e.obj; //obj属性就是鼠标事件完成所绘制的覆盖物对象。
});
mouseTool.measureArea(); //调用鼠标工具的面积量测功能
map.on('dblclick', function() {
mouseTool.close('True');
});
}, false);
AMap.event.addDomListener(document.getElementById('eargleEye'), 'click', function() {
var drawRectangle = mouseTool.rectangle(); //用鼠标工具画矩形
AMap.event.addListener( mouseTool,'draw',function(e){ //添加事件
var rect = e.obj;
var data = {"minLng" : rect.getBounds().getSouthWest( ).getLng(),
"maxLng" : rect.getBounds().getNorthEast( ).getLng(),
"minLat" : rect.getBounds().getSouthWest( ).getLat(),
"maxLat" : rect.getBounds().getNorthEast( ).getLat(),
"cLng" : rect.getBounds().getCenter( ).getLng(),
"cLat" : rect.getBounds().getCenter( ).getLat()
};
if(confirm("are you sure to submit?"))
{
$.post({
url : "{{ url_for('main.NEWPAGE2', username = current_user.username) }}",
data: JSON.stringify(data),
contentType: 'application/json;charset=UTF-8',
success: function(data) {
top.location.href = "{{ url_for('main.NEWPAGE2', username = current_user.username) }}";
},
async:false
});
}
else
{
mouseTool.close(true);
}
});
}, false);
</script>
  • 实现的功能详见代码内注释的文档,其他明细可详询官方文档
  • 官方的实例中心内有详实的案例供参考引用
  • 其中带数字的红蓝图钉只到10, blue mark,red mark
  • 该案例使用的是flask-bootstrap模板,因此模板文件完全支持bootstrap,
    地图嵌入使用容器embeded-responsive.
  • NEWPAGE2中需要达到分栏的效果,使用的是row, col-lg-xx 两个组件进行分区,
    其中一个嵌套地图容器

trouble shooting


无法在src中隐匿API_KEY

一般而言像API_KEY这样的私密信息是写入系统环境变量,在代码中直接读取而非明文写入代码。
即使是jinja2的模板用 的方法也无法将变量传到src=’’中。
所以这点暂时无解,只能在API设置里标记好白名单以规避滥用风险。

但是stack overflow里有一说是和域名关联,也无法滥用

KEY或者其他私密信息例如email和密码都强烈建议使用环境变量

在python中读取系统环境变量:

1
2
import os
os.environ.get('ENV_VAR_NAME')

一般建议将系统环境变量写入到虚拟环境中,即virtualenv中。系统环境变量设置方法:

Linux:

1
$ export ENV_VAR_NAME='YOUR_API_KEY'

windows cmd/powershell:

1
>set ENV_VAR_NAME='YOUR_API_KEY'

AMAP前端说明

虽然高德已经是阿里旗下的产品但是个人读说明文档还是不够顺畅,无法直接找到
解决问题的方法。

社区活跃度也是一般,稍微比百度的强一些。该案例中很多时间都花费在了调试上。

分享到 评论