您的位置:首页 > 运维架构

[置顶] OpenLayers 3 之 使用矢量图层(Vector)

2015-03-27 14:43 483 查看
摘要

        矢量图层:矢量图层是用来渲染矢量数据的图层类型,在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页面如下:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="http://openlayers.org/en/v3.3.0/css/ol.css" type="text/css">
<link rel="stylesheet" href="map_style.css" type="text/css">
<title>OpenLayers 3</title>
</head>
<body>
<h2>My Map</h2>
<div id="map" class="map">
<div id="popup" class="ol-popup">
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
<div id="popup-content" style="width:300px; height:120px;"></div>
</div>
</div>
<script src="http://openlayers.org/en/v3.3.0/build/ol.js" type="text/javascript"></script>
<script src="map_utils.js" type="text/javascript"></script>
</body>
</html>


2、 JavaScript文件的修改

        接下来,我们就给我们的“map_utils.js”做点手术。

       首先我们定义需要全局都能访问到的变量:map ,vectorLayer等等:

/**
* 定义一些全局变量
*/
var map, vectorLayer;
var highlightStyleCache = {}, highlight;
//弹出框需要的部件
var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');

     我们原来定义的map,还是可以拿来直接用,但是需要添加一个vector图层,所以这个图层要提前定义,首先我们定义矢量图层的样式,实例化一个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',
width: 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',
width: 3
})
})
});


然后将style用于初始化矢量图层:

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];
}
});


接下来就是实例化map,还是原来的样子,出了layers加了一个适量图层vectorLayer:

map = new ol.Map({  //初始化map
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
}),
vectorLayer
],
view: new ol.View({
center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});


接下来,当鼠标在地图上移动时,我们要让矢量图层做出点反应,对,我们就让它高亮吧。

/**
* 当鼠标移动时,高亮相应的区域的函数
*/
var featureOverlay = new ol.FeatureOverlay({
map: map,
style: function(feature, resolution) {
var text = resolution < 5000 ? feature.get('name') : '';
if (!highlightStyleCache[text]) {
highlightStyleCache[text] = [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f00',
width: 1
}),
fill: new ol.style.Fill({
color: 'rgba(255,0,0,0.1)'
}),
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
text: text,
fill: new ol.style.Fill({
color: '#000'
}),
stroke: new ol.style.Stroke({
color: '#f00',
width: 3
})
})
})];
}
return highlightStyleCache[text];
}
});

var displayFeatureInfo = function(pixel) {
var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
return feature;
});

if (feature !== highlight) {
if (highlight) {
featureOverlay.removeFeature(highlight);
}
if (feature) {
featureOverlay.addFeature(feature);
}
highlight = feature;
}

};


以上是当鼠标移动时的反应,我们要将它绑定到地图的鼠标移动事件中:

/**
* 鼠标移动的事件
*/
map.on('pointermove', function(evt) {
if (evt.dragging) {   //如果是拖动地图造成的鼠标移动,则不作处理
return;
}
var pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
});


就是这样的效果:



当点击鼠标的时候,你并不想没有反应吧!?所以我们再添加一个鼠标点击事件,效果是弹出我们上一节引入的弹出框框。

/**
* 鼠标点击的事件
*/
map.on('click', function(evt) {
var pixel = map.getEventPixel(evt.originalEvent);
var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
return feature;
});
var coordinate = evt.coordinate;
var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(
coordinate, 'EPSG:3857', 'EPSG:4326'));
if(feature!==undefined){
content.innerHTML = '<p>你点击的坐标是:</p><code>' + hdms + '</code><p>这里属于:'+ feature.get('name') + '</p>';
}
else{
content.innerHTML = '<p>你点击的坐标是:</p><code>' + hdms + '</code><p>这里是大海!</p>';
}
overlay.setPosition(coordinate);
map.addOverlay(overlay);
});

/**
* 隐藏弹出框的函数
*/
closer.onclick = function() {
overlay.setPosition(undefined);
closer.blur();
return false;
};

这样,就搞定了。我们看一下运行效果:



总结

        这次,我们不仅添加了新功能 -- 矢量图层,而且整理了HTML、JavaScript和CSS的结构,不过矢量图层的数据是来自本地文件的,这种情况在真正的应用中很少见,一般都是直接来自后端数据库的,而且对于网络地图这种需要传输大量数据的应用来说,减少重新加载的机会和选用一种轻量的传输格式至关重要!

        这是下一次我们将要涉及的内容,服务器与客户端的通信手段:AJAX通信,以及传输数据格式:GeoJSON格式!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: