• OpenLayers 3 地图图层(Layers) 详解


    2015-04-30 18:41  998人阅读  评论(1)  收藏  举报
    0
      分类:
    WebGIS(28) 
    0
    OpenLayers(17) 
    0
    版权声明:本文为博主原创文章,未经博主允许不得转载。
    目录(?)[+]
    声明:文章为本人原创,转载或使用请注明作者和出处!!谢谢!
          如果不是专业的地图工作者,看到地图,可能觉得地图就是一张将三维世界映射到二维空间,很多信息混杂在一起表示空间信息的动态可交互图片,其实这只是表面现象。实际上地图是由一个或多个图层组成的,使用不同的图层存储不同类型的地物,比如由存储道路的图层,有展示拥堵情况的图层,通常还有一个含有基础地理信息(比如政区划分)的底图图层。
          在 OpenLayers 中,图层是使用 layer 对象表示的,主要有 热度图层(heatmaplayer)、图片图层(imagelayer)、切片图层(tilelayer) 和矢量图层(vectorlayer) 四种类型,它们都是继承 Layer 类的。
    1、Layer 类
          OpenLayers 初始化一幅地图(map),至少需要一个可视区域(view),一个或多个图层( layer), 和 一个地图加载的目标 HTML 标签(target),其中最重要的是图层( layer)。
    在 这里 可以看到 layer 类的定义,类的描述如下:
    /** 
    * @classdesc 
    * Abstract base class; normally only used for creating subclasses and not 
    * instantiated in apps. 
    * A visual representation of raster or vector map data. 
    * Layers group together those properties that pertain to how the data is to be 
    * displayed, irrespective of the source of that data. 
    */
    layer 是一个虚基类,只用于让子类型继承和实现,自身不能实例化。主要功能是对 矢量地图数据 和 栅格地图数据的可视化表达。图层的外观,主要与数据渲染方式有关,与数据的来源关系不大。
    初始化时,传入的参数有:
    • brightness,亮度,默认为 0 ;
    • contrast,对比度,默认为 1 ;
    • hue,色调,默认为0 ;
    • opacity,透明度,默认为 1 ,即完全透明;
    • saturation,饱和度,默认为 1 ;
    • source,图层的来源,如果在构造函数中没有传入相应的参数,可以调用 ol.layer.Layer#setSource方法来设置来源: layer.setSource(source) ;
    • visible,是否可见,默认为 true ;
    • extent,图层渲染的区域,即浏览器窗口中可见的地图区域。extent 是一个矩形范围,格式是[number, number, number, number] 分别代表[left, bottom, right, top] 。如果没有设置该参数,图层就不会显示;
    • minResolution,图层可见的最小分辨率,当图层的缩放级别小于这个分辨率时,图层就会隐藏;
    • maxResolution,图层可见的最大分辨率,当图层的缩放级别等于或超过这个分辨率时,图层就会隐藏。
    包含的共有方法有: 
    - getLayersArray( ),得到所有图层组成的数组; 
    - getLayerStatesArray( ),得到所有图层状态组成的数组; 
    - getSource( ),得到相应图层的来源; 
    - getSourceState( ),得到相应图层的来源状态; 
    - handleSourceChange_( ),处理 source 变动的函数; 
    - handleSourcePropertyChange_( ),处理 source 属性变动的函数; 
    - setSource( ),设置图层 source 属性,参数为一个 source 对象。
    包含的私有方法有: 
    - visibleAtResolution( ),参数是 layerState 和 resolution,如果图层可见,返回 true ,如果传入了 resolution,也会比较 resolution 是否在 minResolution 和 maxResolution 之间。
    在构造函数传入的参数中,source 是一个比较重要的属性,没有它,图层就没有实质性内容,这个 source 是什么呢,打开 ol.source 目录可以看到,有一个 source 基类,其余都是继承其的子类,这些子类非常的多:
    • imagesource.js(imagelayer的图层来源基类)
    • imagecanvassource.js
    • imagemapguidesource.js
    • imagestaticsource.js
    • imagevectorsource.js
    • imagewmssource.js
    • tilesource.js(切片图层 – tilelayer的来源基类)
    • tilearcgisrestsource.js
    • tiledebugsource.js
    • tilejsonsource.js
    • tileutfgridsource.js
    • tilevectorsource.js
    • tilewmssource.js
    • tileimagesource.js 
    • zoomifysource.js
    • wmtssource.js,具有 WMTS 功能的服务器的发布的切片图层
    • bingmapssource.js,bingmaps也是属于切片图层类型,因为微软提供的是切片
    • xyzsource.js,一个具有 XYZ 格式的数据集 
    • mapquestsource.js
    • osmsource.js
    • stamensource.js
    • vectorsource.js(vectorlayer的图层来源基类)
    • clustersource.js
    • wmssource.js,包含了 geoserver 、geoserver 、geoserver 和 geoserver 等,这些地图服务器发布的基于 WMS 协议的图层服务
    地图图层数据的来源有很多,同时格式也各异。实际应用,应该根据实际情况进行选择。
    2、各类图层类型
          在 OpenLayers 3.x 中的 Layer 类型包括 heatmaplayer、imagelayer、tilelayer 和 vectorlayer 四种类型,它们都继承了 ol.layer.Layer 类,监听和触发的事件都在 ol.render.Event 中定义,共用的属性和状态都是在 layerbase 中定义的,它们除了从ol.layer.Layer 类继承而来的参数外,还定义了自己的属性和方法。下面我们来分别看看这几个图层类型。
    PS: 我们基于以前的代码,在 OpenLayers之使用AJAX 中有下载源码链接,修改 map_utils.js 中的 map 来查看效果。
          不管使用什么图层类型,初始化 map 同时,如果不明确指定 control 对象,那么就会默认包含 缩放 和 鼠标拖拽 功能,关于这个 Control 对象,在后面的博客中会讲到,现在认为 Control 就是一个控制与地图交互的工具就好。
    2.1 heatmaplayer
          将矢量数据渲染成热度图的类,继承了 ol.layer.Vector 类,ol.layer.Vector 继承了ol.layer.Layer 类, 额外的参数是 olx.layer.HeatmapOptions,其定义如下:
    /** * @enum {string} */ ol.layer.HeatmapLayerProperty = {   BLUR: 'blur',   GRADIENT: 'gradient',   RADIUS: 'radius' };
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
        注意到 heatmap 图层比起其它类型的图层多了三个属性,常用的是 blur 和 radius,这两个属性什么作用呢,我们可以调整一下看看效果:
     
    0
     
    没错,blur 控制圆点的边缘,对边缘做模糊化; radius 则规定了圆点的半径。注:并不是点,而是圆。
    2.1.1实例
    首先创建一个 heatmaplayer 对象:
    var vector = new ol.layer.Heatmap({   source: new ol.source.KML({     url: 'data/kml/2012_Earthquakes_Mag5.kml',     projection: 'EPSG:3857',     extractStyles: false }),   blur: parseInt(blur.value, 10),   radius: parseInt(radius.value, 10) });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    这里 heatmap 使用KML格式,本地文件data/kml/2012_Earthquakes_Mag5.kml 作为 heatmap 的来源,数据是2012年全球地震发生的位置和震级等简单的描述信息,然后将 heatmap 图层加到 map 中:
    map = new ol.Map({ //初始化map target: 'map',     layers: [ new ol.layer.Tile({         source: new ol.source.MapQuest({layer: 'sat'})       }),       heatmap     ],     view: new ol.View({       center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),       zoom: 4 }) }); 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    查看运行效果:
     
    0
     
    2.2 imagelayer
          主要是指服务器端渲染的图像,可能是已经渲染好的图像,或者是每一次请求,都根据请求内容定制化地生成一幅图片,该图层类型支持任意的范围和分辨率。
    2.2.1 实例
    首先实例化一幅图片图层:
    /** * create an imageLayer */ var extent = [0, 0, 3264, 2448]; var projection = new ol.proj.Projection({             code: 'EPSG:4326',             extent: extent         }), var imageLayer = new ol.layer.Image({     source: new ol.source.ImageStatic({         url: 'sample.jpg',         projection: projection,         imageExtent: extent     }) })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
            与 heatmap 一样,首先需要传入 URL 参数,即图片地址,这里可以是网络图片的地址,或者是本地的文件地址;然后需要传入参考坐标系 projection,code 是一个标识,可以是任何字符串,如果是EPSG:4326 或者是 EPSG:3857 ,那么就会使用这两个坐标系,如果不是,就使用默认的坐标系,extent 是一个矩形范围,上面已经提到;imageLayer 的第三个参数是 imageExtent 表示图片的尺寸,这里我们不能改变图片的原来的比例,图片只会根据原来的比例放大或缩小。
    最后将 imageLayer 加到地图中:
    map = new ol.Map({ //初始化map target: 'map',     layers: [ imageLayer ], view: new ol.View({ projection: projection, center: ol.extent.getCenter(extent), zoom: 2 }) }); 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    效果如下:
     
    0
     
    放大之后感觉很像必应搜索的界面的感觉,有木有 ^_^|:
     
    0
     
    2.3 tilelayer
          切片地图是比较常用的图层类型,切片的概念,就是利用网格将一幅地图切成大小相等的小正方形,如图:
     
    0
     
    这样就明白我们使用百度地图等地图时为什么网速慢时候,会一块一块的加载的原因了吧!对,因为是切片。
          当请求地图的时候,会请求视口(也就是浏览器可见的区域)可见的区域内包含的切片,其余的切片不会请求,这样就节省了网络带宽,而且一般这些切片都是预先切好的,且分为不同的缩放级别,根据不同的缩放级别分成不同的目录。如果将这些切片地图放到缓存中,那访问速度会更快。
    继承了 ol.layer.Layer ,额外的参数是 olx.layer.TileOptions ,其定义如下:
    /** 
    * @typedef {{brightness: (number|undefined), 
    * contrast: (number|undefined), 
    * hue: (number|undefined), 
    * opacity: (number|undefined), 
    * preload: (number|undefined), 
    * saturation: (number|undefined), 
    * source: (ol.source.Tile|undefined), 
    * visible: (boolean|undefined), 
    * extent: (ol.Extent|undefined), 
    * minResolution: (number|undefined), 
    * maxResolution: (number|undefined), 
    * useInterimTilesOnError: (boolean|undefined)}} 
    * @api 
    */
          可以看出,多出了 preload 和 useInterimTilesOnError 两个参数,preload 是在还没有将相应分辨率的渲染出来的时候,将低分辨率的切片先放大到当前分辨率(可能会有模糊),填充到相应位置,默认是 0,现在也就明白了当网速慢时,为什么地图会先是模糊的,然后再变清晰了吧,就是这个过程!useInterimTilesOnError是指当加载切片发生错误时,是否用一个临时的切片代替,默认值是 true。
    2.3.1 实例
    其实在 加载地图的例子 中,我们就是请求 MapQuest 的切片地图:
    map = new ol.Map({ //初始化map target: 'map',     layers: [ new ol.layer.Tile({         source: new ol.source.MapQuest({layer: 'sat'})       })     ],     view: new ol.View({       center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),       zoom: 2 }) }); 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    其中的 ol.layer.Tile 就是切片图层类型,来源是 MapQuest ,layer 
    是请求的图层的类型, MapQuest 有三种类型的图层:osm, sat 和 hyb ,osm 就是 OpenStreetMap 的缩写,是其提供的数据, sat 是卫星图,hyb是两种类型的混合图层。
    我们可以查看一下浏览器的网络请求内容:
     
    0
     
    这里是 Firefox 浏览器的 Firebug 网络请求面板,可见其请求的图片,是一块块的,且是基于一定的编号规则进行编号的。
    2.4 vectorlayer
          在 OpenLayers之使用Vector Layer 中曾经使用过,即矢量图层,矢量图层实际上是在客户端渲染的图层类型,服务器返回的数据或者文件会通过 OpenLayers 进行渲染,得到相应的矢量图层。
    在客户端渲染的矢量数据图层,继承了 ol.layer.Layer ,额外的参数是 olx.layer.VectorOptions ,其定义如下:
    > /** * @typedef {{brightness: (number|undefined), * contrast: (number|undefined), * renderOrder: (function(ol.Feature, ol.Feature):number|null|undefined), * hue: (number|undefined), * minResolution: (number|undefined), * maxResolution: (number|undefined), * opacity: (number|undefined), * renderBuffer: (number|undefined), * saturation: (number|undefined), * source: (ol.source.Vector|undefined), * style: (ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined), * updateWhileAnimating: (boolean|undefined), * updateWhileInteracting: (boolean|undefined), * visible: (boolean|undefined)}} * @api */
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
          相对于一般的图层,多出了 renderOrder、renderBuffer、style、updateWhileAnimating 和 updateWhileInteracting 五个参数。renderOrder 是指渲染地理要素时的顺序,一般情况下,在渲染之前,要素是基于一定规则排序的,而渲染就是根据这个顺序进行依次渲染的,这个参数便指定了这个排序规则,如果赋值为 null ,那么就不会对地理要素进行排序,渲染也不会有一定的顺序;renderBuffer 表示地图的视口区域的缓冲区;style 规定了矢量图层的样式,就是配色和形状等等;updateWhileAnimating 表示当有动画特效时,地理要素是否被重新创建,默认是 false,当设置为 true 时,可能会对性能有所影响;updateWhileInteracting 表示当 地理要素 交互时,是否会被重新渲染。
    2.4.1 实例
    首先创建一个 矢量图层:
    vectorLayer = new ol.layer.Vector({ //初始化矢量图层 source: new ol.source.GeoJSON({     projection: 'EPSG:3857',     url: 'data/geojson/countries.geojson' //从文件加载边界等地理信息 }),   style: function(feature, resolution) { style.getText().setText(resolution < 5000 ? feature.get('name') : ''); //当放大到1:5000分辨率时,显示国家名字 return [style];   } });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    服务器返回的 GeoJSON 格式的文件 data/geojson/countries.geojson 包含国家的边界数据,属于多边形类型,经过 OpenLayers 渲染之后得到结果如下:
     
    0
     
    可以看到蓝色的线为各个国家的边界,当鼠标在某个国家上方时,相应的区块会变红色,这是添加的事件,我们可以改变其样式,注意到 vectorlayer 相对于其他类型的图层,还包含了一个 style 参数,这个参数便是控制矢量图层的外观样式的,其定义如下:
    /** * 定义矢量图层 * 其中style是矢量图层的显示样式 */ var style = new ol.style.Style({   fill: new ol.style.Fill({ //矢量图层填充颜色,以及透明度 color: 'rgba(255, 255, 255, 0.6)' }),   stroke: new ol.style.Stroke({ //边界样式 color: '#319FD3',      1 }),   text: new ol.style.Text({ //文本样式 font: '12px Calibri,sans-serif',     fill: new ol.style.Fill({       color: '#000' }),     stroke: new ol.style.Stroke({       color: '#fff',        3 })   }) });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    style 是一个 ol.style.Style 类型,矢量图层是可以调节透明度的,如下:
    fill: new ol.style.Fill({ //矢量图层填充颜色,以及透明度 color: 'rgba(255, 255, 255, 0.6)' })
    • 1
    • 2
    • 3
    rgba 的最后一个变量就是控制透明度的变量,范围是 0~1,0 表示不透明,1 代表完全透明。因为这里主要讲 Layer,所以关于 ol.style.Style 其它的内容,这里就不多说了。
    3、讨论
          现在非常流行的地图,如百度地图或者高德地图提供的是什么layer类型呢?我们来分别看看它们在 Firefox 看到的网络请求图:
    百度地图: 
    0
     
    高德地图: 
    0
     
    通过上面的讨论,我们可以得出结论,它们都是提供的网络切片图层类型,而一些加载的地理要素,如酒店等,便是加载在一个矢量图层中的,所以说,它们是混杂着切片图层和矢量图层的。
    4、总结
          其实图层可以按照渲染的位置分为两类,一类是在服务器端渲染好,以图片形式返回浏览器的, imagelayer 和 tilelayer 都是属于这种类型;另一类是在浏览器渲染的图层类型,vectorlayer 和 heatmaplayer 就是这种类型。
    OK,终于写完了,好累好累!
     
     
    2015-11-27 12:15  149人阅读  评论(0)  收藏  举报
    0
      分类:
    OpenLayers(17) 
    0
    WebGIS(28) 
    0
    版权声明:本文为博主原创文章,未经博主允许不得转载。
    目录(?)[+]
          在 openlayers 2中,是默认有切换图层控件的,但是由于某种原因,openlayers 3中并没有默认实现,但却给我们很容易扩展的基类(ol.control.Control),我们可以自定义实现,并不是很难,这我会在其他文章中讲解。这篇文章中,我利用一个 GitHub 中的一个开源项目(这个项目就是扩展了ol.control.Control,自定义了切换图层控件),添加切换图层控件,并探索其用法。
          具体的原理及其实现在这篇文章中我就不讲了,想看怎么具体实现的,可以期待一下我的下一篇文章,主要分析怎么继承 ol.control.Control 类,并自定义自己的控件,初定以切换图层控件为例。
    GitHub已有的“轮子”
          在发现 openlayers 3中并没有默认的图层切换控件时,首先想到看看有没有人实现过呢?自己造轮子,虽然有成就感,但是会投入更多的时间成本和精力,在生产环境中,这往往不允许。如果有人实现过,我就可以借鉴一下,不必自己实现,但是并不一定符合自己的应用环境,对此我们了解其实现,按照自己的需求进行修改,当然我们要注意其遵守的开源协议。
          搜索 GitHub ,已经有一个项目实现了我们需要的控件,地址在这里: ol3-layerswitcher 。下载好最新的版本,解压,src子文件夹中有其 javascript 和 css 文件,分别在网页中相应位置添加引用。
    0
     <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>ol3-layers-witchertitle> <link rel="stylesheet" href="css/ol.css" type="text/css"> <link rel="stylesheet" href="css/common-setting.css" type="text/css"> head> <body style="margin:0 0 0 0; padding:0 0 0 0;"> <div id="map" style=" 100%; height: 100%;">div> <script type="text/javascript" src="js/ol.js">script> <script type="text/javascript" src="js/ol3-layerswitcher.js">script> <script type="text/javascript" src="layer-switcher.js">script> body> html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    使用方法
    图层title属性
          要使用该方法,必须在每个图层添加一个 title 属性,ol3-layerswitcher 会根据图层的 title 属性的值,显示在 layerswitcher 控件中。如下示例,“天地图路网”这几个字会显示到 layer-switcher 中:
    var tian_di_tu_road_layer = new ol.layer.Tile({     title: "天地图路网",     source: new ol.source.XYZ({         url: "http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}" }) });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    0
    tipLabel 属性
          layer-switcher 相对于 ol.control.Control基类,只添加了一个属性 – tipLabel,这个属性是一个字符串,默认是 Legend,当鼠标位于控件之上时,会有提示文字,就是这里的 tipLabel的值,其实这个值是通过设置 html button元素的title 属性实现的。如我把 tipLabel设置为 切换图层,那么在鼠标置于图标时会有下面的效果:
    0
    调整控件样式
          控件没有展开的时候,默认图标是 openlayers 3 的图标,如果我们想换一个,就要修改其在 CSS 文件中(ol3-layerswitcher.css)的 background-image 定义,如下图:
    0
          指定的值是 base64 格式的图片 url,我们可以使用 HTML5 的 canvas API 将普通图片转换成 base64 表示形式,如下的我写的函数就是转换普通的图片为 base64 格式的表示,并返回。使用时,将待转换的图片的url路径,想要输出的图片尺寸,传递给函数作为参数:
    function convertImageToBase64(url, height, width){ var img = new Image();     img.crossOrigin = 'Anonymous';     img.onload = function(){ var canvas = document.createElement('CANVAS'); var ctx = canvas.getContext('2d'); var dataURL;         canvas.height = height;         canvas.width = width;         ctx.drawImage(this, 0, 0, height, width);         dataURL = canvas.toDataURL('image/png'); return dataURL;     };     img.src = url; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
          还有一些其它的属性,比如控件默认放置的位置,也在 ol3-layerswitcher.css 中定义,控件使用的 CSS 绝对定位,默认离右边 0.5 em,离顶部 3.5 em,我们可以修改 top、right,或者增加 bottom、left 等属性来修改放置的位置。
    .layer-switcher { position: absolute; top: 3.5em; right: 0.5em; text-align: left; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    总结
          讲到这里,你已经基本会用了吧!当然,如果你想要进一步修改其样式,就要深入的了解其 CSS 文件(你应该有一点CSS基础知识),对其进行更深入的定制化;如果你想扩展或自定义这个控件的功能或者增加其监听的事件,那么你需要研究其实现:ol3-layerswitcher.js。使用一个开源项目,不是说,你就不必关心怎么去实现了,而是应该了解其实现原理,否则,慢慢就变成了‘井底之蛙’,别人有,你会用,别人没有,你就没办法了。
    文章中例子的完整代码,我放在了 GitHub 中,想看的朋友可以到 这个链接 看一下: https://github.com/QingyaFan/openlayers3-examples 。
    好的,就写到这里,有什么问题,可以在文章下面留言或者给我发邮件。
     
     
     OpenLayers 3 之 使用矢量图层(Vector)
     
    2015-03-27 14:43  436人阅读  评论(0)  收藏  举报
    0
      分类:
    WebGIS(28) 
    0
    OpenLayers(17) 
    0
    版权声明:本文为博主原创文章,未经博主允许不得转载。
    摘要
            矢量图层:矢量图层是用来渲染矢量数据的图层类型,在OpenLayers里,它是可以定制的,可以控制它的透明度,颜色,以及加载在上面的要素形状等。
            常用于从数据库中请求数据,接受数据,并将接收的数据解析成图层上的信息。如将鼠标移动到中国,相应的区域会以红色高亮显示出来,高亮便是矢量图层的行为。
     
    主要内容
    1、 HTML文件的进化
            这次添加矢量图层,如果再独自写一个JS文件,就得在引用一个外部JS文件,如果后续再加一个功能,那么就会越来越多的JS文件,不免造成JS文件之间造成干扰,比如说命名冲突等,所以就直接将功能写在以前的JS文件中(popup.js),并将其更名为“map_utils.js”,意为地图工具集!
            首先我们在HTML中原来存留的JavaScript移动到map_utils.js文件中,因为做到表观层和逻辑层分离,是一个很重要的事情,便于后期的管理。之所以之前没有一步就那么做,是为了让大家意识到 -- 过早优化没有必要,怎么实现方便,就先做,避免过度考虑。有一句话说的好:“一个思想过度的人,行动非常软弱!”。
            同时,我们将CSS也分离到一个单独的文件中 – map_style.css,这样,现阶段,就比较容易维护了,别忘了添加引用CSS的语句哦。
            我们并不用对HTML页做其它的修改了,因为矢量图层是一个图层,是从属于Map对象的(注:一个map可以包含很多layer,layer包含底图和一般图层)。
            修改后的HTML页面如下:
     
    [html]  view plain copy
    1. >  
    1. <html< span=""> lang="en">  
    1.     
    1.     <meta< span=""> charset="utf-8">  
    1.      rel="stylesheet" href="http://openlayers.org/en/v3.3.0/css/ol.css" type="text/css">  
    1.     <link< span=""> rel="stylesheet" href="map_style.css" type="text/css">  
    1.       
    1.     
    1.     
    1.     

      My Map

        
    1.      id="map" class="map">  
    1.         <div< span=""> id="popup" class="ol-popup">  
    1.              href="#" id="popup-closer" class="ol-popup-closer">  
    1.             <div< span=""> id="popup-content" style="300px; height:120px;">
      
    1.         
      
    1.     
      
    1.      src="http://openlayers.org/en/v3.3.0/build/ol.js" type="text/javascript">  
    1.     <script< span=""> src="map_utils.js" type="text/javascript">  
    1.     
    1.   
     
     
    2、 JavaScript文件的修改
            接下来,我们就给我们的“map_utils.js”做点手术。
           首先我们定义需要全局都能访问到的变量:map ,vectorLayer等等:
    [javascript]  view plain copy
    1. /** 
    1.  * 定义一些全局变量 
    1.  */  
    1. var map, vectorLayer;  
    1. var highlightStyleCache = {}, highlight;  
    1. //弹出框需要的部件  
    1. var container = document.getElementById('popup');  
    1. var content = document.getElementById('popup-content');  
    1. var closer = document.getElementById('popup-closer');  
     
         我们原来定义的map,还是可以拿来直接用,但是需要添加一个vector图层,所以这个图层要提前定义,首先我们定义矢量图层的样式,实例化一个style对象:
    [javascript]  view plain copy
    1. /** 
    1.  * 定义矢量图层 
    1.  * 其中style是矢量图层的显示样式  
    1.  */  
    1. var style = new ol.style.Style({  
    1.   fill: new ol.style.Fill({ //矢量图层填充颜色,以及透明度  
    1.     color: 'rgba(255, 255, 255, 0.6)'  
    1.   }),  
    1.   stroke: new ol.style.Stroke({ //边界样式  
    1.     color: '#319FD3',  
    1.      1  
    1.   }),  
    1.   text: new ol.style.Text({ //文本样式  
    1.     font: '12px Calibri,sans-serif',  
    1.     fill: new ol.style.Fill({  
    1.       color: '#000'  
    1.     }),  
    1.     stroke: new ol.style.Stroke({  
    1.       color: '#fff',  
    1.        3  
    1.     })  
    1.   })  
    1. });  
     
    然后将style用于初始化矢量图层:
     
    [javascript]  view plain copy
    1. vectorLayer = new ol.layer.Vector({ //初始化矢量图层  
    1.   source: new ol.source.GeoJSON({  
    1.     projection: 'EPSG:3857',  
    1.     url: 'data/geojson/countries.geojson'   //从文件加载边界等地理信息  
    1.   }),  
    1.   style: function(feature, resolution) {  
    1.     style.getText().setText(resolution < 5000 ? feature.get('name') : '');  //当放大到1:5000分辨率时,显示国家名字  
    1.     return [style];  
    1.   }  
    1. });  
     
     
    接下来就是实例化map,还是原来的样子,出了layers加了一个适量图层vectorLayer:
    [javascript]  view plain copy
    1. map = new ol.Map({  //初始化map  
    1.     target: 'map',  
    1.     layers: [  
    1.       new ol.layer.Tile({  
    1.         source: new ol.source.MapQuest({layer: 'sat'})  
    1.       }),  
    1.       vectorLayer  
    1.     ],  
    1.     view: new ol.View({  
    1.       center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),  
    1.       zoom: 4  
    1.     })  
    1. });  
     
    接下来,当鼠标在地图上移动时,我们要让矢量图层做出点反应,对,我们就让它高亮吧。
     
    [javascript]  view plain copy
    1. /** 
    1.  * 当鼠标移动时,高亮相应的区域的函数 
    1.  */  
    1. var featureOverlay = new ol.FeatureOverlay({  
    1.   map: map,  
    1.   style: function(feature, resolution) {  
    1.     var text = resolution < 5000 ? feature.get('name') : '';  
    1.     if (!highlightStyleCache[text]) {  
    1.       highlightStyleCache[text] = [new ol.style.Style({  
    1.         stroke: new ol.style.Stroke({  
    1.           color: '#f00',  
    1.            1  
    1.         }),  
    1.         fill: new ol.style.Fill({  
    1.           color: 'rgba(255,0,0,0.1)'  
    1.         }),  
    1.         text: new ol.style.Text({  
    1.           font: '12px Calibri,sans-serif',  
    1.           text: text,  
    1.           fill: new ol.style.Fill({  
    1.             color: '#000'  
    1.           }),  
    1.           stroke: new ol.style.Stroke({  
    1.             color: '#f00',  
    1.              3  
    1.           })  
    1.         })  
    1.       })];  
    1.     }  
    1.     return highlightStyleCache[text];  
    1.   }  
    1. });  
    1.   
    1. var displayFeatureInfo = function(pixel) {  
    1.   var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {  
    1.     return feature;  
    1.   });  
    1.   
    1.   if (feature !== highlight) {  
    1.     if (highlight) {  
    1.       featureOverlay.removeFeature(highlight);  
    1.     }  
    1.     if (feature) {  
    1.       featureOverlay.addFeature(feature);  
    1.     }  
    1.     highlight = feature;  
    1.   }  
    1.   
    1. };  
     
     
    以上是当鼠标移动时的反应,我们要将它绑定到地图的鼠标移动事件中:
    [javascript]  view plain copy
    1. /** 
    1.  * 鼠标移动的事件  
    1.  */  
    1. map.on('pointermove', function(evt) {  
    1.   if (evt.dragging) {   //如果是拖动地图造成的鼠标移动,则不作处理  
    1.     return;  
    1.   }  
    1.   var pixel = map.getEventPixel(evt.originalEvent);  
    1.   displayFeatureInfo(pixel);  
    1. });  
     
    就是这样的效果:
    0
     
     
    当点击鼠标的时候,你并不想没有反应吧!?所以我们再添加一个鼠标点击事件,效果是弹出我们上一节引入的弹出框框。
    [javascript]  view plain copy
    1. /** 
    1.  * 鼠标点击的事件  
    1.  */  
    1. map.on('click', function(evt) {  
    1.   var pixel = map.getEventPixel(evt.originalEvent);  
    1.   var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {  
    1.     return feature;  
    1.   });  
    1.   var coordinate = evt.coordinate;  
    1.   var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(  
    1.       coordinate, 'EPSG:3857', 'EPSG:4326'));  
    1.   if(feature!==undefined){  
    1.       content.innerHTML = '

      你点击的坐标是:

      ' + hdms + '

      这里属于:'+ feature.get('name') + '

      ';  
    1.   }  
    1.   else{  
    1.       content.innerHTML = '

      你点击的坐标是:

      ' + hdms + '

      这里是大海!

      ';  
    1.   }  
    1.   overlay.setPosition(coordinate);  
    1.   map.addOverlay(overlay);  
    1. });  
    1.   
    1. /** 
    1.  * 隐藏弹出框的函数 
    1.  */  
    1. closer.onclick = function() {  
    1.   overlay.setPosition(undefined);  
    1.   closer.blur();  
    1.   return false;  
    1. };  
     
    这样,就搞定了。我们看一下运行效果:
     
    0
     
     
    总结
            这次,我们不仅添加了新功能 -- 矢量图层,而且整理了HTML、JavaScript和CSS的结构,不过矢量图层的数据是来自本地文件的,这种情况在真正的应用中很少见,一般都是直接来自后端数据库的,而且对于网络地图这种需要传输大量数据的应用来说,减少重新加载的机会和选用一种轻量的传输格式至关重要!
            这是下一次我们将要涉及的内容,服务器与客户端的通信手段:AJAX通信,以及传输数据格式:GeoJSON格式!
     
     
     
     OpenLayers系列(2)——多个图层
    工具的使用步骤请参考 OpenLayers系列(1)——入门示例 一节。
    多图层地图的构成
        多图层的地图由两种图层构成:base layer 和overlay layer 。
        Base layer: 任何一个地图中都存在至少一个图层,否则你的应用将呈现空白,我们把最基本的一个图层称为base layer。Base layer不止一种或一个,你可以选择任意一个图层作为应用的base layer,但是任何时候base layer都只能有一个是turn on的,如果程序在打开一个base layer时发现已经存在另一个打开着的base layer,则应用会关掉之前的base layer而使用最近打开的一个。所以base layer在地图中的概念就像是(radio button)一个单选按钮。
        Overlay layer: 非base layer的图层统称为overlay layer。应用中可使用并同时打开任何多的overlay layer,你可以使用参数设置该层是否显示。Overlay layer在地图中的概念就像是(checkbox)多选框。
        以上概念你可以在OpenLayers提供的一个图层切换器上形象地看到。
    示例1
        以下是一个包含两个图层和图层切换器的示例,该示例在base layer上加上了国家,城市,洲名层:
    0
    打开图层切换器:
    0
    示例1代码:
     
     
     
    示例2
     
    示例2主要展示部分图层参数的效果,该示例一共有5个图层,第个图层有不同效果,可以不断放大查看。
    0
    0
    代码如下:
     
     
     
     
     
     
     
     
    2015-06-07 07:50  976人阅读  评论(0)  收藏  举报
    0
      分类:
    WebGIS(28) 
    0
    OpenLayers(17) 
    0
    版权声明:本文为博主原创文章,未经博主允许不得转载。
    目录(?)[+]
          在 GIS 中,地图一般分为两大类:栅格地图和矢量地图,栅格地图其实就是数码照片,只不过有的是卫星拍的。它们有一个共同特征,就是它们都是由很多个像素组成,像素大小是一致的,行高和列宽是一致的,从这个角度看,一幅遥感影像就像栅格。
          矢量地图,是由很多要素组成的,每个要素都有自己的地理坐标,基于数学规则,无论矢量地图怎么放大,地图都不会失真。它是 OpenLayers 中非常重要的一种图层类型,利用矢量地图可以实现非常多的功能,如 动态标绘、调用 WFS 服务、编辑要素、可点击的要素、动态加载要素 等等。
    矢量图层的构成
          矢量图层是在客户端渲染的,在 web 环境中,对应的就是浏览器。构成一个矢量图层的包含一个数据(source)和一个样式(style),数据构成矢量图层的要素,样式规定要素显示的方式和外观。一个初始化成功的矢量图层包含一个到多个要素(feature),每个要素由地理属性(geometry)和多个其他的属性,可能包含名称等。结构如下图:
     
    0
     
    在初始化矢量图层时,可以有很多选项配置矢量图层的行为和外观,常用的有:
    • brightness、contrast,图层亮度和对比度,都是一个数值;
    • renderOrder,一个指定规则的函数 (function(ol.Feature, ol.Feature));
    • hue,色调,是一个数值;
    • minResolution,可见的最小分辨率;
    • maxResolution,可见的最大分辨率;
    • opacity,图层的透明度,0~1之间的数值,1表示不透明;
    • saturation,饱和度;
    • source,图层数据来源;
    • style,图层样式,一个ol.style.Style或者一个ol.style.Style数组,或者一个返回 ol.style.Style 的函数;
    • visible,图层可见性,默认为 true。
    初始化一个矢量图层
    借助一个例子说明如何初始化一个矢量图层:
    var vector = new ol.layer.Vector({ source: new ol.source.Vector({ url: 'data/china_province_boundries.geojson', projection: 'EPSG:3857', format: new ol.format.GeoJSON({ extractStyles: false }) }), style: style });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
          例中的 source url 设置了数据的来源,projection 设置了地理坐标系,format 设置 数据的解析器,因为 url 规定的数据来源是 geojson 格式,所以解析器也是 geojson 解析器 new ol.format.GeoJSON。
    取得要素
          那么,在一个矢量图层中怎么取得它的某个 feature 呢,一般的想法是 vector.getFeature(),其实不是的,vector 的数据包含在 source 中,要取得 vector 的 feature 数据,要在 source 中,例如 vector.getSource().getFeatures(),该函数会返回一个 feature array,直接使用 [ ],取用即可,或者根据要素的 ID 取得(getFeatureById())。
          同样的,只要数据相关的操作,都要得到 vector 的 source 实例,然后进行操作,例如 添加要素(addFeature)、删除要素(removeFeature),对每个要素进行相同的操作(forEachFeature)。
    取得要素的 geometry
          利用 getGeometry() 可以获得要素的地理属性,这个函数当然返回要素包含的 geometry,geometry 包含很多类型,主要有 point、multi point、linear ring、line string、multi line string、polygon、multi polygon、circle。
          取得 geometry 后,就可以获得要素的坐标了,可以根据坐标做一些地理判断,比如判断 一个坐标是否位于要素内(containsCoordinate(coordinate)或者 containsXY(x, y)),取得要素的中心坐标等。
    总结
          使用矢量图层,可以实现很多功能,比如动态加载矢量数据、调用 WFS 服务、动态标绘、编辑要素,分别是在图层级别和要素级别进行的操作。
          例如可以实现,在矢量图层上绘制不同的图形,并添加属性,然后更新至数据库,即动态标绘系统;或者动态加载要素级数据,比如跟踪汽车的轨迹。
     
     
  • 相关阅读:
    【Redis】集群NetCore实战
    【Redis】集群教程(Windows)
    【Redis】入门
    【SQL SERVER】索引
    【SQL SERVER】锁机制
    【SQL SERVER】数据内部存储结构简单探索
    Windows软件包管理工具
    Git常用命令记录
    【ASP.NET Core学习】远程过程调用
    CouchDB学习-API
  • 原文地址:https://www.cnblogs.com/devgis/p/16542817.html
Copyright © 2020-2023  润新知