ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

openlayer制作专题图

2021-02-14 09:59:12  阅读:248  来源: 互联网

标签:专题 name openlayer ol popup key var new 制作


 

最近看了一份人民大学的报告,《中国城市政商关系排行榜2020》,https://new.qq.com/omn/20201230/20201230A0F3MY00.html。

讲的是中国各个城市的政商关系健康指数,决定拿这份报告中的数据,来做一份html的专题图。

数据是使用python脚本从腾讯地图webapi上获取的,前端页面使用的是高德地图瓦片。

效果如下:

 

一、数据获取

参考腾讯web api:https://lbs.qq.com/service/webService/webServiceGuide/webServiceDistrict

脚本:

import requests
import time
# 获取省code和省name列表
def getAllProvince(key):
    url = 'http://apis.map.qq.com/ws/district/v1/list?key='+key
    reponse = requests.get(url=url)
    reponse.encoding = 'utf-8'
    data = reponse.json()
    provincelist = []
    for r in data['result'][0]:
        provincelist.append(r['id']+'\t'+r['name'])
    return provincelist
# 获取省围栏
def getProvincePolygon(key,provinceCode):
    url = 'https://apis.map.qq.com/ws/district/v1/search?&keyword='+provinceCode+'&key='+key+'&get_polygon=2&max_offset=3000'
    print(url)
    reponse = requests.get(url=url)
    reponse.encoding = 'utf-8'
    data = reponse.json()
    print(data)
    path = data['result'][0][0]['polygon']
    polygonlist = []
    # 对响应结果进行差分解压,lng lat,lng lat,lng lat|lng lat……格式
    for p in path:
        print(p)
        ringlist = []
        pointnum = int(len(p)/2)
        for i in range(0,pointnum):
            ringlist.append(str(p[i*2])+' '+str(p[i*2+1]))
        polygonlist.append('POLYGON(('+','.join(ringlist)+'))')
    return polygonlist
key = '腾讯key'

healthlist = {'北京':86.33,'上海':81.84,'天津':62.73,'海南':51.43,'浙江':49.42,'山东':48.91,
              '广东':47.47,'江苏':45,'重庆':44.64,'福建':40.39,'贵州':38.4,'四川':36.74,'安徽':36.52,'广西':34.95,'江西':33.77,
              '湖北':31.56,'宁夏':28.82,'湖南':28.03,'辽宁':27.7,'山西':25.73,'内蒙古':25.27,'陕西':23.95,'西藏':23.94,'甘肃':22.56,'新疆':21.99,
              '青海':21.69,'河北':21.39,'吉林':21.16,'黑龙江':21.08,'河南':20.49,'云南':19.17}

f = open(r'province.txt','a',encoding='utf-8')
f.write('\t'.join(['code','name','health','polygon'])+'\n')
province_list = getAllProvince(key)
for p in province_list:
    code,name = p.split('\t')
    if healthlist.__contains__(name):
        health = healthlist[name]
    else:
        health = 0.0
    time.sleep(1)
    polygonlist = getProvincePolygon(key,code)
    for pl in polygonlist:
        print(pl)
        f.write('\t'.join([code,name,str(health),pl])+'\n')
f.close()

执行完脚本,获取的数据长这样:

 

二、数据转换

因为openlayer能直接识别geojson格式的数据,所以我们把这份数据转成geojson的就行。

打开QGIS,ctrl+L,打开数据源管理器,分隔文本文件,按照下面的设置,将province.txt文件添加到QGIS面板上。

 

因为openlayer默认的坐标系为EPSG:3857,既平面墨卡托投影坐标系,如果用EPSG:4326,既WGS84球面经纬度坐标系,会导致加载的底图瓦片变形。

所以我们要先将数据做个投影,转成平面的。

点选界面右下角,修改项目坐标系。

 

将项目坐标系修改为WGS 84/Pseudo-Mercator。

 

在图层面板上,选中图层province,右键导出,另存要素为。

 

 

矢量图层另存为中,将格式选为GeoJSON,坐标系参照系选为项目坐标参照系,点击ok,将文件存为GeoJSON格式。

 

GeoJSON文件可以拿文本文档打开。

三、前端

json.js:

var getFeatures = function(){

       var featureJson=province.geojson中的内容

       return featureJson;

}

openlayer_map.html:

<!DOCTYPE html>

<html lang="en">



