初识webGIS库—OpenLayers
Posted 水星记_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识webGIS库—OpenLayers相关的知识,希望对你有一定的参考价值。
文章目录
前言
GIS 作为获取、存储、分析和管理地理空间数据的重要工具,用 GIS 技术绘制地图比用传统的手工操作或自动制图工具更加灵活。今天给大家分享一个专为 GIS 客户端开发提供的 JavaScript 类库包 — OpenLayers。
一、OpenLayers是什么?
OpenLayers 是一个专为 Web GIS 客户端开发提供的 JavaScript 类库包,用于实现标准格式发布的地图数据访问。它的主要作用就是用于展现数据并且提供相应的地图操作工具。官方文档地址:https://openlayers.org/
二、快速开始
1.安装
npm i --save ol
cnpm i --save ol
2.入门使用
2.1 为地图准备一个
div
的容器
<div style="height: 100%; width: 100vw">
<div id="map" ref="map"></div>
</div>
2.2 绑定
id
初始化一个地图;将图层Layer
添加到Map
中,指定数据源服务(url)
;设置Map
容器的视图窗口。
initMap()
this.map = new Map(
target: "map", // html中的地图id
// 图层的基类
layers: [
new TileLayer(
source: new OSM(), //指定了图层的数据来源,图层作用是以一定的样式渲染数据,source则指定数据
),
],
view: new View(
projection: "EPSG:4326", //坐标系,有EPSG:4326和EPSG:3857
center: [116.23, 39.54], //中心坐标点
zoom: 10, //默认缩放级别
),
);
,
完整代码
<template>
<div style="height: 100%; width: 100vw">
<div id="map" ref="map"></div>
</div>
</template>
<script>
import "ol/ol.css";
import Map, View from "ol";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
export default
data()
return
map: null,
;
,
mounted()
this.initMap(); //定义一个方法
,
methods:
// 初始化地图
initMap()
this.map = new Map(
target: "map", // html中的地图id
// 图层的基类(添加图层)
layers: [
new TileLayer(
source: new OSM(), //指定了图层的数据来源,图层作用是以一定的样式渲染数据,source则指定数据
),
],
view: new View(
projection: "EPSG:4326", //坐标系,有EPSG:4326和EPSG:3857
center: [116.23, 39.54], //中心坐标点
zoom: 10, //默认缩放级别
),
);
,
,
;
</script>
<style>
#map
width: 100%;
height: 100%;
</style>
实现效果
三、配置
在所有配置中,Map、Layer、Source、View、Control、Interaction 是 Openlayers 的核心配置;下面为大家一一讲解。
1.Map
Map 是 Openlayers 使用基础,所有的图层、地图控件、地图工具等必须添加到 Map 中才能使用。
1.1 Map 常用的属性、方法和事件
属性:
- layers 图层
- view 视图
- controls 地图控件
- target 地图容器
- overlays 叠加图层
例:view 方法的使用
view: new View(
projection: "EPSG:4326",
center: [116.23, 39.54],
zoom: 10,
),
方法:
- addControl(control) 添加控件
- addInteraction(interaction) 添加交互
- addLayer(layer) 添加图层
- addOverlay(overlay) 添加覆盖物
- dispatchEvent(event) 调度事件并调用所有侦听此类型事件的侦听器
- on(type, listener) 侦听某种类型的事件
- getOverlays() 获取所有覆盖物
- removeOverlay(overlay) 删除指定覆盖物
例:addControl 方法的使用
this.map.addControl(
new control.OverviewMap(
collapsed: true,
)
);
事件:
- click 地图点击事件
- dblclick 地图双击事件
- moveend 地图移动时触发
- movestart 地图开始移动时触发
- postrender 地图渲染后触发
- singleclick 地图单击事件
例:click 事件的使用
this.map.on("click", (evt) =>
this.mapPointerClick(evt);
);
2.Layer
Layer 是 Map 的核心组成部分,ol 定义了四种基本的图层类型,分别是分别是 Tile(瓦片)、Image(图片)、Vector(矢量)、VectorTile(矢量切片),这四种类有一个共同的基类 Layer,它们的大多数属性和方法都继承自这个类。
2.1 Layer 常用的属性和方法
属性:
- source 指定了图层的数据来源
- className 图层各个元素的样式
- opacity 透明度,默认为 1
- visible 是否可见,默认是 true
- zIndex 图层的叠加顺序,默认是 0
- extent 图层渲染的区域(浏览器窗口中可见的地图区域)
- minResolution 图层最小分辨率,当 layer 缩放级别小于这个分辨率时,图层隐藏
- maxResolution 图层最大分辨率
- minZoom 图层最小缩放级别
- maxZoo 图层最大缩放级别
例:source 属性的使用
layers: [
new TileLayer(
source: new OSM(),
),
],
方法:
- getLayersArray() 拿到所有图层
- getLayerStatesArray() 拿到所有图层状态
- getSource() 拿到相应图层的来源
- getSourceState() 拿到相应图层的来源状态
- setSource() 设置图层 source 属性,参数为一个 source 对象
- setMap() 添加 Layer 到 Map,并由 Map 管理
例:getSourceState 方法的使用
this.clusterSource.getSource().forEachFeature((feature) =>
//执行操作
);
3.Source
Source 就是数据来源和格式。简单理解就是在使用 layers(图层) 时,不同的图层需要传入不同的数据类型才能渲染地图。它们需要的数据格式都是通过 Source 定义好的,我们只需要把现有的数据按照规定传入数据源中即可。
3.1 Source 的数据类型
分类:
- ol.source.BingMaps Bing 地图图块数据的图层源
- ol.source.CartoDB CartoDB Maps API 的图层源
- ol.source.Cluster 聚簇矢量数据
- ol.source.Vector 提供矢量图层数据
- ol.source.Image 提供单一图片数据的类型
- ol.source.ImageCanvas 数据来源是一个 canvas 元素,其中的数据是图片
- ol.source.ImageMapGuide Mapguide 服务器提供的图片地图数据
- ol.source.ImageStatic 提供单一的静态图片地图
- ol.source.ImageVector数据来源是一个 canvas 元素,但是其中的数据是矢量来源
- ol.source.ImageWMS WMS 服务提供的单一的图片数据
- ol.source.MapQuest MapQuest 提供的切片数据
- ol.source.Stamen Stamen 提供的地图切片数据
- ol.source.Tile 提供被切分为网格切片的图片数据
- ol.source.TileVector 被切分为网格的矢量数据
- ol.source.TileDebug 并不从服务器获取数据
- ol.source.TileImage 提供切分成切片的图片数据
- ol.source.TileUTFGrid TileJSON 格式 的 UTFGrid 交互数据
- ol.source.TileJSON TileJSON 格式的切片数据
- ol.source.TileArcGISRest ArcGIS Rest 服务提供的切片数据
- ol.source.WMTS WMTS 服务提供的切片数据
- ol.source.Zoomify Zoomify 格式的切片数据
- ol.source.OSM OpenStreetMap 提供的切片数据
- ol.source.XYZ 具有在 URL 模板中定义的一组 XYZ 格式的 URL 的切片数据的图层源
例:通过 layer 使用 source
this.layer = new TileLayer(
source: new XYZ(
url: "http://192.168.0.138/OSM/z_x_y.png",
wrapX: true,
),
);
4.View
view 的作用主要是控制地图的交互,例如设置地图的展示位置范围、地图中心位置以及当前地图使用的投影坐标系等等。
4.1 View 常用的属性和方法
属性:
- center 视图初始化中心点位
- enableRotation 是否启用旋转
- constrainRotation 旋转约束;false 意味着没有约束;true 意味着没有约束,但在 0 附近捕捉到 0。数字将旋转限制为该数量的值,就是设置 90 只能旋转 90 度
- extent 限制视图的范围;可选:[minx, miny, maxx, maxy]
- constrainOnlyCenter 若为 true,则范围约束将仅适用于视图中心而不是整个范围
- smoothExtentConstraint 若为 true,范围约束将被平滑地应用,即允许视图稍微超出给定的 extent
- maxResolution 用于确定分辨率约束的最大分辨率
- minResolution 用于确定分辨率约束的最小分辨率
- maxZoom 用于确定分辨率约束的最大缩放级别
- minZoom 用于确定分辨率约束的最小缩放级别
- constrainResolution 若为 true,则视图将始终在交互后以最接近的缩放级别进行动画处理;false 表示允许中间缩放级别
- resolutions决定缩放级别的分辨率
- zoom 只有 resolution 未定义时使用;缩放级别用于计算视图的初始分辨率
- rotation 以弧度为单位的视图初始旋转(顺时针旋转,0 表示北)
例:maxZoom 事件的使用
view: new View(
// 地图视图
projection: "EPSG:4326",
center: [118.27, 39.71],
zoom: 10,
maxZoom: 20,
),
方法:
- getCenter 获取视图中心,返回地图中心坐标
- getZoom 获取当前的缩放级别
- getMaxZoom 获取视图的最大缩放级别
- getMinZoom 获取视图的最小缩放级别
- getProjection 获取地图使用的“投影坐标系统”,如 EPSG:3857
- getMaxResolution 获取视图的最大分辨率
- getMinResolution 获取视图的最低分辨率
- getRotation 获取视图旋转
- getZoomForResolution 获取分辨率的缩放级别
- setCenter 设置当前视图的中心
- setConstrainResolution 设置视图是否应允许中间缩放级别
- setZoom 缩放到特定的缩放级别。任何分辨率限制都将适用
- setMaxZoom 为视图设置新的最大缩放级别
- setMinZoom 为视图设置新的最小缩放级别
- setRotation 设置该视图的旋转角度
例:getZoom 事件的使用
//amend 点击事件
amend()
const view = this.map.getView();
const zoom = view.getZoom();
view.setZoom(zoom - 1);
console.log(view, "缩放级别:" + zoom);
,
5.Control
Control 控件,操作地图相关的工具。
5.1 Control 常用的控件
控件:
- FullScreen() 全屏控制
- MousePosition() 坐标拾取控件
- ScaleLine() 比例尺控件
- ZoomSlider() 滑块缩放控件
- OverviewMap() 鹰眼控件
- Attribution() 官方 LoGo
例:Control 控件的使用
this.map = new Map(
controls: control.defaults().extend([
// 根据需要打开关闭即可
new control.FullScreen(), //全屏控制
// new control.MousePosition(), //坐标拾取控件
// new control.ScaleLine(),//比例尺控件
// new control.ZoomSlider(),//滑块缩放控件
// new control.OverviewMap(),//鹰眼控件
]),
);
6.Interaction
Interaction 也是用来控制地图的,但与控件不同的是 Interaction 是在地图上绘制要素、选择、修改、移动、拉伸等等操作。
6.1 Interaction 常用的交互功能
常用交互功能:
- doubleclickzoom 双击地图进行缩放
- draganddrop 以“拖文件到地图中”的交互添加图层
- dragbox 用于划定一个矩形范围
- dragpan 拖拽平移地图
- dragrotateandzoom 拖拽方式进行缩放和旋转地图
- dragrotate 拖拽方式旋转地图
- dragzoom 拖拽方式缩放地图
- draw 绘制地理要素功能
- keyboardpan 键盘方式平移地图
- keyboardzoom 键盘方式缩放地图
- select 选择要素功能
- modify 更改要素
- mousewheelzoom 鼠标滚轮缩放功能
- pinchrotate 手指旋转地图,针对触摸屏
- pinchzoom 手指进行缩放,针对触摸屏
- pointer 鼠标的用户自定义事件基类
- snap 鼠标捕捉,当鼠标距离某个要素一定距离之内,自动吸附到要素
例:dragrotateandzoom 交互的使用
this.map = new Map(
interactions: defaultInteractions().extend([new DragRotateAndZoom()]),
);
四、实践
经过以上的学习,相信大家对 OpenLayers 已经有了初步的认识,下面我们来写一个简单的操作,根据接口数据中的经纬度在地图上渲染点位,点击点位展示当前点击点位的详情数据,如下图:
实现思路
1.引入所需组件;
2.初始化一个地图;
3.循环接口数据拿到所需经纬度,通过 addLayer 方法添加到地图中;
4.添加弹详情出层,通过 id 拿到定义的容器,添加 overlay 到 map;
5.创建点击事件,点击点位后,利用 feature.get 方法拿到数据渲染点位详情即可。
完整代码
<template>
<div>
<div class="mapBox" id="map">
<div id="popup" class="ol-popup">
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
<div id="popup-content">
<div class="detailsBox">
<div>所属区县:mapDataDetail.qx</div>
<div>加油站地址:mapDataDetail.jyzdz</div>
<div>加油站负责人:mapDataDetail.jyzfzr</div>
<div>联系电话:mapDataDetail.lxdh</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import areaGeo from "./map.json";
import Map, View, Feature, ol from "ol";
import TileLayer from "ol/layer/Tile";
import * as control from "ol/control";
import Polygon, MultiPolygon from "ol/geom";
import VectorLayer from "ol/layer/Vector";
import Cluster, OSM, Vector as VectorSource, XYZ from "ol/source";
import "ol/ol.css";
import
Style,
Stroke,
Fill,
Icon,
Circle as CircleStyle,
Text,
from "ol/style";
import GeoJSON from "ol/format/GeoJSON";
import Point from "ol/geom/Point";
import toStringHDMS from "ol/coordinate";
import toLonLat from "ol/proj";
import Overlay from "ol/Overlay";
export default
data()
return
mapData: [], //地图点位
mapPointVectorLayer: null, //地图点位图层控制器
geoRouteLayer: null, //geo市局边界图层
clusterSource: null,
map: null,
overlay: null, //业务点聚合图层详情图层
mapDataDetail:
qx: "",
jyzdz: "",
jyzfzr: "",
lxdh: "",
jyzzz: "",
, //点位详情数据
;
,
methods:
//初始化地图
initMap()
// 地图实例
this.map = new Map(
target: "map", // 对应页面里 id 为 map 的元素
controls: control.defaults().extend([
// 根据需要打开关闭即可
new control.FullScreen(), //全屏控制
]),
layers: [
new TileLayer(
source: new OSM(),
),
],
view: new View(
// 地图视图
projection: "EPSG:4326", // 坐标系,有EPSG:4326和EPSG:3857
center: [118.27, 39.71], // 默认打开的中心坐标
zoom: 10.1, // 地图缩放级别(打开页面时默认级别)
minZoom: 10, //最小缩放级别
maxZoom: 20, //最大缩放级别
),
);
,
//模拟请求接口
mapList()
let data = [
district: "路北区",
lat: "118.080181",
lng: "39.588275",
oilStationAddress: "唐山市路北区安立路",
oilStationCharge: "吴彦祖",
oilStationChargePhone: "18888888888",
oilStationName: "唐山加油站",
oilStationStatus: "0",
,
district: "路北区",
lat: "118.202271",
lng: "39.651675",
oilStationAddress: "唐山市路北区上海路",
oilStationCharge: "谢霆锋",
oilStationChargePhone: "18888888888",
oilStationName: "唐山",
oilStationStatus: "1",
,
];
this.mapData = data;
this.showPoints();
this.addPopup();
this.map.on("click", (evt) =>
this.mapPointerClick(evt);
);
,
//添加弹出层
addPopup()
this.overlay = new Overlay(
element: document.getElementById("popup"),
offset: [0, -13],
);
//添加 overlay 到 map
this.map.addOverlay(this.overlay);
// 关闭弹出层
var closer = document.getElementById("popup-closer");
closer.onclick = () =>
this.overlay.setPosition(undefined);
closer.blur();
return false;
;
,
//展示聚合点位
showPoints()
// 聚合图层数据源
this.clusterSource = new Cluster(
distance: 100,
source: new VectorSource(
features: [],
),
);
this.mapPointVectorLayer = new VectorLayer(
source: this.clusterSource,
style: (feature) =>
return this.setClusterStyle(feature);
,
);
let features = [];
this.mapData.forEach((item) =>
if (item.lng != "" && item.lat != "")
let newObj = Object.assign(, item);
newObj.geometry = new Point([Number(item.lat), Number(item.lng)]);
features.push(new Feature(newObj));
);
this.clusterSource.getSource().addFeatures(features);
this.map.addLayer(this.mapPointVectorLayer);
,
//鼠标点击事件。若悬浮到设备上,则现在设备的具体信息
mapPointerClick(evt)
let pixel = this.map.getEventPixel(evt.originalEvent);
let featureMouseOver = this.map.forEachFeatureAtPixel(
pixel,
function (feature, layer)
return feature;
);
let coordinate;
if (featureMouseOver)
if (featureMouseOver.getProperties().features)
//聚合情况下
if (featureMouseOver.getProperties().features.length == 1)
console.log(1111);
//只有一个要素000000000000000
let f = featureMouseOver.getProperties().features[0]; //获取该要素
this.clusterSource.getSource().forEachFeature((feature) =>
if (f == feature)
coordinate = [feature.get("lat"), feature.get("lng")];
this.mapDataDetail.qx = feature.get("district");
this.mapDataDetail.jyzdz = feature.get("oilStationAddress");
this.mapDataDetail.jyzfzr = feature.get("oilStationCharge");
this.mapDataDetail.lxdh = feature.get("oilStationChargePhone");
this.mapDataDetail.jyzzz = feature.get("oilStationStatus");
console.log(feature.get("oilStationAddress"));
this.overlay.setPosition(coordinate);
);
if (!coordinate)
this.overlay.setPosition(undefined);
,
//设置聚合图层的样式
setClusterStyle(feature)
var features = feature.get("features");
var size = features.length;
var style;
if (size == 1)
style = [
new Style(
image: new Icon(
src: "https://s1.ax1x.com/2022/07/06/ja5kvQ.png", //详情点位icon
),
),
];
else
// 样式处理
style = new Style(
image: new CircleStyle(
radius: 18,
stroke: new Stroke(
color: "#fff",
),
fill: new Fill(
color: "#3399CC",
),
),
text: new Text(
font: "15px sans-serif",
text: size.toString(),
fill: new Fill(
color: "#fff",
),
),
);
return style;
,
//设置区域
addArea(geo = [])
if (geo.length == 0)
return false;
let features = [];
var geoserver = geo[0].features;
geoserver.forEach((g) =>
let lineData = g;
let routeFeature = "";
if (lineData.geometry.type == "MultiPolygon")
routeFeature = new Feature(
以上是关于初识webGIS库—OpenLayers的主要内容,如果未能解决你的问题,请参考以下文章