文章目录

  • 前言
  • 一、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. 【iOS 开发】iOS 10.3 如何更换 app 图标
  2. 程序计算机限制无法打开,由于一个软件限制策略的阻止,windows无法打开此程序...解决方案参考...
  3. 20165235实验四 Android程序设计
  4. 1、ios开发之 内购
  5. 5G NR 逻辑信道、传输信道和物理信道
  6. 服务器操作系统字符集,设置服务器字符集
  7. C#学习笔记——25个经典问题
  8. Async Program 基本知识 (Process、Thread、Context Switch)
  9. 关于图片轮换与Tab标签
  10. idata界面_iData手持移动终端组合键恢复出厂设置教程
  11. Lucene应用开发揭秘 上线啦!((更新程度:完毕))
  12. UWP 颜色选择器(ColorPicker) 和 自定义的Flyout(AdvancedFlyout)
  13. XML PUBLISHER输出excel存在科学计数
  14. Word2vec 源码详解
  15. 生成特定区间的随机数
  16. 国密 SM4 高并发服务 加压测服务 加生成秘钥 结合上篇一起使用 国密 SM2 SM3 SM4 后续升级版本,内容丰富单独写一篇百万压测4000毫秒加解密
  17. Java商城 架构演化
  18. 农历日期用html怎么显示,怎么显示阴历(农历)日期的js代码?
  19. markdown语法测试
  20. python三维可视化

热门文章

  1. Robotiq+UR3e+Kinect V2 Gazeobo仿真成功,解决robotiq抖动问题
  2. UR3e+robotiq+抓取仿真实验
  3. html有分隔符的输入框,char语句输入分隔符
  4. python-视频声音根据语音识别自动转为带时间的srt字幕文件
  5. 各大搜索引擎提交网站的入口地址
  6. SILKYPIX Developer Studio Pro for Mac v11.0.3 专业的RAW图像处理软件
  7. 摄像头 保存到外网服务器_【小喵科技】物联网教程系列四:喵家外网IOT服务器...
  8. python-输入圆半径,求圆周长和圆面积
  9. java.lang.ClassNotFoundException: Didn't find class com.test.test.activity.MainActivity
  10. 网络设备配置--1、配置交换机enable、console、telnet密码