为了监视快递小哥,我做了一个小程序!

529 查看

我感觉我可以在电脑上查看快递小哥离我有多远了!

我们来看一下代码。

从地图展现的程度来说,这个地图布局基本没有难度。如果你对我这么说感到疑惑那么我建议你可以看看这个: 高德地图示例中心。你应该很快可以构建出想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+cctrl+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攻城狮,来玩玩么?