GIS

OpenLayers是什么

了解OpenLayers的基本概念、核心能力、地图组成以及OpenLayers与Map、Layer、Source、Feature和Geometry之间的关系。

阅读约 165 分钟

OpenLayers是什么

OpenLayers是一个开源的JavaScript地图开发库,用于在Web浏览器中创建交互式地图应用。

它可以帮助开发者在网页中实现:

  • 地图显示
  • 地图缩放
  • 地图平移
  • 图层管理
  • 矢量数据展示
  • GeoJSON加载
  • WKT数据处理
  • 地图交互
  • 空间要素编辑
  • 坐标转换
  • 地图事件处理

简单来说:

OpenLayers是一套用于开发WebGIS地图应用的JavaScript库。

例如:

OpenLayers
    ↓
创建Map
    ↓
添加Layer
    ↓
加载Source
    ↓
管理Feature
    ↓
显示Geometry
    ↓
浏览器地图

OpenLayers能够做什么

OpenLayers主要用于构建WebGIS应用。

常见功能包括:

地图
├── 缩放
├── 平移
├── 旋转
├── 图层
├── 标注
├── 要素
├── 绘制
├── 编辑
├── 查询
└── 空间数据展示

例如一个城市地图可以包含:

底图
├── 道路
├── 河流
├── 建筑物
├── 行政区
├── POI
└── 业务数据

这些数据都可以通过OpenLayers显示在浏览器中。

OpenLayers与GIS的关系

GIS是一整套地理信息系统技术。

OpenLayers则主要负责:

Web端地图显示与交互

可以理解为:

GIS
│
├── 空间数据库
├── 空间分析
├── 坐标系统
├── 数据格式
├── 地图服务
└── WebGIS
      ↓
  OpenLayers

OpenLayers本身不是空间数据库,也不是完整的GIS软件。

它更像是:

WebGIS前端地图引擎。

OpenLayers基本结构

OpenLayers最核心的结构可以理解为:

Map
│
├── View
│
├── Layer
│   ├── TileLayer
│   └── VectorLayer
│
└── Control

而Layer下面通常还有:

Layer
    ↓
Source
    ↓
Feature
    ↓
Geometry

因此完整结构可以表示为:

Map
 ↓
Layer
 ↓
Source
 ↓
Feature
 ↓
Geometry

这是理解OpenLayers最重要的结构之一。

Map

Map是OpenLayers地图的核心对象。

创建地图:

import Map from 'ol/Map.js'

const map = new Map({
  target: 'map'
})

其中:

Map
 ↓
整个地图实例

Map负责组织:

  • 图层
  • 视图
  • 控件
  • 交互
  • 地图事件

例如:

Map
├── View
├── Layers
├── Controls
└── Interactions

target

OpenLayers地图需要挂载到HTML元素。

例如:

<div id="map"></div>

然后:

const map = new Map({
  target: 'map'
})

这样OpenLayers就会将地图渲染到:

#map

元素中。

View

View用于控制地图的观察状态。

例如:

import View from 'ol/View.js'

const view = new View({
  center: [12950000, 4850000],
  zoom: 10
})

然后:

const map = new Map({
  target: 'map',
  view
})

View主要负责:

  • 中心点
  • 缩放级别
  • 旋转角度
  • 分辨率
  • 投影

可以理解为:

Map
 ↓
View
 ↓
决定用户看到地图的哪个位置

center

center表示地图中心点。

例如:

center: [12950000, 4850000]

这里的坐标通常需要与地图View使用的投影一致。

WebGIS中常见的是:

EPSG:3857

zoom

zoom表示地图缩放级别。

例如:

zoom: 10

通常:

zoom越小
 ↓
看到范围越大

zoom越大
 ↓
看到范围越小

可以理解为:

zoom 3
 ↓
全国范围

zoom 10
 ↓
城市范围

zoom 16
 ↓
街道范围

具体效果取决于地图View和分辨率配置。

Layer

Layer是地图图层。

OpenLayers常见Layer包括:

TileLayer
VectorLayer
ImageLayer
WebGLTile

例如:

import TileLayer from 'ol/layer/Tile.js'

const layer = new TileLayer({
  source
})

然后:

map.addLayer(layer)

地图就可以显示这个图层。

TileLayer

TileLayer主要用于显示瓦片地图。

例如:

import TileLayer from 'ol/layer/Tile.js'
import OSM from 'ol/source/OSM.js'

const layer = new TileLayer({
  source: new OSM()
})

map.addLayer(layer)

结构:

TileLayer
    ↓
OSM Source
    ↓
地图瓦片

常用于:

  • OSM底图
  • XYZ地图
  • WMTS
  • 其他瓦片服务

VectorLayer

VectorLayer用于显示矢量数据。

例如:

import VectorLayer from 'ol/layer/Vector.js'

