文章目录

  • 前言
  • 一、OpenLayers是什么?
  • 二、快速开始
    • 1.安装
    • 2.入门使用
  • 三、配置
    • 1.Map
    • 2.Layer
    • 3.Source
    • 4.View
    • 5.Control
    • 6.Interaction
  • 四、实践
    • 实现思路
    • 完整代码
  • 总结

前言

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:3857center: [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:3857center: [116.23, 39.54], //中心坐标点zoom: 10, //默认缩放级别}),});},},
};
</script><style>
#map {width: 100%;height: 100%;
}
</style>

实现效果


三、配置

在所有配置中,MapLayerSourceViewControlInteractionOpenlayers 的核心配置;下面为大家一一讲解。

1.Map

MapOpenlayers 使用基础,所有的图层、地图控件、地图工具等必须添加到 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

LayerMap 的核心组成部分,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:3857center: [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 到 mapthis.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);//只有一个要素000000000000000let 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({geometry: new MultiPolygon(lineData.geometry.coordinates),});} else if (lineData.geometry.type == "Polygon") {routeFeature = new Feature({geometry: new Polygon(lineData.geometry.coordinates),});}routeFeature.setStyle(new Style({fill: new Fill({color: "#4e98f444", //填充颜色}),stroke: new Stroke({width: 3, //边界宽度color: [71, 137, 227, 1], //边界颜色}),}));features.push(routeFeature);});// 设置图层this.geoRouteLayer = new VectorLayer({source: new VectorSource({features: features,}),});// 添加图层this.map.addLayer(this.geoRouteLayer);},},mounted() {this.initMap(); //加载默认图层this.addArea(areaGeo); //加载边界图层this.mapList(); //模拟接口},
};
</script><style scoped>
.mapBox {width: 100%;height: 100vh;
}
.detailsBox {padding: 14px;font-size: 14px;color: white;box-shadow: 0px 0px 30px 0px #0085f7 inset;background: rgba(6, 13, 45, 0.8);
}
</style>

总结

OpebLayers 作为 webGIS 客户端的 JavaScript 包,如今的 OpebLayers 功能也在日益完善,在很多项目中已经可以完全可以替代 ArcGIS API for JavaScript,也希望日后 OpebLayers 的更新能带给用户更丰富的体验。

初识webGIS库—OpenLayers相关推荐

  1. DirectX12(D3D12)基础教程(四)——初识DirectXMath库、使用独立堆创建常量缓冲、理解管线状态对象、理解围栏同步

    目录 1.前言及本章内容提要 2.初识DirectXMath库 3.使用独立堆创建常量缓冲 4.理解管线状态对象 5.理解围栏同步 6.完整代码 1.前言及本章内容提要 经过了之前3篇教程的跨度有点大 ...

  2. $python数据分析基础——初识numpy库

    numpy库是python的一个著名的科学计算库,本文是一个quickstart. 引入:计算BMI BMI = 体重(kg)/身高(m)^2 假如有如下几组体重和身高数据,让求每组数据的BMI值: ...

  3. day38 mycql 初识概念,库(增删改查),表(增删改)以及表字段(增删改查),插入更新操作...

    在Navicat中把已经生成的表逆向成模型 数据库上,右键-逆向数据库到模型 ego笔记: 增删改查 文件夹(库)增create database day43 charset utf8;改alter ...

  4. 【WebGIS】Openlayers流动线与风场效果

    目录 基础开发 一.流动线 二.风场 源码 基础开发 一.流动线 效果展示 基础原理 通过openlayers API,设置线段样式 ol/style/Stroke下的 lineDash 和 line ...

  5. Turtle库_初识Turtle库

    在python中,有许多自带的库,无需安装,它们的功能俱全,可以帮助我们完成很多工作,今天我们就来学习比较容易上手的Turtle库. (Turtle在英文中是乌龟

  6. 初识标准库vector

    vector:相同类型对象的集合(不能包含引用,引用不是对象),有索引,是一个类模板,通常称容器. 初始化:与string有些类似,但也有些不同 #include<iostream> #i ...

  7. 【ChatBot开发笔记】聊天机器人准备工作——初识NLTK库、语料与词汇资源

    目录 简述 一.NLTK 1.安装 2.搜索 3.词统计 二.语料与词汇资源 1.举例 2.类似的语料库还有: 3.语料库的通用接口: 4.其他词典资源: 5.加载自己的语料库 结语 简述 2021. ...

  8. OpenLayers加载天地图

    openlayer 是基于JavaScript的webGIS库 ,通过openlayer可以很容易的调用地图,并做相应的操作. 在head中载入openlayer的js文件: <link rel ...

  9. 手把手教你用vue+JavaScript+openlayers+iview制作实时天气预报图

    啥都不说先看效果 还有事件统计功能,以及本地天气预报功能. 这算是前端技术中的webgis相关的知识,这些实现都是用的纯前端加上中国天气网api和高德地图的地理编码的api请求数据.因为这个小demo ...

最新文章

  1. 三年后75%企业数据将移至云端?SAP新应用加速云服务
  2. FilterDispatcher is deprecated! Please use
  3. excel vba 使用mschart_使用VBA时不妨借力Excel催化剂的能力,开发更加轻松便捷
  4. QT学习:QTime类
  5. php简单学生管理系统设计与实现,基于PHP的学生成绩管理系统的设计与实现.doc...
  6. python微信开发实例 pdf 百度网盘_用python看女神微信里的百度云资源有啥?
  7. 原生js制作页面长时间未操作退出登录
  8. 常见的python模块_python常见模块
  9. OpenCV形态学运算
  10. oracle数据库gi,Oracle_RAC数据库GI的PSU升级(11.2.0.4.0到11.2.0.4.8)
  11. 哈工大SCIR Lab | EMNLP 2019 常识信息增强的事件表示学习
  12. EasyUI框架01——基础学习
  13. 撤销Excel文件工作表保护的两种方法
  14. linux: dirent.h 使用
  15. 矿物质电缆的优点与应用场所
  16. 易语言取html显示的文本,易语言 获取网页文本
  17. 电容倍增器作为电源滤波器
  18. 计算机二级Ms-Office选择题汇总
  19. 聆听C++语言创建者的教诲
  20. unity全局总的音频管理器

热门文章

  1. matlab 字数统计,matlab中数据及统计描述和分析.doc
  2. 五名外部董事上岗宝钢集团
  3. M1 芯片mac电脑下载应用运行闪退和没有权限的处理方法?
  4. 嵌入式系统stm32 跑马灯实验
  5. 蓝牙 HID 剖析(一)
  6. System Calls [LKD 05]
  7. 电子信息工程求职目标_求职加油站丨【机电明日招聘】11月5日招聘信息汇总
  8. 骁龙780G怎么样 骁龙780G参数
  9. 基于ssm保险理财系统
  10. Java 使用EasyExcel导出excel文件