地图小区景点边界轮廓实现

栏目: JavaScript · 发布时间: 7年前

内容简介:经常的我们在使用地图功能时,会发现在选择一个小区或者一个热门景点的时候,地图上面会给出其边界轮廓,能够方便我们知道其范围大小,有时候在我们使用地图组件的时候,也会面临着类似的需求。比如在地图上面标识出一个商场范围内的热力图,一个热门景点的游览情况等。那么,我们该如何利用地图功能来实现这类效果呢,今天我们一起来探讨一下。最近我们就有一个需求,需要标识出一些热门场所的人流的热力图情况,同时需要给出该热门场所的边界轮廓。经过查看百度地图和高德地图的开发者API文档,发现并没有这类公共接口提供我们使用。目前地图能

经常的我们在使用地图功能时,会发现在选择一个小区或者一个热门景点的时候,地图上面会给出其边界轮廓,能够方便我们知道其范围大小,有时候在我们使用地图组件的时候,也会面临着类似的需求。比如在地图上面标识出一个商场范围内的热力图,一个热门景点的游览情况等。那么,我们该如何利用地图功能来实现这类效果呢,今天我们一起来探讨一下。

地图小区景点边界轮廓实现

最近我们就有一个需求,需要标识出一些热门场所的人流的热力图情况,同时需要给出该热门场所的边界轮廓。经过查看百度地图和高德地图的开发者API文档,发现并没有这类公共接口提供我们使用。目前地图能够提供我们使用的,基本只能是一些行政区划的边界范围,这个在我之前的文章中也有写过,大家可以参照 《仿链家地图找房的简单实现》

那么现在面临的需求该如何实现呢?

通过查看地图功能的接口调用情况和在网上查询相关资料,最终我们找到了下面这个“不算是方法的方法”。

  • 使用了地图的相关API接口获取相关数据
  • API接口不是官方给出的,所以也就面临着稳定性的问题,可能随时被关(高德的只能简单参考,本身就存在较大缺陷,后面会说)

实现思路

  • 通过地图的POI查询服务获取到兴趣点id

    那么什么是POI呢?

    检索服务提供某一特定地区的兴趣点位置查询服务(POI:Point of Interest,感兴趣点)

    相关的官方文档请参照以下地址:

  • 通过兴趣点id获取该兴趣点的详细信息

    这里面需要用到的相关API就需要我们查看地图的执行过程,找到对应的API了。(也希望各个地图官方能够给出官方的方法吧)

PS:地图功能的使用情况在本篇不做说明,具体申请相关Key的过程请分别参照官网说明即可。

下面我们来分别给出百度地图和高德地图的实现方法:

百度地图实现

闲话休谈,咱们直接上码