const layer = new VectorLayer({
  source
})

map.addLayer(layer)

结构:

VectorLayer
    ↓
VectorSource
    ↓
Feature
    ↓
Geometry

常用于:

  • 线
  • GeoJSON
  • WKT
  • 用户绘制数据
  • 业务要素

Source

Source用于管理Layer的数据来源。

例如:

Layer
 ↓
Source

不同Layer通常对应不同类型的Source。

例如:

TileLayer
 ↓
TileSource

VectorLayer
 ↓
VectorSource

VectorSource:

import VectorSource from 'ol/source/Vector.js'

const source = new VectorSource()

它可以管理多个Feature。

Feature

Feature是OpenLayers中的地图要素。

例如一个城市:

Feature
├── Geometry
│   └── Point
│
└── Properties
    ├── name
    └── type

创建Feature:

import Feature from 'ol/Feature.js'

例如:

const feature = new Feature({
  geometry,
  name: '北京'
})

Feature主要由两部分组成:

Feature
├── Geometry
└── Properties

因此:

Feature可以理解为一个具有空间几何和属性信息的GIS对象。

Geometry

Geometry负责描述空间形状。

常见类型:

Point
LineString
Polygon
MultiPoint
MultiLineString
MultiPolygon

例如:

import Point from 'ol/geom/Point.js'

const point = new Point([
  12950000,
  4850000
])

然后:

const feature = new Feature({
  geometry: point
})

关系:

Feature
    ↓
Geometry
    ↓
Point

Feature属性

Feature除了Geometry,还可以保存业务属性。

例如:

const feature = new Feature({
  geometry: point,
  name: '北京',
  type: 'city',
  level: 1
})

读取:

feature.get('name')

得到:

北京

也可以:

feature.getProperties()

获得所有属性。

因此:

Feature
├── geometry
├── name
├── type
└── level

VectorSource

VectorSource是矢量Feature的容器。

例如:

const source = new VectorSource({
  features: [
    feature
  ]
})

也可以动态添加:

source.addFeature(feature)

添加多个:

source.addFeatures(features)

获取:

source.getFeatures()

结构:

VectorSource
├── Feature
├── Feature
├── Feature
└── Feature

VectorLayer与VectorSource

VectorLayer负责显示:

VectorLayer

VectorSource负责管理数据:

VectorSource

因此:

VectorLayer
    ↓
VectorSource
    ↓
Feature[]

可以理解为:

Layer
 ↓
负责地图显示

Source
 ↓
负责数据管理

GeoJSON

OpenLayers支持GeoJSON。

首先:

import GeoJSON from 'ol/format/GeoJSON.js'

读取GeoJSON:

const format = new GeoJSON()

const features = format.readFeatures(data)

然后:

const source = new VectorSource({
  features
})

最后:

const layer = new VectorLayer({
  source
})

完整流程:

GeoJSON
 ↓
GeoJSON Format
 ↓
Feature[]
 ↓
VectorSource
 ↓
VectorLayer
 ↓
Map

WKT

OpenLayers也支持WKT。

例如:

POINT (116.397 39.908)

可以使用:

import WKT from 'ol/format/WKT.js'

const format = new WKT()

const feature = format.readFeature(wkt)

然后:

WKT
 ↓
readFeature()
 ↓
Feature
 ↓
VectorSource
 ↓
VectorLayer

坐标系

OpenLayers中的地图坐标非常依赖坐标参考系统。

常见:

EPSG:4326
EPSG:3857

例如:

GeoJSON
EPSG:4326
    ↓
坐标转换
    ↓
OpenLayers
EPSG:3857

读取GeoJSON时:

const features = format.readFeatures(data, {
  dataProjection: 'EPSG:4326',
  featureProjection: 'EPSG:3857'
})

因此开发OpenLayers应用时必须明确:

数据坐标系
    ↓
地图坐标系

Projection

OpenLayers中的View可以指定projection。

例如:

const view = new View({
  projection: 'EPSG:3857',
  center: [12950000, 4850000],
  zoom: 10
})

这样地图View就使用:

EPSG:3857

作为地图坐标系。

地图控件

OpenLayers提供了一系列Controls。

例如:

Zoom
Rotate
FullScreen
ScaleLine
MousePosition
OverviewMap
ZoomSlider

例如:

import ScaleLine from 'ol/control/ScaleLine.js'

map.addControl(
  new ScaleLine()
)

可以在地图上显示比例尺。

地图交互

OpenLayers支持多种地图交互。

常见:

缩放
平移
旋转
绘制
修改
选择
拖拽

例如Draw:

import Draw from 'ol/interaction/Draw.js'

const draw = new Draw({
  source,
  type: 'Point'
})

map.addInteraction(draw)

用户就可以在地图上绘制Point。

Select

可以通过Select选择地图要素。

例如:

import Select from 'ol/interaction/Select.js'

