OpenLayers Layer是什么
Layer(图层)是OpenLayers地图中用于组织和显示地图数据的核心对象。
简单来说:
Layer决定地图上“显示哪一类数据”。
例如一个地图可以包含:
Map
├── 底图
├── 道路
├── 河流
├── 建筑物
├── 行政区
└── POI
这些内容通常可以分别放在不同的Layer中。
例如:
Map
│
├── TileLayer
│ └── 底图
│
├── VectorLayer
│ └── 道路
│
├── VectorLayer
│ └── 行政区
│
└── VectorLayer
└── POI
因此可以把Layer理解为:
地图内容的组织和显示单元。
Layer在OpenLayers中的位置
OpenLayers最重要的数据结构之一是:
Map
↓
Layer
↓
Source
↓
Feature
↓
Geometry
例如:
Map
│
└── VectorLayer
│
└── VectorSource
│
├── Feature
│ └── Point
│
├── Feature
│ └── LineString
│
└── Feature
└── Polygon
其中:
Map
↓
管理整个地图
Layer
↓
组织和显示图层
Source
↓
提供图层数据
Feature
↓
空间要素
Geometry
↓
空间形状
为什么需要Layer
假设一个城市地图中有:
道路
建筑物
河流
行政区
POI
如果所有数据都直接放到Map中,管理会非常困难。
因此可以拆成:
Map
│
├── 道路Layer
├── 建筑Layer
├── 河流Layer
├── 行政区Layer
└── POI Layer
这样就可以单独控制每个图层。
例如:
道路Layer
├── 显示/隐藏
├── 透明度
├── 层级
└── 样式
建筑Layer
├── 显示/隐藏
├── 透明度
├── 层级
└── 样式
Layer的基本创建
OpenLayers提供不同类型的Layer。
例如:
import TileLayer from 'ol/layer/Tile.js'
创建:
const layer = new TileLayer({
source
})
然后添加到Map:
map.addLayer(layer)
基本流程:
创建Layer
↓
配置Source
↓
添加到Map
↓
地图显示
Layer与Source的关系
Layer通常不会直接保存完整的GIS数据。
它主要通过Source获取数据。
例如:
VectorLayer
↓
VectorSource
↓
Feature[]
代码:
const source = new VectorSource({
features
})
const layer = new VectorLayer({
source
})
可以理解为:
Layer
↓
负责显示
Source
↓
负责数据
这是OpenLayers中非常重要的设计。
Layer常见类型
OpenLayers中常见的Layer包括:
TileLayer
ImageLayer
VectorLayer
VectorTileLayer
WebGLTile
不同Layer适合不同的数据。
| Layer | 主要用途 |
|---|---|
| TileLayer | 瓦片地图 |
| ImageLayer | 图片地图 |
| VectorLayer | 普通矢量数据 |
| VectorTileLayer | 矢量瓦片 |
| WebGLTile | WebGL栅格瓦片 |
其中最常使用的是:
TileLayer
VectorLayer
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
↓
地图瓦片
常用于:
- OSM地图
- XYZ瓦片
- WMTS
- 其他瓦片服务
TileLayer的特点
TileLayer不是直接显示一个完整的大地图图片。
它通常将地图切分成大量瓦片:
┌───┬───┬───┐
│ 1 │ 2 │ 3 │
├───┼───┼───┤
│ 4 │ 5 │ 6 │
├───┼───┼───┤
│ 7 │ 8 │ 9 │
└───┴───┴───┘
浏览器只加载当前视野需要的瓦片。
因此非常适合:
大范围地图
在线底图
道路地图
卫星影像
VectorLayer
VectorLayer用于显示普通矢量数据。
例如:
import VectorLayer from 'ol/layer/Vector.js'
import VectorSource from 'ol/source/Vector.js'
const source = new VectorSource()
const layer = new VectorLayer({
source
})
map.addLayer(layer)
结构:
VectorLayer
↓
VectorSource
↓
Feature
↓
Geometry
VectorLayer可以显示:
Point
LineString
Polygon
MultiPoint
MultiLineString
MultiPolygon
VectorLayer适合什么
VectorLayer非常适合业务数据。
例如:
POI
道路
行政区
建筑物
设备
车辆
管线
轨迹
电子围栏
例如:
设备Layer
├── 设备Feature
├── 设备Feature
└── 设备Feature
每个Feature可以包含:
Geometry
+
Properties
例如:
设备Feature
├── Point
├── name
├── status
└── deviceId
VectorTileLayer
VectorTileLayer用于显示矢量瓦片。
例如:
VectorTileLayer
↓
VectorTileSource
↓
MVT
常见格式:
MVT
PBF
与普通VectorLayer相比:
VectorLayer
↓
大量Feature
VectorTileLayer
↓
大量矢量瓦片
VectorTileLayer更适合:
- 全国地图
- 城市地图
- 大规模道路
- 大量建筑物
- 高性能地图
ImageLayer
ImageLayer主要用于显示单张地图影像或图片数据。
例如:
ImageLayer
↓
ImageSource
适合:
- WMS图片
- 服务端生成地图
- 单张地图影像
- 专题地图
与TileLayer相比:
TileLayer
↓
很多瓦片
ImageLayer
↓
一张或少量图片
WebGLTile
WebGLTile主要用于使用WebGL渲染栅格瓦片。
适合处理:
栅格数据
影像
DEM
科学数据
它可以利用GPU提高大规模栅格数据的显示性能。
Layer的visible
Layer可以控制是否显示。
例如:
layer.setVisible(false)
隐藏图层:
visible = false
显示:
layer.setVisible(true)
也可以初始化:
const layer = new VectorLayer({
source,
visible: false
})
这样图层默认不显示。
常用于:
图层开关
图层控制面板
专题图切换
业务图层显示控制
Layer的opacity
opacity用于控制透明度。
例如:
layer.setOpacity(0.5)
其中:
1
↓
完全不透明
0.5
↓
半透明
0
↓
完全透明
例如卫星影像:
imageryLayer.setOpacity(0.7)
可以让下面的矢量图层更加容易观察。
Layer的zIndex
zIndex用于控制图层的显示顺序。
例如:
roadLayer.setZIndex(10)
poiLayer.setZIndex(20)
那么:
POI
↓
zIndex 20
道路
↓
zIndex 10
通常数值越大的图层显示层级越高。
可以理解为:
zIndex
↑
│
POI
道路
行政区
底图
Layer的minZoom
可以限制图层在哪些缩放级别显示。
例如:
const layer = new VectorLayer({
source,
minZoom: 10
})
表示在较小缩放级别时不显示该图层。
适合:
全国范围
↓
不显示POI
城市范围
↓
显示POI
街道范围
↓
显示详细建筑
Layer的maxZoom
也可以限制最大缩放级别。
例如:
const layer = new VectorLayer({
source,
maxZoom: 18
})
这样超过指定缩放级别后图层就不会继续显示。
因此:
minZoom
↓
最小显示缩放级别
maxZoom
↓
最大显示缩放级别
Layer的extent
extent可以限制Layer显示的空间范围。
例如:
const layer = new VectorLayer({
source,
extent: [
12900000,
4800000,
13000000,
4900000
]
})
可以理解为:
只有进入指定空间范围
↓
Layer才参与显示
适合:
- 区域专题图
- 分区数据
- 局部业务图层
Layer的className
可以给Layer设置CSS类名。
例如:
const layer = new VectorLayer({
source,
className: 'road-layer'
})
这样可以方便进行特定的DOM相关控制。
不过需要注意:
OpenLayers的主要地图渲染并不是依赖普通HTML DOM元素完成的。
因此Layer样式控制主要还是通过OpenLayers自身的渲染和Style机制。
Layer的properties
Layer也可以保存自定义属性。
例如:
const layer = new VectorLayer({
source,
properties: {
name: '道路',
type: 'road',
category: 'transport'
}
})
获取:
layer.get('name')
得到:
道路
这对于构建图层管理系统非常有用。
例如:
Layer
├── name
├── type
├── category
└── source
Layer的Source
Layer最重要的配置之一就是Source。
例如:
const layer = new VectorLayer({
source
})
可以动态获取:
const source = layer.getSource()
然后操作Source:
source.addFeature(feature)
因此:
Layer
↓
getSource()
↓
Source
Layer动态添加
地图创建后可以动态添加Layer。
map.addLayer(layer)
例如:
map.addLayer(roadLayer)
map.addLayer(buildingLayer)
map.addLayer(poiLayer)
最终:
Map
├── roadLayer
├── buildingLayer
└── poiLayer
Layer动态删除
可以使用:
map.removeLayer(layer)
例如:
map.removeLayer(poiLayer)
这样POI图层就会从地图中移除。
注意:
removeLayer只是将Layer从Map的图层集合中移除,并不等于删除Layer对象本身。
获取所有Layer
可以:
const layers = map.getLayers()
然后:
layers.forEach(layer => {
console.log(layer)
})
可以用于:
- 图层管理
- 图层排序
- 图层批量控制
- 图层面板
LayerGroup
当Layer数量较多时,可以使用LayerGroup进行组织。
结构:
Map
│
├── 底图
│
└── LayerGroup
├── 道路
├── 建筑
└── POI
例如:
import LayerGroup from 'ol/layer/Group.js'
const group = new LayerGroup({
layers: [
roadLayer,
buildingLayer,
poiLayer
]
})
map.addLayer(group)
这样就可以把多个Layer作为一个整体管理。
LayerGroup的作用
例如:
交通图层组
├── 道路
├── 铁路
└── 地铁
可以整体:
显示
隐藏
管理
例如:
group.setVisible(false)
整个交通图层组都会隐藏。
Layer与LayerGroup
可以理解为:
Layer
↓
单个图层
LayerGroup
↓
多个图层的集合
例如:
Map
│
├── Base Layer
│
├── Transportation Group
│ ├── Road Layer
│ ├── Railway Layer
│ └── Subway Layer
│
└── POI Layer
这种结构非常适合复杂WebGIS应用。
Layer的顺序
多个Layer叠加时需要考虑显示顺序。
例如:
最上层
↓
POI
道路
行政区
卫星影像
底图
↓
最下层
可以使用zIndex控制。
例如:
baseLayer.setZIndex(0)
boundaryLayer.setZIndex(10)
roadLayer.setZIndex(20)
poiLayer.setZIndex(30)
最终:
POI
↓ 30
道路
↓ 20
行政区
↓ 10
底图
↓ 0
Layer与Feature的区别
Layer和Feature非常容易混淆。
它们负责的事情不同。
Layer
↓
组织一组数据
Feature
↓
表示一个具体空间要素
例如:
道路Layer
├── Feature:道路1
├── Feature:道路2
└── Feature:道路3
每个Feature都有自己的Geometry:
道路Feature
↓
LineString
所以:
Layer
↓
Source
↓
Feature[]
↓
Geometry
Layer与Geometry的区别
Geometry描述形状:
Point
LineString
Polygon
Layer描述显示的数据集合。
例如:
POI Layer
↓
Feature
↓
Point
因此不能简单认为:
Layer = Geometry
正确关系是:
Layer
↓
Source
↓
Feature
↓
Geometry
Layer与GeoJSON的关系
GeoJSON是一种数据格式。
Layer是OpenLayers中的地图图层对象。
典型流程:
GeoJSON
↓
GeoJSON Format
↓
Feature[]
↓
VectorSource
↓
VectorLayer
↓
Map
例如:
const features = new GeoJSON().readFeatures(data)
const source = new VectorSource({
features
})
const layer = new VectorLayer({
source
})
map.addLayer(layer)
因此:
GeoJSON不是Layer,而是可以转换成Feature后放入VectorLayer的数据格式。
Layer与WMS的关系
WMS是一种地图服务。
OpenLayers可以通过对应Source加载WMS。
典型结构:
WMS
↓
TileWMS / ImageWMS
↓
TileLayer / ImageLayer
↓
Map
例如:
TileLayer
↓
TileWMS
↓
WMS服务
Layer与XYZ的关系
XYZ主要是一种瓦片访问方式。
结构:
XYZ
↓
XYZ Source
↓
TileLayer
↓
Map
例如:
import XYZ from 'ol/source/XYZ.js'
const source = new XYZ({
url: 'https://example.com/{z}/{x}/{y}.png'
})
const layer = new TileLayer({
source
})
因此:
XYZ
↓
Source
TileLayer
↓
显示瓦片
Layer与WMTS的关系
WMTS是标准瓦片地图服务。
结构:
WMTS
↓
WMTS Source
↓
TileLayer
↓
Map
适合加载:
- 标准地图服务
- 专题地图
- 影像地图
- 地形地图
Layer与Vector Tile的关系
Vector Tile主要使用矢量瓦片。
结构:
MVT
↓
VectorTileSource
↓
VectorTileLayer
↓
Map
适合大规模矢量地图。
例如:
全国道路
↓
大量Vector Tile
↓
VectorTileLayer
↓
地图
Layer样式
不同Layer的样式方式有所不同。
VectorLayer通常使用Style。
例如:
const layer = new VectorLayer({
source,
style: feature => {
return style
}
})
可以根据Feature属性动态设置样式。
例如:
status = online
↓
绿色
status = offline
↓
红色
这在业务GIS中非常常见。
根据Feature设置样式
例如:
const layer = new VectorLayer({
source,
style: feature => {
const status = feature.get('status')
if (status === 'online') {
return onlineStyle
}
return offlineStyle
}
})
这样一个Layer中的不同Feature就可以显示不同效果。
Layer与性能
Layer并不是越多越好。
例如:
Map
├── Layer 1
├── Layer 2
├── Layer 3
├── ...
└── Layer 1000
过多Layer会增加管理和渲染复杂度。
设计地图时应该合理组织:
底图
↓
专题图层
↓
业务图层
↓
交互图层
对于大量数据,还需要考虑:
Vector Tile
数据分级
空间索引
按缩放级别加载
按范围加载
WebGL
Layer常见应用结构
一个实际的城市GIS系统可能是:
Map
│
├── BaseMap
│
├── AdministrativeLayer
│
├── RoadLayer
│
├── BuildingLayer
│
├── RiverLayer
│
├── POILayer
│
├── DeviceLayer
│
└── InteractionLayer
其中:
BaseMap
↓
底图
AdministrativeLayer
↓
行政区
RoadLayer
↓
道路
BuildingLayer
↓
建筑
DeviceLayer
↓
业务设备
InteractionLayer
↓
选择、高亮、绘制
推荐的Layer设计
实际项目中,可以按照业务类型组织:
Map
│
├── Base
│ └── BaseLayer
│
├── GIS
│ ├── BoundaryLayer
│ ├── RoadLayer
│ ├── RiverLayer
│ └── BuildingLayer
│
├── Business
│ ├── DeviceLayer
│ ├── VehicleLayer
│ └── POILayer
│
└── Interaction
├── SelectionLayer
├── DrawLayer
└── HighlightLayer
这种结构比把所有Feature都放到一个VectorLayer中更加容易维护。
Layer核心关系
OpenLayers中Layer最重要的关系可以总结为:
Map
↓
Layer
↓
Source
↓
Feature
↓
Geometry
不同数据对应不同Layer:
瓦片
↓
TileLayer
普通矢量
↓
VectorLayer
矢量瓦片
↓
VectorTileLayer
图片
↓
ImageLayer
栅格瓦片
↓
WebGLTile
Layer核心属性
常用Layer属性包括:
source
visible
opacity
zIndex
minZoom
maxZoom
extent
className
properties
其中最常使用的是:
source
visible
opacity
zIndex
Layer常用操作
添加
map.addLayer(layer)
删除
map.removeLayer(layer)
获取Source
layer.getSource()
显示
layer.setVisible(true)
隐藏
layer.setVisible(false)
设置透明度
layer.setOpacity(0.5)
设置层级
layer.setZIndex(10)
设置属性
layer.set('name', '道路')
Layer知识结构
可以用下面的结构理解OpenLayers Layer:
Layer
│
├── TileLayer
│ └── TileSource
│ ├── OSM
│ ├── XYZ
│ └── WMTS
│
├── ImageLayer
│ └── ImageSource
│ └── WMS
│
├── VectorLayer
│ └── VectorSource
│ └── Feature
│ └── Geometry
│
├── VectorTileLayer
│ └── VectorTileSource
│ └── MVT
│
└── WebGLTile
└── TileSource
总结
Layer是OpenLayers地图中的核心组成部分,主要负责组织和显示地图数据。
最重要的关系是:
Map
↓
Layer
↓
Source
↓
Feature
↓
Geometry
常见Layer包括:
TileLayer
VectorLayer
ImageLayer
VectorTileLayer
WebGLTile
可以记住:
TileLayer主要显示瓦片,VectorLayer主要显示普通矢量数据,ImageLayer主要显示图片地图,VectorTileLayer主要显示矢量瓦片,而Layer通过Source获取数据并最终显示在Map中。
掌握Layer之后,下一步可以继续学习OpenLayers中的Source,理解VectorSource、XYZ、WMTS、TileWMS以及ImageWMS等数据源是如何与Layer配合工作的。
相关工具
使用 IYATools 在线工具快速处理 GIS 数据