</html>
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>百度地图DEMO</title>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你申请的AK"></script>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {

        var queryHouseOutline = function(hid, callback) {
            var baseURL = 'http://map.baidu.com/?reqflag=pcmap&coord_type=3&from=webmap&qt=ext&ext_ver=new&l=18';
            var url = baseURL + "&uid=" + hid;
            callback && (window.queryHouseOutlineCallback = callback);
            $.ajax({
                type: "get",
                async: false,
                url: url,
                dataType: "jsonp",
                jsonpCallback: "queryHouseOutlineCallback",
                success: function(datas) {}
            });
        };

        /**
         * 模糊查询小区信息, 无返回值
         * @param {} house  小区名称
         * @param {} city   所属城市名称
         * @param {} ak     百度地图AK
         * @param {} callback   回调函数,该函数可以接收到请求的返回值
         */
        var queryHouse = function(house, city, ak, callback) {
            var baseURL = 'http://api.map.baidu.com/place/v2/search?output=json&scope=2';
            var url = baseURL + "&q=" + house + "&region=" + city + "&ak=" + ak;
            callback && (window.queryHouseCallback = callback);
            $.ajax({
                type: "get",
                async: false,
                url: url,
                dataType: "jsonp",
                jsonpCallback: "queryHouseCallback",
                success: function(datas) {}
            });
        };

        /**
         * 墨卡托坐标转百度坐标
         * @param {} coordinate
         * @return {}
         */
        var coordinateToPoints = function(map, coordinate) {
            var points = [];
            if (coordinate) {
                var arr = coordinate.split(";");
                if (arr) {
                    for (var i = 0; i < arr.length; i++) {
                        var coord = arr[i].split(",");
                        if (coord && coord.length == 2) {
                            var mctXY = new BMap.Pixel(coord[0], coord[1]);
                            var project = map.getMapType().getProjection();
                            var point = project.pointToLngLat(mctXY);
                            points.push(new BMap.Point(point.lng, point.lat));
                        }
                    }
                }
            }
            return points;
        };
        /**
         * 墨卡托坐标解析
         * @param {} mocator
         * @return {}
         */
        var parseGeo = function(mocator) {
            if (typeof mocator != 'string') {
                return {};
            }
            var t = mocator.split("|");
            var n = parseInt(t[0]);
            var i = t[1];
            var r = t[2];
            var o = r.split(";");
            if (n === 4) {
                for (var a = [], s = 0; s < o.length - 1; s++) {
                    "1" === o[s].split("-")[0] && a.push(o[s].split("-")[1]);
                }
                o = a;
                o.push("");
            }
            var u = [];
            switch (n) {
                case 1:
                    u.push(o[0]);
                    break;
                case 2:
                case 3:
                case 4:
                    for (var s = 0; s < o.length - 1; s++) {
                        var l = o[s];
                        if (l.length > 100) {
                            l = l.replace(/(-?[1-9]\d*\.\d*|-?0\.\d*[1-9]\d*|-?0?\.0+|0|-?[1-9]\d*),(-?[1-9]\d*\.\d*|-?0\.\d*[1-9]\d*|-?0?\.0+|0|-?[1-9]\d*)(,)/g,
                                "$1,$2;");
                            u.push(l);
                        } else {
                            for (var c = [], d = l.split(","), f = 0; f < d.length; f += 2) {
                                var p = d[f];
                                var h = d[f + 1];
                                c.push(p + "," + h);
                            }
                            u.push(c.join(";"))
                        }
                    }
                    break;
                default:
                    break;
            }

            if (u.length <= 1) {
                u = u.toString();
            }

            var result = {
                type: n,
                bound: i,
                points: u
            };
            return result;
        };


        var map = new BMap.Map("allmap"); // 创建Map实例
        map.centerAndZoom("北京", 19);
        map.addControl(new BMap.MapTypeControl()); //添加地图类型控件

        map.enableScrollWheelZoom(false); //开启鼠标滚轮缩放

        /**
         * 第一个参数是城市名,第二参数是小区名 
         */
        var showArea = function(city, area) {
            queryHouse(area, city, "你申请的AK", function(data) {
                if (data.message == 'ok') {
                    var houses = data.results;
                    if (houses && houses.length > 0) {
                        var house = houses[0];
                        queryHouseOutline(house.uid, function(houseOutline) {
                            var geo = houseOutline.content.geo;
                            if (!geo) {
                                var location = house.location;
                                var point = new BMap.Point(location.lng, location.lat);
                                map.centerAndZoom(point, 19);
                                var marker = new BMap.Marker(point);
                                marker.setAnimation(BMAP_ANIMATION_BOUNCE);
                                map.addOverlay(marker);
                            } else {
                                map.clearOverlays();
                                var geoObj = parseGeo(geo);
                                //边界点
                                var points = coordinateToPoints(map, geoObj.points);
                                var ply = new BMap.Polygon(points, {
                                    strokeWeight: 2,
                                    strokeColor: "#F01B2D",
                                    strokeOpacity: 0.9,
                                    fillColor: "transparent"
                                }); //建立多边形覆盖物
                                map.addOverlay(ply); //添加覆盖物
                                map.setViewport(ply.getPath()); //调整视野 
                            }
                        });
                    }
                }
            });
        };

        showArea($('#cityId').val(), $('#areaId').val());

        $('#showBtn').click(function() {
            debugger;
            showArea($('#cityId').val(), $('#areaId').val());
        });

        $("#areaId").keydown(function(e) {
            if (event.keyCode == "13") {
                showArea($('#cityId').val(), $('#areaId').val());
            }
        })
    });
    </script>
</head>

<body>
    <table>
        <tr>
            <td>城市:</td>
            <td>
                <input id="cityId" type="text" value="北京" />
            </td>
            <td>小区:</td>
            <td>
                <input id="areaId" type="text" value="故宫博物院" />
            </td>
            <td>
                <button id="showBtn">显示</button>
            </td>
        </tr>
    </table>
    <div id="allmap" style="width: 90vw; height: 90vh;"></div>
</body>

</html>
复制代码

相关的代码注释都有所添加,参照即可。其中需要注意的是百度地图获取到的坐标点需要进行转换成百度地图识别的点位形式。 另外,边界的描画使用到的是地图的Polygon功能,相关内容请参照

高德地图实现

