我感觉我可以在电脑上查看快递小哥离我有多远了!
应用演示地址:
源码下载: 下载到本地解压后即可运行。由于流量问题,请先替换源码
delivery.js
中的appId
appId注册链接: 。
我们来看一下代码。
从地图展现的程度来说,这个地图布局基本没有难度。如果你对我这么说感到疑惑那么我建议你可以看看这个: 。你应该很快可以构建出想wildGeo这样的界面。如果你对此表示有难度的话,请拷贝下面的代码到一个空白的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 variablevar map;// Set the center as Wilddog HQvar locations = { "WilddogHQ": [39.897614,116.408032]};var center = locations["WilddogHQ"];// Get a reference to the Wilddog public transit open data setvar transitWilddogRef = new Wilddog("https://.wilddogio.com/")
野狗为了更好的和地图是进行适配,开发了wildGeo对象,他是一个单独的js,有兴趣的开发者可以 或
我们在建立了transitwilddogRef
对象的基础上,需要尽力wildGeo
对象。
// Create a new WildGeo instance, pulling data from the public transit datavar wildGeo = new WildGeo(transitWilddogRef.child("_geofire"));
上面的代码说明了,创建wildGeo
对象来操作地理坐标数据,数据来源于transitWilddogRef
下面的_geofire
节点。
之后,我们来看一下怎样数据初始化。
/*************//* GEOQUERY *//*************/// Keep track of all of the deliverys currently within the queryvar deliverysInQuery = {};// Create a new GeoQuery instancevar 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);}
累死妹子了!
作为一个博爱的程序媛,我还要一定要做这个事情(为什么我写了这句话感觉到好邪恶!):
Android版本:
IOS版本:
鉴于本人是一个前端攻城狮,所以这两个版本的东西我也就只能给你们一个链接吧,各位IOS攻城狮和Android攻城狮,来玩玩么?