Openlayers 地名搜索、坐标搜索、行政区划等服务-基于天地图Web服务

发布于:2023-01-17 ⋅ 阅读:(477) ⋅ 点赞:(0)

Openlayers 地名搜索、坐标搜索、行政区划等服务-基于天地图Web服务

OpenLayers 教程

天地图作为广大 GISer 使用频繁的服务之一,除了应用众多的底图服务(影像、地形、矢量),还有很多 Web 服务接口。

比如:地名搜索、地理编码查询、地理逆编码查询、行政区划、路径公交规划等,可以根据项目的实际需求调用接口。

本文介绍在前端使用 ajax 发起请求,获取天地图服务数据,并且在地图渲染。

包括: 地名搜索(获取列表)、地理编码查询(地名查询坐标)、地理逆编码查询(坐标查询地名)、行政区别、路径规划(导航)

PS:其他服务也类型,前端发起请求,获取数据,通过 Openlayers 渲染即可!

放上官网地址: 天地图 Wep API

在这里插入图片描述

Openlayers 使用天地图Web服务

<html lang="en">
<head>
    <meta charSet="utf-8">
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
    <style>
        /* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */
        .map {
            height: 400px;
            width: 100%;
            float: left;
        }
    </style>
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <script src="http://openlayers.vip/examples/resources/ol.js"></script>
    <script src="http://openlayers.vip/examples/resources/jquery-3.5.1.min.js"></script>
    <script src="http://openlayers.vip/examples/resources/layer.js"></script>

    <script src="./tiandituLayers.js"></script>
    <title>OpenLayers example</title>

</head>
<body>
<h2>OpenLayers tianditu web</h2>
<!--地图容器,需要指定 id -->
<div id="map" class="map"></div>