</html>
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>高德地图DEMO</title>
    <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.10&key=你申请的AK"></script>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
        var map = new AMap.Map('allmap', {
            zoom: 19,
            center: [116.397428, 39.90923]
        }); // 创建Map实例

        /**
         * 第一个参数是城市名,第二参数是小区名 
         */
        var showArea = function(city, area) {
            queryHouse(area, city, "你申请的AK", function(data) {
                console.error(data)
                if (data.status == 1) {
                    var houses = data.pois;
                    if (houses && houses.length > 0) {
                        var house = houses[0];
                        queryHouseOutline(house.id, function(houseOutline) {
                            console.error("get outline success");

                            var pathPoints = houseOutline.data.spec.mining_shape.shape;
                            
                            var tmpPath = pathPoints.split(";");

                            var points = [];
                            tmpPath.forEach(function(value, index, array) {
                                points.push(value.split(","))
                            });

                            map.clearMap();

                            var ply = new AMap.Polygon({
                                map: map,
                                path: points,
                                strokeColor: "#F01B2D",
                                fillColor: "transparent"
                            }); //建立多边形覆盖物

                            map.setFitView(); //调整最佳显示
                        });
                    }
                }
            });
        };

        var queryHouseOutline = function(hid, callback) {
            var baseURL = 'https://www.amap.com/detail/get/detail';
            $.ajax({
                type: "get",
                data: {
                    id: hid
                },
                url: baseURL,
                dataType: "json",
                success: function(datas) {
                    callback(datas)
                }
            });
        };

        /**
         * 模糊查询小区信息, 无返回值
         * @param {} house  小区名称
         * @param {} city   所属城市名称
         * @param {} ak     高德地图AK
         * @param {} callback   回调函数,该函数可以接收到请求的返回值
         */
        var queryHouse = function(house, city, ak, callback) {
            var baseURL = 'http://restapi.amap.com/v3/place/text?&keywords=' + house + '&city=' + city + '&output=json&offset=20&page=1&key=' + ak;
            callback && (window.queryHouseCallback = callback);
            $.ajax({
                type: "get",
                async: false,
                url: baseURL,
                dataType: "jsonp",
                jsonpCallback: "queryHouseCallback",
                success: function(datas) {}
            });
        };

        showArea($('#cityId').val(), $('#areaId').val());

        $('#showBtn').click(function() {
            showArea($('#cityId').val(), $('#areaId').val());
        });

        $("#areaId").keydown(function(e) {
            if (event.keyCode == "13") {
                showArea($('#cityId').val(), $('#areaId').val());
            }
        })
    });
    </script>
</head>

<body>
    <table>
        <tr>
            <td>城市:</td>
            <td>
                <input id="cityId" type="text" value="北京" />
            </td>
            <td>小区:</td>
            <td>
                <input id="areaId" type="text" value="故宫博物院" />
            </td>
            <td>
                <button id="showBtn">显示</button>
            </td>
        </tr>
    </table>
    <div id="allmap" style="width: 90vw; height: 90vh;"></div>
</body>

</html>
复制代码

高德地图的实现方式根据实际的效果来看,本身应该是做了API接口限制的处理,经常会出现获取不到详细信息或者给出的详细信息中的边界信息数据不准确。 这里只是作为一个对比参照,高德地图不推荐来做这个需求,API接口稳定性太差。

后记

①百度地图会涉及到功能接口配额的问题

地图小区景点边界轮廓实现

主要会涉及到上面的 地点检索 配额,如果只是个人简单使用的,可以注册个人开发者,基本配额就够使用了

②高德地图没有找到配额相关的数据,毕竟走的非正规手段吧

③百度地图和高德地图对于一些位置的边界数据不同

有些地点只会在其中一个能够获取到(高德地图能够返回数据的情况下)

④高德地图在检索位置时,能够支持全拼音输入,也能检索出来(感觉这个厉害,但是中文多音字处理不知道会怎么样)

参考资料:

百度地图小区边界(轮廓)处理

高德地图之 python 爬取POI数据及其边界经纬度(根据关键字在城市范围内搜索)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大数据之眼

大数据之眼

[德]尤夫娜·霍夫施泰特 / 陈巍 / 浙江文艺出版社 / 2018-5-7 / 68.00元

德国狂销10万册的大数据商业应用畅销书,经典之作《大数据时代》的姊妹篇。 该书在德语国家促发了一场关于大数据,人工智能与人的关系建构的大讨论。 德国大数据与人工智能领域权威,首度为中国读者亲笔作序。 在后大数据时代,如何维护自己的隐私,如何巧妙利用资源获得更多金钱? 一部对大数据发展所产生的问题进行思考和规避的先知式作品。 当智能机器欲“优化”我们,入侵我们的生活,统......一起来看看 《大数据之眼》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具