<head>

    <meta charset="UTF-8">

    <title>各省/直辖市政商关系健康指数</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css">

    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>

    <script src="json.js" type="text/javascript"></script>

    <style type="text/css">

    #map,

    html,

    body {

        height: 100%;

        width: 100%;

    }



    .ol-popup {

        position: absolute;

        background-color: white;

        box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);

        padding: 15px;

        border-radius: 10px;

        border: 1px solid #cccccc;

        bottom: 12px;

        left: -50px;

        min-width: 100px;

    }



    .ol-popup:after,

    .ol-popup:before {

        top: 100%;

        border: solid transparent;

        content: " ";

        height: 0;

        width: 0;

        position: absolute;

        pointer-events: none;

    }



    .ol-popup:after {

        border-top-color: white;

        border-width: 10px;

        left: 48px;

        margin-left: -10px;

    }



    .ol-popup:before {

        border-top-color: #cccccc;

        border-width: 11px;

        left: 48px;

        margin-left: -11px;

    }



    .ol-popup-closer {

        text-decoration: none;

        position: absolute;

        top: 2px;

        right: 8px;

    }



    .ol-popup-closer:after {

        content: "✖";

    }

    </style>

</head>



<body>

    <div id="map"></div>

    <div id="popup" class="ol-popup">

        <a href="#" id="popup-closer" class="ol-popup-closer"></a>

        <div id="popup-content"></div>

    </div>

</body>

<script type="text/javascript">

//弹窗

var container = document.getElementById('popup');

var content = document.getElementById('popup-content');

var closer = document.getElementById('popup-closer');

var overlay = new ol.Overlay({

    element: container,

    autoPan: true,

    autoPanAnimation: {

        duration: 50,

    },

});

closer.onclick = function() {

    overlay.setPosition(undefined);

    closer.blur();

    return false;

};

var polygons = getFeatures();

var colors = ['#000000', '#001133', '#002266', '#003399', '#0044cc', '#0055ff', '#3377ff', '#6699ff', '#99bbff', '#ccddff', '#ffffff'];

var styleFunction = function(feature) {

    let colorHex = colors[10 - Math.round(parseFloat(feature.getProperties()['health']) / 10)];

    let colorRgba = 'rgba(' + parseInt('0x' + colorHex.slice(1, 3)) + ',' + parseInt('0x' + colorHex.slice(3, 5)) + ',' +

        parseInt('0x' + colorHex.slice(5, 7)) + ',' + 0.8 + ')'

    let stylePolygon = new ol.style.Style({

        fill: new ol.style.Fill({

            color: colorRgba,

        }),

    });

    return stylePolygon;

};



features = new ol.format.GeoJSON().readFeatures(polygons);

var vectorSource = new ol.source.Vector({

    features: features,

});

var vectorLayer = new ol.layer.Vector({

    source: vectorSource,

    style: styleFunction

});

//页面

var view = new ol.View({

    center: ol.proj.transform([112.273486, 35.719192], 'EPSG:4326', 'EPSG:3857'),

    zoom: 4

});



var layers = [

    // 加载高德瓦片底图

    new ol.layer.Tile({

        source: new ol.source.XYZ({

            url: "http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8"

        })

    }), vectorLayer

];

//地图

var map = new ol.Map({



    target: 'map', //指向div

    layers: layers,

    overlays: [overlay],

    view: view

});



// 单击选择控件

var selectSingleClick = new ol.interaction.Select({ style: styleFunction });

map.addInteraction(selectSingleClick);

selectSingleClick.on('select', function(e) {

    content.innerHTML = '<code>' + e.target.getFeatures().getArray()[0].getProperties()['name'] + '为:' + e.target.getFeatures().getArray()[0].getProperties()['health'] + '</code>';

    overlay.setPosition(e['mapBrowserEvent']['coordinate']);

});

</script>



</html>

四、总结

使用openlayer的人不多,但它应该是最底层的、最严格符合OGC WMS规范的地图前端了。

用openlayer做专题图是不太合适,但用它做绘制页面工具的开发是挺好的。

Openlayer不够轻量级,上手也难,但用它的时候,会觉得很专业、很标准、很严格。

Openlayer的各种样例:https://openlayers.org/en/latest/examples/

 

 

标签:专题,name,openlayer,ol,popup,key,var,new,制作
来源: https://blog.csdn.net/sinat_41310868/article/details/113805926

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有