<script type="text/javascript">
    var map = new ol.Map({
        // 地图容器
        target: 'map',
        // 地图图层,比如底图、矢量图等
        layers: [
            getIMG_CLayer(),
            getIBO_CLayer(),
            getCIA_CLayer(),
        ],
        // 地图视野
        view: new ol.View({
            projection: "EPSG:4326",
            // 定位
            center: [115.67724700667199, 37.73879478106912],
            // 缩放
            zoom: 6,
            maxZoom: 18,
            minZoom: 1,
            // 注意,天地图地图等级 level 参数,需要设置为整数,否则会出错
            //1.设置缩放级别为整数
            constrainResolution: true,
            //2.关闭无级缩放地图
            smoothResolutionConstraint: false,
        })
    });

    // 初始化图层
    var layerVector = initVectorLayer();

    /**
     * @todo 矢量图层
     * @returns {VectorLayer}
     * @constructor
     */
    function initVectorLayer() {
        //实例化一个矢量图层Vector作为绘制层
        let source = new ol.source.Vector();
        //创建一个图层
        let customVectorLayer = new ol.layer.Vector({
            source: source,
            zIndex: 2,
        });
        //将绘制层添加到地图容器中
        map.addLayer(customVectorLayer);

        return customVectorLayer;
    }

    /**
     * @todo wkt格式数据转化成图形对象
     * @param {string} wkt   "POINT(112.7197265625,39.18164062499999)" 格式数据
     * @param {string|Projection} sourceCode 源投影坐标系
     * @param {string|Projection} targetCode 目标投影坐标系
     * @returns {Feature}
     */
    function getFeatureByWKT(wkt, sourceCode, targetCode) {
        try {
            let view = map.getView();
            if (!wkt) {
                return null;
            }
            let format = new ol.format.WKT();

            let feature;

            feature = format.readFeature(wkt, {
                featureProjection: targetCode || view.getProjection(),
                dataProjection: sourceCode || view.getProjection(),
            });

            return feature;
        } catch (e) {
            console.log(e);
            return null;
        }
    }

    /**
     * 获取样式
     * @param name
     * @returns {ol.style.Style}
     */
    function getStyle(name) {
        // 圆点样式
        return new ol.style.Style({
            image: new ol.style.Icon({
                // 允许跨域,如果不设置,打印地图不会打印
                crossOrigin: 'anonymous',
                // 标注图片和文字之间的距离
                anchor: [0.5, 0],
                // 图片的偏移
                offset: [0.2, 0],
                // 图片的锚点,一般来说,都是右下角
                anchorOrigin: 'bottom-right',
                //图标的url
                src: "http://api.tianditu.gov.cn/v4.0/image/marker-icon.png",
                //图标比例, 0.5 大概是25*34
                scale: 1,
            }),
            text: new ol.style.Text({
                text: name,
                // 偏移
                offsetX: 0,
                offsetY: -60,
                // 文字居中
                textAlign: 'center',
                // 字体
                font: 'normal bold  18px  Arial,sans-serif',
                // 比例
                scale: 1,
                // 边距
                padding: [5, 5, 5, 5],
                // 字体颜色
                fill: new ol.style.Fill({
                    color: 'rgba(51,51,51, 1)'
                }),
                // 字体边框,可以配合 fill 是文字高亮
                stroke: new ol.style.Stroke({
                    color: 'rgba(0, 255, 255, 0.8)',
                    width: 2,
                }),
                // 背景色
                backgroundFill: new ol.style.Fill({
                    color: 'rgba(252,254,255, 1)'
                }),
                // 背景边框
                backgroundStroke: new ol.style.Stroke({
                    color: 'rgba(0, 255, 255, 0.8)',
                    width: 1,
                }),
            })
        });
    }

    /**
     * 定位
     * @param layerTemp
     */
    function moveTo(layerTemp) {
        //定位范围
        map.getView().fit(layerTemp.getSource().getExtent(), {
            duration: 500,//动画的持续时间,
            callback: function () {
            },
        });
    }

    // 添加多个点,地名获取列表,将点叠加在地图上
    let addMarkerList = function (poi) {
        let arr = [];
        if (poi && poi.length > 0) {
            for (let i = 0; i < poi.length; i++) {

                const poiElement = poi[i];

                let xy = poiElement.lonlat.split(',');

                let feature = getFeatureByWKT('POINT(' + xy[0] + ' ' + xy[1] + ')');

                feature.setStyle(getStyle(poiElement.name));

                arr.push(feature)
            }
        }

        layerVector.getSource().addFeatures(arr);

        moveTo(layerVector);
    }

    // 添加点
    let addMarker = function (result) {

        let x = result.location.lon;
        let y = result.location.lat;

        let feature = getFeatureByWKT('POINT(' + x + ' ' + y + ')');

        // 如果有面图形要素,则加载;主要是行政区划的边界。
        let featurePolygon = result.location.polygon && getFeatureByWKT(result.location.polygon);

        feature.setStyle(getStyle(result.formatted_address || result.location.keyWord))

        layerVector.getSource().addFeatures([feature]);

        featurePolygon && layerVector.getSource().addFeatures([featurePolygon]);

        moveTo(layerVector);
    }

    //显示导航位置
    let addLine = function (responseData) {

		// 导航数据为 xml 格式
        let temp = $(responseData).find('routelatlon').text();

		// 拼接 wkt 格式
        while (temp.indexOf(',') != -1) {
            temp = temp.replace(',', ' ');
        }
        while (temp.indexOf(';') != -1) {
            temp = temp.replace(';', ',');
        }

        temp = temp.substring(0, temp.length - 1);

        temp = 'LINESTRING(' + temp + ')';

        let feature = getFeatureByWKT(temp);

        //渐变色线
        let styleLine = [];
        let steps = 10;
        // 渐变色原理,其实就是多个样式共同使用
        for (let i = 0; i < steps; i++) {
            styleLine.push(
                new ol.style.Style({
                    stroke: new ol.style.Stroke({
                        color: [0, 255, 255, 1 / (steps - i)],
                        width: (steps - i) * 2 - 1
                    }),
                })
            );
        }

        feature.setStyle(styleLine);
        layerVector.getSource().addFeatures([feature]);

        moveTo(layerVector);
    }

    // 关键字查询列表,根据关键字获取列表数据
    function searchKeyword() {

        // 清除上一次叠加对象
        layerVector && layerVector.getSource().clear();

        $.ajax({
            url: 'http://api.tianditu.gov.cn/v2/search',
            type: 'get',
            contentType: "application/json;charset=UTF-8", //指定消息请求类型
            data: {
                // 注意参数格式
                postStr: JSON.stringify({
                    // 关键字
                    "keyWord": $('#searchKeywordQuery').val(),
                    // 地图等级,需要设置整数
                    "level": map.getView().getZoom(),
                    // 地图范围
                    "mapBound": map.getView().calculateExtent(map.getSize()).toString(),
                    // 查询类型
                    "queryType": '1',
                    // 分页
                    "start": '0',
                    "count": '10',
                }),
                type: 'query',
                // 请更换自己的 tk,此 tk 只能在当前域名下使用
                tk: '2b7cbf61123cbe4e9ec6267a87e7442f',
            },
            beforeSend: function () {
                layer.load(2, {
                    shade: [0.5, '#fff'] //0.1透明度的白色背景
                })
            },
            success: function (res, status) {

                layer.closeAll();

                res.pois && addMarkerList(res.pois);
            },
        });
    }

    // 地理编码查询,根据关键字查询坐标
    function searchName() {

        // 清除上一次叠加对象
        layerVector && layerVector.getSource().clear();

        $.ajax({
            url: 'http://api.tianditu.gov.cn/geocoder',
            type: 'get',
            contentType: "application/json;charset=UTF-8", //指定消息请求类型
            data: {
                // 注意参数格式
                ds: JSON.stringify({
                    // 关键字
                    "keyWord": $('#searchNameQuery').val(),
                }),
                type: 'query',
                // 请更换自己的 tk,此 tk 只能在当前域名下使用
                tk: '2b7cbf61123cbe4e9ec6267a87e7442f',
            },
            beforeSend: function () {
                layer.load(2, {
                    shade: [0.5, '#fff'] //0.1透明度的白色背景
                })
            },
            success: function (res, status) {

                layer.closeAll();

                res = JSON.parse(res);

                res.location && addMarker(res);
            },
        });
    }

    // 地理逆编码查询,根据坐标查询名称
    function searchCoordinate() {

        // 清除上一次叠加对象
        layerVector && layerVector.getSource().clear();

        let coordinates = $('#searchCoordinateQuery').val().split(',');

        $.ajax({
            url: 'http://api.tianditu.gov.cn/geocoder',
            type: 'get',
            contentType: "application/json;charset=UTF-8", //指定消息请求类型
            data: {
                // 注意参数格式
                postStr: JSON.stringify({
                    // 坐标
                    "lon": coordinates[0],
                    "lat": coordinates[1],
                    "ver": 1
                }),
                type: 'geocode',
                // 请更换自己的 tk,此 tk 只能在当前域名下使用
                tk: '2b7cbf61123cbe4e9ec6267a87e7442f',
            },
            beforeSend: function () {
                layer.load(2, {
                    shade: [0.5, '#fff'] //0.1透明度的白色背景
                })
            },
            success: function (res, status) {

                layer.closeAll();

                res = JSON.parse(res);

                res.result && addMarker(res.result);
            },
        });
    }

    // 行政区别,根据关键字查询行政区划信息;包括名称、类型(省市)、范围等
    function searchGovernment() {

        // 清除上一次叠加对象
        layerVector && layerVector.getSource().clear();

        $.ajax({
            url: 'http://api.tianditu.gov.cn/administrative',
            type: 'get',
            async: false,
            contentType: "application/json;charset=UTF-8", //指定消息请求类型
            data: {
                // 注意参数格式
                postStr: JSON.stringify({
                    // 关键字
                    "searchWord": $('#searchGovernmentQuery').val(),
                    "searchType": '1',
                    // 子项
                    "needSubInfo": 'false',
                    // 所有属性
                    "needAll": 'false',
                    // 边界属性,好像是不起作用
                    "needPolygon": 'true',
                    "needPre": '10',
                }),
                type: 'query',
                // 请更换自己的 tk,此 tk 只能在当前域名下使用
                tk: '2b7cbf61123cbe4e9ec6267a87e7442f',
            },
            beforeSend: function () {
                layer.load(2, {
                    shade: [0.5, '#fff'] //0.1透明度的白色背景
                })
            },
            success: function (res, status) {

                layer.closeAll();

                if (res && res.data && res.data.length > 0) {

					// 拼接通用方法参数
                    let location = {};

					// 坐标
                    location.lon = res.data[0].lnt;
                    location.lat = res.data[0].lat;
                    
					// 名称
                    location.keyWord = res.data[0].name;
                    
					// 四至范围
                    location.bound = res.data[0].bound.split(',');
                    
					// 类型(省市县)
                    location.adminType = res.data[0].adminType;

					// 拼接矩形(面状图形要素)
                    let polygon = 'POLYGON((' + location.bound[0] + ' ' + location.bound[1] + '' +
                        ',' + location.bound[2] + ' ' + location.bound[1] + ',' +
                        '' + location.bound[2] + ' ' + location.bound[3] + ',' +
                        '' + location.bound[0] + ' ' + location.bound[3] + ',' +
                        '' + location.bound[0] + ' ' + location.bound[1] + '))';

                    location.polygon = polygon;

                    res.data[0].location = location;

                    addMarker(res.data[0]);
                }
            },
        });
    }

    // 路径规划,根据出发地和目的地获取导航路径
    function searchRoute() {

        // 清除上一次叠加对象
        layerVector && layerVector.getSource().clear();

        $.ajax({
            url: 'http://api.tianditu.gov.cn/drive',
            type: 'get',
            contentType: "application/json;charset=UTF-8", //指定消息请求类型
            data: {
                // 注意参数格式
                postStr: JSON.stringify({
                    // 出发地
                    "orig": $('#searchRouteQuery1').val(),
                    // 目的地
                    "dest": $('#searchRouteQuery2').val(),
                    "style": '0',
                    "ver": 1
                }),
                type: 'search',
                // 请更换自己的 tk,此 tk 只能在当前域名下使用
                tk: '2b7cbf61123cbe4e9ec6267a87e7442f',
            },
            beforeSend: function () {
                layer.load(2, {
                    shade: [0.5, '#fff'] //0.1透明度的白色背景
                })
            },
            success: function (res, status) {

                layer.closeAll();
                
                res && addLine(res);
            },
        });
    }