const select = new Select()

map.addInteraction(select)

当用户点击Feature时,可以获取选中的要素。

select.on('select', event => {
  console.log(event.selected)
})

Modify

Modify用于编辑Feature。

例如:

import Modify from 'ol/interaction/Modify.js'

const modify = new Modify({
  source
})

map.addInteraction(modify)

用户可以直接拖动Geometry的节点修改空间数据。

Draw

Draw可以创建:

Point
LineString
Polygon
Circle

例如绘制Polygon:

const draw = new Draw({
  source,
  type: 'Polygon'
})

用户绘制完成后:

Draw
 ↓
Geometry
 ↓
Feature
 ↓
VectorSource

Style

OpenLayers中的Feature可以设置样式。

例如:

import Style from 'ol/style/Style.js'
import Fill from 'ol/style/Fill.js'
import Stroke from 'ol/style/Stroke.js'

const style = new Style({
  fill: new Fill({
    color: 'rgba(0, 120, 255, 0.2)'
  }),
  stroke: new Stroke({
    color: '#0078ff',
    width: 2
  })
})

然后:

const layer = new VectorLayer({
  source,
  style
})

这样VectorLayer中的Feature就可以按照指定样式显示。

Point样式

Point通常使用:

Circle
Icon
Text

例如:

import CircleStyle from 'ol/style/Circle.js'

const style = new Style({
  image: new CircleStyle({
    radius: 6,
    fill: new Fill({
      color: '#1677ff'
    })
  })
})

LineString样式

LineString通常使用Stroke:

const style = new Style({
  stroke: new Stroke({
    color: '#1677ff',
    width: 3
  })
})

适用于:

  • 道路
  • 河流
  • 管线
  • GPS轨迹

Polygon样式

Polygon通常使用:

Fill
Stroke

例如:

const style = new Style({
  fill: new Fill({
    color: 'rgba(22, 119, 255, 0.2)'
  }),
  stroke: new Stroke({
    color: '#1677ff',
    width: 2
  })
})

OpenLayers事件

OpenLayers提供大量事件。

例如:

click
singleclick
pointermove
movestart
moveend

监听点击:

map.on('singleclick', event => {
  console.log(event.coordinate)
})

可以获得点击位置。

Feature点击查询

可以通过:

map.forEachFeatureAtPixel()

查询鼠标点击位置的Feature。

例如:

map.on('singleclick', event => {
  map.forEachFeatureAtPixel(
    event.pixel,
    feature => {
      console.log(feature)
    }
  )
})

流程:

用户点击地图
    ↓
Pixel
    ↓
forEachFeatureAtPixel()
    ↓
Feature

这是WebGIS业务开发中非常常见的功能。

地图数据来源

OpenLayers可以加载很多类型的数据。

例如:

GeoJSON
WKT
KML
GPX
TopoJSON
XYZ
WMTS
WMS
Vector Tile

可以理解为:

数据格式
    ↓
OpenLayers Format / Source
    ↓
Layer
    ↓
Map

WMS

WMS主要用于加载地图服务。

通常:

WMS
 ↓
ImageLayer / TileLayer
 ↓
Map

WMS返回的通常是地图图片,而不是普通Feature集合。

适合:

  • 地图服务
  • 专题图
  • 服务端渲染地图

WMTS

WMTS是瓦片地图服务。

通常:

WMTS
 ↓
TileLayer
 ↓
Map

适合高性能地图浏览。

XYZ

XYZ是Web地图中非常常见的瓦片组织方式。

典型结构:

/{z}/{x}/{y}.png

其中:

z
 ↓
缩放级别

x
 ↓
列

y
 ↓
行

OpenLayers可以使用XYZ Source加载这种地图。

Vector Tile

Vector Tile用于高性能矢量地图。

例如:

MVT
 ↓
VectorTileSource
 ↓
VectorTileLayer
 ↓
Map

相比大量普通Feature,Vector Tile更适合:

  • 大规模道路
  • 城市地图
  • 全国地图
  • 高性能矢量地图

OpenLayers与Cesium

OpenLayers主要用于:

二维WebGIS

而Cesium主要用于:

三维地球

可以简单理解为:

OpenLayers
 ↓
2D地图

Cesium
 ↓
3D地球

如果主要需求是:

  • 业务地图
  • GIS数据编辑
  • GeoJSON
  • WMS
  • WFS
  • 矢量图层

OpenLayers非常适合。

如果主要需求是:

  • 三维地球
  • 地形
  • 三维建筑
  • 三维城市
  • 大规模三维场景

则通常考虑Cesium。

OpenLayers完整数据结构

一个典型OpenLayers地图可以理解为:

Map
│
├── View
│
├── Controls
│
├── Interactions
│
└── Layers
    │
    ├── TileLayer
    │   └── TileSource
    │
    └── VectorLayer
        └── VectorSource
            │
            ├── Feature
            │   ├── Geometry
            │   └── Properties
            │
            ├── Feature
            │   ├── Geometry
            │   └── Properties
            │
            └── Feature

这是学习OpenLayers最重要的一张结构图。

OpenLayers核心对象

可以将OpenLayers核心对象分成几个部分。

地图

Map
View

图层

Layer
TileLayer
VectorLayer

数据源

Source
VectorSource
XYZ
WMTS
WMS

空间要素

Feature
Geometry

数据格式

GeoJSON
WKT
KML
GPX

交互

Select
Draw
Modify
Translate

控件

Zoom
ScaleLine
FullScreen
MousePosition

OpenLayers开发基本流程

一个典型OpenLayers项目通常按照以下步骤开发:

1. 创建Map
        ↓
2. 创建View
        ↓
3. 创建地图底图
        ↓
4. 创建Source
        ↓
5. 加载数据
        ↓
6. 创建Layer
        ↓
7. 添加到Map
        ↓
8. 添加Interaction
        ↓
9. 添加Control
        ↓
10. 处理业务事件

例如:

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new OSM()
    })
  ],
  view: new View({
    center: [12950000, 4850000],
    zoom: 10
  })
})

一个简单的矢量地图

import Map from 'ol/Map.js'
import View from 'ol/View.js'
import Feature from 'ol/Feature.js'
import Point from 'ol/geom/Point.js'
import VectorSource from 'ol/source/Vector.js'
import VectorLayer from 'ol/layer/Vector.js'

const feature = new Feature({
  geometry: new Point([
    12950000,
    4850000
  ]),
  name: '示例点'
})

const source = new VectorSource({
  features: [feature]
})

const layer = new VectorLayer({
  source
})

const map = new Map({
  target: 'map',
  layers: [
    layer
  ],
  view: new View({
    center: [
      12950000,
      4850000
    ],
    zoom: 10
  })
})

数据关系:

Point
 ↓
Feature
 ↓
VectorSource
 ↓
VectorLayer
 ↓
Map

OpenLayers的核心思想

学习OpenLayers时,不要只记API。

最重要的是理解:

Map
 ↓
Layer
 ↓
Source
 ↓
Feature
 ↓
Geometry

其中:

Map
 ↓
管理整个地图

Layer
 ↓
负责图层

Source
 ↓
负责数据来源

Feature
 ↓
负责空间要素

Geometry
 ↓
负责空间形状

另外:

View
 ↓
控制地图视角

Interaction
 ↓
处理用户操作

Control
 ↓
提供地图控件

Format
 ↓
处理GIS数据格式

OpenLayers与GeoJSON的关系

GeoJSON是数据格式:

GeoJSON

OpenLayers是地图开发库:

OpenLayers

二者不是同一个概念。

通常:

GeoJSON
 ↓
GeoJSON Format
 ↓
Feature
 ↓
VectorSource
 ↓
VectorLayer
 ↓
OpenLayers Map

OpenLayers与Feature的关系

Feature是OpenLayers地图中的核心矢量对象。

OpenLayers
    ↓
Feature
    ↓
Geometry + Properties

Feature可以来自:

GeoJSON
WKT
KML
Draw
API
数据库
手工创建

因此Feature是连接外部GIS数据和OpenLayers地图的重要对象。

OpenLayers与Geometry的关系

Geometry描述空间形状:

Point
LineString
Polygon

Feature持有Geometry:

Feature
 ↓
Geometry

VectorSource管理Feature:

VectorSource
 ↓
Feature[]

VectorLayer显示VectorSource:

VectorLayer
 ↓
VectorSource

最终:

Geometry
 ↓
Feature
 ↓
VectorSource
 ↓
VectorLayer
 ↓
Map

总结

OpenLayers是一个用于开发WebGIS应用的开源JavaScript地图库。

它的核心结构可以记住:

Map
 ↓
Layer
 ↓
Source
 ↓
Feature
 ↓
Geometry

其中:

Map
    ↓
地图容器

View
    ↓
地图视角

Layer
    ↓
地图图层

Source
    ↓
数据来源

Feature
    ↓
空间要素

Geometry
    ↓
空间形状

Interaction
    ↓
用户交互

Control
    ↓
地图控件

Format
    ↓
GIS数据格式转换

最重要的开发思维是:

OpenLayers负责Web地图的显示和交互,Layer负责组织图层,Source负责管理数据,Feature负责描述空间要素,Geometry负责描述空间形状,而GeoJSON、WKT等负责与外部GIS数据进行交换。

掌握这套结构之后,就可以继续学习OpenLayers中的MapViewLayerSourceFeatureGeometryGeoJSONWKTDrawSelect以及Modify等核心知识。

🧰

相关工具

使用 IYATools 在线工具快速处理 GIS 数据