Openlayers
一、介绍
OpenLayers是一个用于开发WebGIS客户端的JavaScript包。OpenLayers 支持的地图来源包括Google Maps、Yahoo、 Map、微软Virtual Earth 等,用户还可以用简单的图片地图作为背景图,与其他的图层在OpenLayers 中进行叠加,在这一方面OpenLayers提供了非常多的选择。除此之外,OpenLayers实现访问地理空间数据的方法都符合行业标准。OpenLayers 支持Open GIS 协会制定的WMS(Web Mapping Service)和WFS(Web Feature Service)等网络服务规范,可以通过远程服务的方式,将以OGC 服务形式发布的地图数据加载到基于浏览器的OpenLayers 客户端中进行显示。
二、基本概念
基本使用:npm install ol下载,全局使用在main.js中import并use,或者局部使用在需要使用的.vue文件中import后可直接使用
注意:这里需要import的原型比较多,记得仔细检查是否漏引
1.map
OpenLayers 的核心组件是地图 ( ol/Map)。它被渲染到一个target容器(例如div网页上包含地图的元素)。所有地图属性都可以在构建时进行配置,也可以使用 setter 方法进行配置,例如setTarget().
下面的标记可用于创建<div>包含您的地图的标记。
<div id="map" style="width: 100%, height: 400px"></div>
下面的脚本使用元素的 id 作为选择器来构造一个在<div>上面渲染的地图。map
import Map from 'ol/Map';
var map = new Map({target: 'map'});
2.view
地图不负责地图的中心、缩放级别和投影等事项。相反,这些是ol/View实例的属性。
import View from 'ol/View';
map.setView(new View({
center: [0, 0],
zoom: 2
}));
一个View有一个projection投影。投影决定了地图分辨率计算的坐标系center和单位。如果未指定(如上面的代码片段),则默认投影为 Spherical Mercator (EPSG:3857),以米为地图单位。
该zoom选项是指定地图分辨率的便捷方式。可用缩放级别由maxZoom(默认值:28)、zoomFactor(默认值:2)和maxResolution(默认值以投影的有效范围适合 256x256 像素图块的方式计算)确定。从缩放级别 0 开始,分辨率为maxResolution每像素单位,后续缩放级别通过将先前缩放级别的分辨率除以 来计算zoomFactor,直到maxZoom达到缩放级别。
3.source
为了获取层的远程数据,OpenLayers 使用ol/source/Source子类。这些可用于 OpenStreetMap 或 Bing 等免费和商业地图切片服务、WMS 或 WMTS 等 OGC 源,以及 GeoJSON 或 KML 等格式的矢量数据。
import OSM from 'ol/source/OSM';
var osmSource = OSM();
4.layer
layer是来自source,OpenLayers 有四种基本类型的层:
ol/layer/Tile- 渲染在按特定分辨率的缩放级别组织的网格中提供平铺图像的源。(瓦片)ol/layer/Image- 渲染以任意范围和分辨率提供地图图像的源。ol/layer/Vector- 在客户端渲染矢量数据。ol/layer/VectorTile- 渲染作为矢量图块提供的数据。
import TileLayer from 'ol/layer/Tile';
var osmLayer = new TileLayer({source: osmSource});
map.addLayer(osmLayer);
5.style
var style = new Style({
//边框样式
stroke: new ol.style.Stroke({
color: 'white',
width: 2,
}),
//填充样式
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.7)',
}),
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'white',
})
})
})
6.feature
步骤:创建要素实例,设置样式,设置id,向source添加要素feature
组合
上面的代码片段可以组合成一个脚本,用一个瓦片层初始化并且渲染一个地图
import Map from 'ol/Map';
import View from 'ol/View';
import OSM from 'ol/source/OSM';
import TileLayer from 'ol/layer/Tile';
new Map({
layers: [ // 图层数组
new TileLayer( // 地图图层,比如底图、矢量图等
{source: new OSM()}
)
],
view: new View({
// 投影,默认为38
projection: 'EPSG:4326',
// 中心坐标
center: [114.064839, 22.548857],
// 地图最小缩放比例
minZoom: 10,
// 地图最大缩放比例
maxZoom: 19,
// 地图缩放级别(打开页面时默认级别)
zoom: 12
// 旋转
rotation: 1,
}),
target: 'map' // 指定容器id
});
例子:(高德地图)
//加载高德地图的数据源
var gaodeMapLayer=new ol.layer.Tile({
title:"高德地图",
source:new ol.source.XYZ({
//指定url瓦片
url:'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
wrapX:true//x方向平铺,也可以选择false
})
});
//创建地图容器
var map=new ol.Map({
layers:[gaodeMapLayer],
//加载瓦片图层数据
view:new ol.View({
//中心点坐标
center:[12156971,3891618],
projection:'EPSG:3857',
zoom:8,
minZoom:3
}),
target:'map'
//目标加载到map中
})
实现了地图的显示功能之后可以加载常用的控件,比如常用的导航控件,导航条放大缩小等 加载地图导航条:
//加载地图导航条实现放大缩小
var zoomslider=new ol.control.ZoomSlider();
map.addControl(zoomslider);
var zoomToExtent=new ol.control.ZoomToExtent({
//地图缩放的范围,当前地图缩放至此范围,视图域将显示此范围内的地图
extent:[13100000,4290000,13200000,5210000]
});
//加载到map容器中
map.addControl(zoomToExtent);
导航条就是滑动形式放大缩小,可以通过编写css代码修改样式
#map .ol-zoom .ol-zoom-out{
margin-top: 204px;
}
#map .ol-zoomslider{
background-color: transparent;
top: 2.3em;
}
#map .ol-touch.ol-zoom .ol-zoom-out{
margin-top: 212px;
}
#map .ol-touch .ol-zoomslider{
top: 2.75em;
}
#map .ol-zoom-in .ol-has-tooltip:hover[ role=tooltip;],
#map .ol-zoom-in .ol-has-tooltip:focus[role=tooltip]{
top:3px;
}
#map .ol-zoom-out .ol-has-tooltip:hover[ role=tooltip],
#map .ol-zoom-out .ol-has-tooltip:focus[role=tooltip]{
top:232px;
}
#map .ol-zoom-extent{
top:280px;
}
注意: 这些操作主要有几点注意,加载瓦片图层数据时需要设置参数XYZ, 旋转角度的设置,地图旋转是通过旋转控件(ol.control.Rotation)实现的,此控件已默认添加到地图中,ol.control.Rotate控件的autohHide参数默认为true,在旋转角度为0°时将自动隐藏旋转按钮 tooltip时设置悬浮的提示框 修改css样式时,c比如修改lass下得id对应样式,.class和#id之间需要空格 wrapX:true, //x方向平铺,false就是不平铺
自定义地图
注意:feature中不能直接getSource(),layer才可以直接getSource()。但是可以通过自己封装函数来实现通过feature获取layer。feature可以直接getGeometry()
通过target指定id为map的div容器,如果地图未正确显示,可以检查地图容器宽高的设置
方法1:初始化map实例后,向某一指定图层添加点/线/面元素(feature)
//初始化红绿灯数据
initLightData(){
this.lightLayer.getSource().clear(); // 清空图层
this.lightData.forEach((item, index) => {
var feature = new Feature({
geometry: new Point([Number(item.x), Number(item.y)]),
});
let url = "images/light.png";
const zoom = this.map.getView().getZoom();
let style = new Style({
image: new Icon({
scale: 0.15 * (zoom -13) ,
src: url,
anchor: [0.48, 0.52],
}),
});
feature.setStyle(style);
this.lightLayer.getSource().addFeature(feature);
});
},
import { Image as ImageLayer, Vector as VectorLayer, Tile as TileLayer, } from "ol/layer";
import { Circle as CircleStyle, Fill, Icon, Stroke, Style, Text, } from "ol/style";
// 候车室点位
drawWaitingPoint() {
this.wrnameData.forEach((item, index) => {
var feature = new Feature({
geometry: new Point([item.x, item.y]),
});
feature.setId(`${item.wrname}`);
let style = new Style({
text: new Text({
font: "normal 10px 黑体",
// // 对其方式
textAlign: "center",
// 基准线
textBaseline: "middle",
offsetY: 0,
offsetX: 0,
// 文本填充样式
fill: new Fill({
color: "rgba(236,218,20,1)",
}),
padding: [5, 5, 5, 5],
text: `${item.wrname}`,
}),
});
feature.setStyle(style); // 为元素设置样式
this.roomLayer.getSource().addFeature(feature);
});
},
方法2:添加点/线/面图层
import { Feature } from "ol";
import { Point, LineString, Polygon } from "ol/geom";
addLayer() {
this.vectorLayer = new VectorLayer({
source: new VectorSource(),
});
this.vectorLayer.getSource().addFeature(
//添加点图层
new Feature({
geometry: new Point([104.2979180563, 30.528298024]),
})
//添加线图层
// new Feature({
// geometry: new LineString([
// [104.2979180563, 30.528298024],
// [104.2987389704, 30.527798338],
// ]),
// })
//添加面图层
// new Feature({
// geometry: new Polygon([
// [
// [104.2979180563, 30.528298024],
// [104.2987389704, 30.527798338],
// [104.2974397847, 30.5265062907],
// [104.2979180563, 30.528298024],
// ],
// ]),
// })
);
}
三、自定义点线面图层
创建点要素Point
let feature = new Feature({
geometry: new Point([104.2979180563, 30.528298024]),
});
创建线要素LineString
let feature = new Feature({
geometry: new LineString([
[104.2979180563, 30.528298024],
[104.2987389704, 30.527798338],
]),
});
创建面要素Polygon
let feature = new Feature({
geometry: new Polygon([
[
[106, 33],
[108.03955078125, 32.2313896627376],
[108.25927734375, 33.15594830078649],
[106, 33],
],
]),
});
动态添加坐标
let geometry = new LineString(); //LineString 线,Point 点,Polygon 面
let coordinate = [
[105.6005859375, 30.65681556429287],
[107.95166015624999, 31.98944183792288],
];
function addPonitToGeometry(arr) {
for (let i = 0; i < arr.length; i++) {
geometry.appendCoordinate(arr[i]);
}
}
addPonitToGeometry(coordinate);
let LineStringFeature = new Feature(geometry);
给feature设置id
feature.setId(xxx)
获取feature的id
feature.getId()
通过feature的id获取feature
source.getFeatureById(xxx)
添加feature
source.addFeature(xxx)
移除feature
source.removeFeature(xxx)
数据源source中遍历所有要素feature
source.forEachFeature(feature=>{})
数据源source中获取features数组
source.getFeatures()
geojson中获取features数组
import GeoJSON from "ol/format/GeoJSON";
geojsonData: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [0, 0],
},
},
],
},
let features = new GeoJSON().readFeatures(this.geojsonData)
给feature动态设置文本text
change() {
this.feature
.getStyle()
// .getText()
// .setText("哈哈哈");
this.feature.changed();
}
给feature设置样式style
feature.setStyle(new Style(xxx))
根据feature获取geometry
feature.getGeometry()
将feature置于视图中心-fly飞行
this.map.getView().fit(feature.getGeometry(), {
duration: 1000,
padding: [100, 100, 100, 100],
});
根据feature获取geometry类型
feature.getGeometry().getType()
如:Point、LineString、Polygon等
给feature设置指定属性
feature.set("xx",xx)
给feature设置多个属性
feature.setProperties(Object)
获取feature中的指定属性
获取feature要素后,可以直接通过feature.get('属性名') 来获取geojson中该feature的属性值
feature.get('属性名')
获取feature中的所有属性
或者通过feature.getProperties() 来获取geojson中该feature的所有的属性值,返回包含属性值的一个对象
通过feature获取layer
适用于点要素和面要素,而线要素还有待研究。
import {Vector as VectorSource } from "ol/source";
// 根据feature获取layer
getLayer(feature = {}, map = {}) {
let layers = map.getLayers().getArray();
for (let i in layers) {
let source = layers[i].getSource();
if (source instanceof VectorSource) {
let features = source.getFeatures();
if (features.length > 0) {
for (let j in features) {
if (features[j] === feature) {
return layers[i];
}
}
}
}
}
return {};
},