</script>
<br/>
<br/>
<input type="text" id="searchKeywordQuery" value="西什库大街" placeholder="请输入地名查询..."/>
<button id="searchKeyword" onClick="searchKeyword()">关键字查询列表</button>
<br/>
<br/>
<input type="text" id="searchNameQuery" value="西什库大街31号院23" placeholder="请输入地名查询..."/>
<button id="searchName" onClick="searchName()">地理编码查询</button>
<br/>
<br/>
<input type="text" id="searchCoordinateQuery" value="116.37304,39.92594" placeholder="请输入 x y 查询..."/>
<button id="searchCoordinate" onClick="searchCoordinate()">地理逆编码查询</button>
<br/>
<br/>
<input type="text" id="searchGovernmentQuery" value="北京市" placeholder="请输入城市名称..."/>
<button id="searchGovernment" onClick="searchGovernment()">行政区别</button>
<br/>
<br/>
<input type="text" id="searchRouteQuery1" value="116.38301126947785,39.91934326306291" placeholder="请输入出发地..."/>
<input type="text" id="searchRouteQuery2" value="116.2813877343216,39.99109771862933" placeholder="请输入目的地..."/>
<button id="searchRoute" onClick="searchRoute()">路径规划</button>
</body>
</html>

在线示例

Openlayers 天地图Web服务:Openlayers-tianditu-web


网站公告

今日签到

点亮在社区的每一天
去签到