设为首页收藏本站

EPS数据狗论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2324|回复: 2

基于OpenLayers的WebGIS实例:添加标记要素

[复制链接]

8

主题

287

金钱

363

积分

入门用户

发表于 2018-7-9 09:57:27 | 显示全部楼层 |阅读模式

作图需求,基于环杭州湾区城市间的产业链空间投影数据,用表格和数据反映城市间的联系,想要将这种城市间的产业关联表现在地图上,提供的城市间产业关联的数据(数值已做处理)如图1。

img01.jpg

接下来开始思考如何将该数据以地图的形式呈现出来。首先想到的是利用ArcGIS作图,但是本次作图是要表现要素(城市)间的关联性,如果在每个要素上添加一个饼状图,表现不直观而且没有方向感,如果手工划线勾箭头,或许可以实现,但不是本人的风格。


因此只能选择放弃ArcGIS,转而想到了OpenLayers——为WebGIS开发提供的JavaScript类库包,最好的开源地图引擎,用于实现标准格式发布的地图数据访问。OpenLayers灵活的地图表现形式,使我决定采用开发一个简单的WebGIS地图的方式来解决这个问题。


关于OpenLayers类库的介绍,本文不做具体说明,请查阅官方文档,我只负责丢链接——OpenLayers官方文档。


有了作图工具,然后思考作图总体思路,也就是要做出什么效果的图。设想如下:对于每个中心城市,选择一到两个关联度大的指向城市,用线条和箭头的方式表达城市间的相关性,线条粗细和颜色深浅代表关联度的大小(关联度大,线段粗,颜色深,颜色的作用是有层次感,便于识别),线段中间(或一侧)的箭头是流向方向,用黄色阴影表示流向的目的地,流入的越多,阴影部分越大。


下面介绍具体的实现方法。


1.数据准备及处理


本次任务需要准备的数据包括:


原始城市产业关联数据,格式为Excel;


地图底图,包括中国省级行政区划、地市级行政区划等矢量要素、河流水网(可选)等数据。


对于原始城市产业关联数据,可编码为JSON数据格式,方便后期数据读取和使用,格式示例如图2,其中,城市用首字母简单代替,“city”是中心城市,“neighbors”代表指向城市,“rv”表示关联度。

img02.jpg

由于任务需求简单,本次作图不采用在线地图发布服务,使用QGIS工具(create web map插件)将ShapeFile矢量地图转换为可支持OpenLayers离线加载的GeoJSON数据格式。利用QGIS的该插件,可以直接将矢量地图发布为WebGIS,如图3,方便后续处理。

img03.jpg

2. WebGIS编程开发


文档组织结构如图4所示。data存储数据等,images存储开发过程所需的图片素材,layers、resources和styles存放基于OpenLayers的WebGIS地图基本要素。



网页开发的基础就不多介绍了,想要做WebGIS,一定要有网页开发的基础,HTML、JavaScript、css等语言要熟悉。


现在已经有了基本的地图底图,要把表示城市关联的线段和箭头添加上去,首先要加载城市关联度json数据,然后根据城市关系构建线段图层要素,再根据线段及方向添加箭头,下面是实现代码。



  1. // 加载关联度数据
  2. var relations = eval('relations_fz');

  3. // 创建OL要素集
  4. var flightsSource = new ol.source.Vector({
  5.         wrapX: false,
  6.         loader: function() {
  7.             for (var i = 0; i < relations.length; i++) {
  8.             // 获取城市和指向城市
  9.               var city = relations[i].city;
  10.               var neighbors = relations[i].neighbors;
  11.                
  12.               var from = city_coords[city];

  13.               // 在两个地点之间创建弧线要素
  14.               for (var j = 0; j < neighbors.length; j++) {
  15.                   var to = city_coords[neighbors[j]]
  16.                   var arcGenerator = new arc.GreatCircle(
  17.                       {x: from[0], y: from[1]},
  18.                       {x: to[0], y: to[1]});

  19.                   var arcLine = arcGenerator.Arc(10, {offset: 10});
  20.                   if (arcLine.geometries.length === 1) {
  21.                     var line = new ol.geom.LineString(arcLine.geometries[0].coords);
  22.                     line.transform(ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
  23.                      
  24.                     var feature = new ol.Feature({
  25.                       geometry: line
  26.                        
  27.                     });
  28.                      
  29.                     var dx = to[0] - from[0];
  30.                     var dy = to[1] - from[1];
  31.                     // 在线段的3/4处添加箭头,计算箭头的角度
  32.                     var mx = from[0] + (to[0] - from[0]) / 4. * 3.;
  33.                     var my = from[1] + (to[1] - from[1]) / 4. * 3.;
  34.                     var rotation = Math.atan2(dy, dx);
  35.                      
  36.                     // arrows
  37.                     point = new ol.geom.Point(to);
  38.                     point.transform(ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
  39.                      
  40.                     arrow_point = new ol.geom.Point([mx, my]);
  41.                     arrow_point.transform(ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
  42.                      
  43.                     var arrow_feature = new ol.Feature({
  44.                       geometry: arrow_point
  45.                     });
  46.                      
  47.                     var point_feature = new ol.Feature({
  48.                       geometry: point
  49.                     });
  50.                      
  51.                     // 设置显示格式,根据输入数据动态调整线条粗细、透明度和箭头大小等
  52.                     style_l = new ol.style.Style({
  53.                                     stroke: new ol.style.Stroke({
  54.                                         color: 'rgba(135, 20, 0, ' + relations[i].rv[j] * 3 + ')',
  55.                                         width: relations[i].rv[j] * 80
  56.                                     })
  57.                                 })
  58.                     style_p = new ol.style.Style({
  59.                                   image: new ol.style.Icon({
  60.                                       src: './images/point.png',
  61.                                       anchor: [1, 0.5],
  62.                                       rotateWithView: true,
  63.                                       scale: relations[i].rv[j] * 0.75
  64.                                     })
  65.                                 })
  66.                     style_ap = new ol.style.Style({
  67.                                   image: new ol.style.Icon({
  68.                                       src: './images/arrow.png',
  69.                                       anchor: [0.5, 0.5],
  70.                                       rotateWithView: true,
  71.                                       rotation: -rotation,
  72.                                       scale: relations[i].rv[j] * 0.3
  73.                                     })
  74.                                 })
  75.                                  
  76.                     // 添加至OL要素集
  77.                     feature.setStyle(style_l);
  78.                     point_feature.setStyle(style_p);
  79.                     arrow_feature.setStyle(style_ap);
  80.                  
  81.                     flightsSource.addFeature(point_feature);
  82.                     flightsSource.addFeature(arrow_feature);
  83.                     flightsSource.addFeature(feature);
  84.                   }
  85.               }
  86.             }
  87.             //map.on('postcompose', animateFlights);
  88.         }
  89.       });
  90.       
  91. // 添加至地图
  92. var flightsLayer = new ol.layer.Vector({
  93.     source: flightsSource,
  94. });
  95. map.addLayer(flightsLayer);
  96.    
复制代码

然后设置地图要素的Style,以城市样式为例。
  1. var styleCache_={}
  2. var style_province = function(feature, resolution){
  3.     var value = ""
  4.     var style = [ new ol.style.Style({
  5.         stroke: new ol.style.Stroke({color: '#555', lineDash: [1,2,3,4,5,6], lineCap: 'square', lineJoin: 'bevel', width: 1.5}),
  6.     })];
  7.     if ("" !== null) {
  8.         var labelText = String("");
  9.     } else {
  10.         var labelText = ""
  11.     }
  12.     var key = value + "_" + labelText

  13.     if (!styleCache_[key]){
  14.         var text = new ol.style.Text({
  15.               font: '10px \'None\', sans-serif',
  16.               text: labelText,
  17.               textBaseline: "center",
  18.               textAlign: "left",
  19.               offsetX: 5,
  20.               offsetY: 3,
  21.               fill: new ol.style.Fill({
  22.                 color: 'rgba(None, None, None, 255)'
  23.               }),
  24.             });
  25.         styleCache_[key] = new ol.style.Style({"text": text})
  26.     }
  27.     var allStyles = [styleCache_[key]];
  28.     allStyles.push.apply(allStyles, style);
  29.     return allStyles;
  30. };
复制代码


至此,WebGIS地图制作完成,可以交差了,本次任务结束。

转自 gaohr.win

24

主题

704

金钱

2709

积分

中级用户

发表于 2018-7-14 21:23:49 | 显示全部楼层
thanks for sharing, learnt a lot!
回复 支持 反对

使用道具 举报

0

主题

1061

金钱

5697

积分

高级用户

发表于 2018-7-24 14:55:31 | 显示全部楼层
谢谢您的分享!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

意见反馈|网站地图|手机版|小黑屋|EPS数据狗论坛 ( 京ICP备09019565号-3 )   

Powered by BFIT! X3.4

© 2008-2028 BFIT Inc.

快速回复 返回顶部 返回列表