我感觉我可以在电脑上查看快递小哥离我有多远了!
应用演示地址: http://geomap.wilddogapp.com/
源码下载: http://git.oschina.net/chengxinxin/wildGeo 下载到本地解压后即可运行。由于流量问题,请先替换源码
delivery.js
中的appId
appId注册链接: https://www.wilddog.com/my-account/signup。
我们来看一下代码。
从地图展现的程度来说,这个地图布局基本没有难度。如果你对我这么说感到疑惑那么我建议你可以看看这个: 高德地图示例中心。你应该很快可以构建出想wildGeo这样的界面。如果你对此表示有难度的话,请拷贝下面的代码到一个空白的HTML文件中:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>基本地图展示</title>
<link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/>
<script src="http://cache.amap.com/lbs/static/es5.min.js"></script>
<script src="http://webapi.amap.com/maps?v=1.3&key=您申请的key值"></script>
<script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>
</head>
<body>
<div id="container"></div>
<script>
var map = new AMap.Map('container', {
resizeEnable: true,
zoom:11,
center: [116.397428, 39.90923]
});
</script>
</body>
</html>
这样你就可以在浏览器中打开一张地图了。
下面我们该干什么了? Coding!
我们需要在地图上标注配送站的信息,高德地图上叫做 自定义标记覆盖物,野狗的wildGeo工程师是这样写的:
//自定义点标记内容
var stationMarkerContent = document.createElement("div");
stationMarkerContent.className = "markerContentStyle";
//点标记中的图标
var stationMarkerImg = document.createElement("img");
stationMarkerImg.className = "markerlnglat";
stationMarkerImg.src ="http://webapi.amap.com/images/marker_sprite.png";
stationMarkerContent.appendChild(stationMarkerImg);
//点标记中的文本
var stationMarkerSpan = document.createElement("span");
stationMarkerSpan.innerHTML = '配送站';
stationMarkerSpan.setAttribute("class", "span1")
stationMarkerContent.appendChild(stationMarkerSpan);
var stationMarker = new AMap.Marker({ //AMap.Marker是非常重要的点,关于样式如果不是很符合你的要求,你可以手动去改!
map:map,
position:new AMap.LngLat(116.408032,39.897614),//基点位置
autoRotation:false,
content: stationMarkerContent //自定义点标记覆盖物内容,这个地方可以直接写HTML文件
});
野狗工程师在做wildGeo用的是JavaScript来做的,他定义了一个 stationMarkerContent
来盛放自定义标记覆盖物的内容。之后把标价覆盖物
的HTML代码构造好了放到了 AMap.Marker
对象的content
中。你当然可以直接在content
中写好你构造好的HTML代码
字符串。
完成以上的步骤,客户实现的效果是,一张地图,之后会有一个配送站地理位置图标,和配送站三个文字。
因为我们需要确定是地图上任意一个点上某个范围内的送餐员电话,所以我们需要一某个点为中心画圆,当然,高德地图给我们提供了这样的一个接口。
var circle = new AMap.Circle({
map:map,//map指的是你创建的地图对象,就是这篇文章第五个代码块中的那个map对象
center:loc,// 圆心位置
radius:(1500), //半径
strokeColor: "#6D3099", //线颜色
strokeOpacity: 1, //线透明度
strokeWeight: 3, //线粗细度
fillColor: "#B650FF", //填充颜色
fillOpacity: 0.35//填充透明度
});
之后地图上会有一个出现一个表示范围的圆环。下面就是野狗实施后端云大显身手的时间了! 别忘记注册 野狗 账号
首先,如果你要通过 ctrl+c
和 ctrl+p
之后代码就可以使用的话,你一定要了解后台的数据结构。wildGeo数据结构如下:
{
"_geofire": {
"beijing:0000": {
"g": "wx4dwxwtp8",
"l": [
39.856513,
116.310528
]
},
"beijing:0001": {
"g": "wx4en9qsrw",
"l": [
39.909971999999996,
116.310528
]
},
"beijing:0100": {
"g": "wx4f8rstp8",
"l": [
39.856513,
116.3846855
]
},
"beijing:0101": {
"g": "wx4g03ksrw",
"l": [
39.909971999999996,
116.3846855
]
}
},
"beijing": {
"delivery": {
"0000": {
"id": "0000",
"lat": 39.856513,
"lng": 116.310528
},
"0001": {
"id": "0001",
"lat": 39.909971999999996,
"lng": 116.310528
},
"0100": {
"id": "0100",
"lat": 39.856513,
"lng": 116.3846855
},
"0101": {
"id": "0101",
"lat": 39.909971999999996,
"lng": 116.3846855
}
}
}
}
你们一定要明白数据结构和数据的区别!你可以把上面的数据复制到本地的一个json文件中,之后导入到你的野狗app里面去。
之后建立也野狗对象
//map variable
var map;
// Set the center as Wilddog HQ
var locations = {
"WilddogHQ": [39.897614,116.408032]
};
var center = locations["WilddogHQ"];
// Get a reference to the Wilddog public transit open data set
var transitWilddogRef = new Wilddog("https://<appId>.wilddogio.com/")
野狗为了更好的和地图是进行适配,开发了wildGeo对象,他是一个单独的js,有兴趣的开发者可以 下载 或 阅读文档
我们在建立了transitwilddogRef
对象的基础上,需要尽力wildGeo
对象。
// Create a new WildGeo instance, pulling data from the public transit data
var wildGeo = new WildGeo(transitWilddogRef.child("_geofire"));
上面的代码说明了,创建wildGeo
对象来操作地理坐标数据,数据来源于transitWilddogRef
下面的_geofire
节点。
之后,我们来看一下怎样数据初始化。
/*************/
/* GEOQUERY */
/*************/
// Keep track of all of the deliverys currently within the query
var deliverysInQuery = {};
// Create a new GeoQuery instance
var geoQuery = wildGeo.query({
center: center, //center指的是 var center = locations["WilddogHQ"];
radius: 1500
});
/* Adds new delivery markers to the map when they enter the query */
geoQuery.on("key_entered", function(deliveryId, deliveryLocation) {
// Specify that the delivery has entered this query
deliveryId = deliveryId.split(":")[1];
deliverysInQuery[deliveryId] = true;
// Look up the delivery's data in the Transit Open Data Set
transitWilddogRef.child("beijing/delivery").child(deliveryId).once("value", function(dataSnapshot) {
// Get the delivery data from the Open Data Set
delivery = dataSnapshot.val();
// If the delivery has not already exited this query in the time it took to look up its data in the Open Data
// Set, add it to the map
if (delivery !== null && deliverysInQuery[deliveryId] === true) {
// Add the delivery to the list of deliverys in the query
deliverysInQuery[deliveryId] = delivery;
// Create a new marker for the delivery
delivery.marker = createdeliveryMarker(delivery);
}
});
});
我们需要观察几个点:
第一个点是
wildGeo.query()
之后会产生一个新的对象叫做:geoQuery
。geoQuery.on(eventType,callback)
eventType是事件类型:这里用的是key_entered
,表示监听的点是否进入范围之内。如果进入则存到deliverysInQuery
对象中去,通过createdeliveryMarker
方法,在地图上创建一个个的快递员图标。
那么如果快递离开了我们的那个范围呢?
geoQuery.on("key_exited", function(deliveryId, deliveryLocation) {
// Get the delivery from the list of deliverys in the query
deliveryId = deliveryId.split(":")[1];
var delivery = deliverysInQuery[deliveryId];
// If the delivery's data has already been loaded from the Open Data Set, remove its marker from the map
if (delivery !== true && typeof delivery.marker !== "undefined") {
delivery.marker.stopMove();
delivery.marker.setMap(null);
}
// Remove the delivery from the list of deliverys in the query
delete deliverysInQuery[deliveryId];
});
我们可以使用key_exited
这个方法,来监听离开我们的快递员。
最后附上createdeliveryMarker
方法。
/**********************/
/* HELPER FUNCTIONS */
/**********************/
/* Adds a marker for the inputted delivery to the map */
function createdeliveryMarker(delivery) {
//自定义点标记内容
var markerContent = document.createElement("div");
markerContent.className = "markerContentStyle";
//点标记中的图标
var markerImg = document.createElement("img");
markerImg.className = "markerlnglat";
markerImg.src = "images/man.png";
markerImg.height = "35";
markerImg.width = "27";
markerContent.appendChild(markerImg);
//点标记中的文本
var markerSpan = document.createElement("span");
markerSpan.innerHTML = delivery.id;
markerContent.appendChild(markerSpan);
var marker = new AMap.Marker({
map:map,
position:new AMap.LngLat(delivery.lng, delivery.lat),//基点位置
autoRotation:false,
content: markerContent //自定义点标记覆盖物内容
});
return marker;
}
和地图初始化代码
片段
function initializeMap() {
var loc = new AMap.LngLat(center[1], center[0]);
//初始化地图对象,加载地图
var UA = navigator.userAgent;
if (UA.indexOf("Mobile") == -1 || UA.indexOf("Mobile") == -1) {
defineMap(loc, 15);
} else {
defineMap(loc , 13);
};
//加载工具条
// map.plugin(["AMap.ToolBar"],function(){
// var tool = new AMap.ToolBar();
// map.addControl(tool);
// });
//
// //加载比例尺
// map.plugin(["AMap.Scale"],function(){
// var scale = new AMap.Scale();
// map.addControl(scale);
// });
var circle = new AMap.Circle({
map:map,
center:loc,// 圆心位置
radius:((radiusInKm) * 1000), //半径
strokeColor: "#6D3099", //线颜色
strokeOpacity: 1, //线透明度
strokeWeight: 3, //线粗细度
fillColor: "#B650FF", //填充颜色
fillOpacity: 0.35//填充透明度
});
//自定义点标记内容
var stationMarkerContent = document.createElement("div");
stationMarkerContent.className = "markerContentStyle";
//点标记中的图标
var stationMarkerImg = document.createElement("img");
stationMarkerImg.className = "markerlnglat";
stationMarkerImg.src ="http://webapi.amap.com/images/marker_sprite.png";
stationMarkerContent.appendChild(stationMarkerImg);
//点标记中的文本
var stationMarkerSpan = document.createElement("span");
stationMarkerSpan.innerHTML = '配送站';
stationMarkerSpan.setAttribute("class", "span1")
stationMarkerContent.appendChild(stationMarkerSpan);
var stationMarker = new AMap.Marker({
map:map,
position:new AMap.LngLat(116.408032,39.897614),//基点位置
autoRotation:false,
content: stationMarkerContent //自定义点标记覆盖物内容
});
var lnglat;
var clickEventListener = AMap.event.addListener(map,'click',function(e){
lnglat=e.lnglat;
circle.setCenter(lnglat);
updateCriteria();
});
var updateCriteria = _.debounce(function() {
lnglat = circle.getCenter();
geoQuery.updateCriteria({
center: [lnglat.getLat(), lnglat.getLng()],
radius: radiusInKm
});
}, 10);
}
累死妹子了!
作为一个博爱的程序媛,我还要一定要做这个事情(为什么我写了这句话感觉到好邪恶!):
鉴于本人是一个前端攻城狮,所以这两个版本的东西我也就只能给你们一个链接吧,各位IOS攻城狮和Android攻城狮,来玩玩么?