OpenLayers Feature是什么
在OpenLayers中,Feature(要素)是用于表示一个具有空间几何和属性信息的地图对象。
例如:
- 一个城市
- 一条道路
- 一个建筑物
- 一个商店
- 一个行政区域
- 一个设备
- 一个轨迹
都可以在OpenLayers中表示为Feature。
简单来说:
Feature = Geometry + Attributes
例如:
Feature
├── Geometry
│ └── Point
│ └── 坐标
│
└── Properties
├── name
├── type
└── status
Feature是OpenLayers矢量数据开发中非常核心的对象。
Feature的基本结构
一个Feature通常包含:
Feature
├── Geometry
├── Properties
├── Style
└── ID
其中:
Geometry
↓
描述空间位置和形状
Properties
↓
描述业务属性
Style
↓
控制地图显示效果
ID
↓
标识Feature
例如一个商店Feature:
Feature
├── Geometry
│ └── Point
│ └── [116.397, 39.908]
│
├── Properties
│ ├── name = 商店A
│ ├── type = shop
│ └── status = open
│
└── Style
└── 图标
创建Feature
OpenLayers可以通过Feature创建一个要素。
import Feature from 'ol/Feature.js'
import Point from 'ol/geom/Point.js'
const feature = new Feature({
geometry: new Point([116.397, 39.908])
})
这样就创建了一个Point Feature。
结构:
Feature
↓
Point
↓
[116.397, 39.908]
Feature的Geometry
Feature最重要的组成部分之一就是Geometry。
例如:
const feature = new Feature({
geometry: new Point([116.397, 39.908])
})
这里:
Feature
↓
geometry
↓
Point
Feature本身负责描述一个完整地图对象,而Geometry负责描述这个对象的空间形状。
Point Feature
Point是最常见的Feature类型之一。
import Feature from 'ol/Feature.js'
import Point from 'ol/geom/Point.js'
const feature = new Feature({
geometry: new Point([116.397, 39.908])
})
可以表示:
商店
医院
学校
摄像头
充电桩
设备
例如:
Feature
└── Point
└── [116.397, 39.908]
LineString Feature
LineString可以表示线状对象。
import LineString from 'ol/geom/LineString.js'
const feature = new Feature({
geometry: new LineString([
[116.397, 39.908],
[116.405, 39.915],
[116.412, 39.920]
])
})
可以表示:
道路
河流
铁路
管线
GPS轨迹
结构:
Feature
└── LineString
├── Point
├── Point
└── Point
Polygon Feature
Polygon用于表示区域。
import Polygon from 'ol/geom/Polygon.js'
const feature = new Feature({
geometry: new Polygon([
[
[116.390, 39.900],
[116.400, 39.900],
[116.400, 39.910],
[116.390, 39.910],
[116.390, 39.900]
]
])
})
可以表示:
行政区
建筑物
地块
公园
湖泊
规划区域
MultiGeometry
Feature的Geometry并不一定只能是单个对象。
也可以使用:
MultiPoint
MultiLineString
MultiPolygon
GeometryCollection
例如:
import MultiPoint from 'ol/geom/MultiPoint.js'
const feature = new Feature({
geometry: new MultiPoint([
[116.397, 39.908],
[116.405, 39.915],
[116.412, 39.920]
])
})
因此:
Feature
↓
Geometry
├── Point
├── LineString
├── Polygon
├── MultiPoint
├── MultiLineString
└── MultiPolygon
Feature属性
Feature除了Geometry之外,还可以保存业务属性。
例如:
const feature = new Feature({
geometry: new Point([116.397, 39.908]),
name: '商店A',
type: 'shop',
status: 'open'
})
这些属性可以用于:
查询
筛选
弹窗
标注
样式
业务逻辑
例如:
feature.get('name')
得到:
商店A
get属性
可以使用get()读取Feature属性。
const name = feature.get('name')
const type = feature.get('type')
const status = feature.get('status')
例如:
console.log(feature.get('name'))
输出:
商店A
set属性
可以使用set()修改属性。
feature.set('status', 'closed')
也可以:
feature.set('name', '新商店')
修改后:
name
↓
新商店
getProperties
可以获取Feature的全部属性。
const properties = feature.getProperties()
例如:
{
geometry: ...,
name: '商店A',
type: 'shop',
status: 'open'
}
需要注意,Geometry本身也属于Feature对象的一个特殊属性。
Geometry的获取
可以使用:
const geometry = feature.getGeometry()
例如:
const geometry = feature.getGeometry()
console.log(geometry)
返回:
Point
LineString
Polygon
等Geometry对象。
修改Geometry
可以通过:
feature.setGeometry(newGeometry)
修改Feature的Geometry。
例如:
feature.setGeometry(
new Point([116.410, 39.920])
)
原来的位置:
[116.397, 39.908]
变成:
[116.410, 39.920]
因此Feature可以动态移动。
Feature与Geometry的关系
需要特别理解:
Feature
↓
Geometry
Geometry负责:
位置
形状
坐标
Feature负责:
Geometry
+
业务属性
+
样式
+
标识
因此:
Geometry
↓
空间对象
Feature
↓
完整地图要素
Feature与VectorSource
Feature通常不会直接添加到Map。
典型结构是:
Map
↓
VectorLayer
↓
VectorSource
↓
Feature
↓
Geometry
例如:
import VectorSource from 'ol/source/Vector.js'
const source = new VectorSource({
features: [feature]
})
这里:
VectorSource
↓
管理Feature集合
Feature添加到VectorSource
也可以动态添加:
source.addFeature(feature)
多个Feature:
source.addFeatures([
feature1,
feature2,
feature3
])
结构:
VectorSource
├── Feature 1
├── Feature 2
└── Feature 3
Feature删除
删除一个Feature:
source.removeFeature(feature)
删除全部Feature:
source.clear()
例如:
source.clear()
可以清空当前VectorSource中的所有Feature。
VectorLayer
VectorLayer负责将VectorSource中的Feature显示到地图上。
import VectorLayer from 'ol/layer/Vector.js'
const layer = new VectorLayer({
source
})
完整关系:
Map
↓
VectorLayer
↓
VectorSource
↓
Feature
↓
Geometry
这是OpenLayers矢量图层最重要的结构之一。
创建完整Feature
例如创建一个商店:
const feature = new Feature({
geometry: new Point([116.397, 39.908]),
name: '商店A',
type: 'shop',
status: 'open'
})
创建Source:
const source = new VectorSource({
features: [feature]
})
创建Layer:
const layer = new VectorLayer({
source
})
最后添加到Map:
map.addLayer(layer)
整体结构:
Map
↓
VectorLayer
↓
VectorSource
↓
Feature
├── Geometry
│ └── Point
│
└── Properties
├── name
├── type
└── status
Feature样式
Feature可以设置自己的Style。
例如:
import Style from 'ol/style/Style.js'
import CircleStyle from 'ol/style/Circle.js'
import Fill from 'ol/style/Fill.js'
import Stroke from 'ol/style/Stroke.js'
feature.setStyle(
new Style({
image: new CircleStyle({
radius: 6,
fill: new Fill({
color: '#1677ff'
}),
stroke: new Stroke({
color: '#ffffff',
width: 2
})
})
})
)
这样Point Feature就可以显示为一个圆形标记。
Feature Style与Layer Style
OpenLayers中既可以给Feature设置Style,也可以给Layer设置Style。
Feature Style:
feature.setStyle(style)
Layer Style:
const layer = new VectorLayer({
source,
style
})
可以理解为:
Feature Style
↓
控制单个Feature
Layer Style
↓
控制整个图层中的Feature
根据属性设置样式
实际项目中经常根据Feature属性动态设置Style。
例如:
const layer = new VectorLayer({
source,
style: (feature) => {
const status = feature.get('status')
if (status === 'warning') {
return warningStyle
}
return normalStyle
}
})
这样可以实现:
status = normal
↓
普通样式
status = warning
↓
警告样式
常用于:
设备监控
车辆监控
告警地图
人口地图
业务专题图
Feature事件
Feature支持属性变化等事件。
例如:
feature.on('change', () => {
console.log('Feature发生变化')
})
当Feature发生变化时,可以进行相关处理。
Geometry变化事件
如果需要监听Geometry变化,可以:
const geometry = feature.getGeometry()
geometry.on('change', () => {
console.log('Geometry发生变化')
})
例如用户拖动Feature时:
用户拖动
↓
Geometry坐标改变
↓
Geometry change
↓
更新业务数据
Feature ID
Feature可以设置唯一ID。
feature.setId('shop-001')
获取:
feature.getId()
返回:
shop-001
ID常用于:
数据更新
数据删除
Feature定位
业务对象关联
例如:
Feature
id = device-001
可以对应后端数据库:
device_id = device-001
Feature与后端数据
实际项目中,Feature通常来自后端GIS数据。
例如后端返回:
{
"id": 1,
"name": "商店A",
"type": "shop",
"geometry": {
"type": "Point",
"coordinates": [116.397, 39.908]
}
}
前端转换后:
Backend Data
↓
GeoJSON
↓
OpenLayers
↓
Feature
GeoJSON转换为Feature
OpenLayers提供GeoJSON格式转换能力。
import GeoJSON from 'ol/format/GeoJSON.js'
const format = new GeoJSON()
const features = format.readFeatures(geojson)
这样可以将GeoJSON转换成OpenLayers Feature。
结构:
GeoJSON
↓
readFeatures()
↓
Feature[]
Feature转换为GeoJSON
也可以将Feature转换为GeoJSON。
const geojson = format.writeFeature(feature)
多个Feature:
const geojson = format.writeFeatures(features)
因此:
GeoJSON
↓
Feature
Feature
↓
GeoJSON
这对于前后端GIS数据交换非常重要。
Feature与WKT
如果后端使用WKT:
POINT (116.397 39.908)
可以先通过WKT格式解析器转换成Geometry或Feature。
典型流程:
WKT
↓
OpenLayers Format
↓
Feature
↓
VectorSource
↓
VectorLayer
↓
Map
因此Feature是各种GIS数据格式进入OpenLayers地图渲染体系的重要中间对象。
Feature选择
OpenLayers可以对地图上的Feature进行选择。
例如:
import Select from 'ol/interaction/Select.js'
const select = new Select()
map.addInteraction(select)
用户点击Feature后:
用户点击
↓
Select
↓
Feature
↓
selected Feature
可以获取:
select.getFeatures()
Feature点击事件
可以监听Select:
select.on('select', (event) => {
const feature = event.selected[0]
if (feature) {
console.log(feature.get('name'))
}
})
例如:
点击地图对象
↓
获取Feature
↓
读取name
↓
显示弹窗
Feature弹窗
一个常见的WebGIS流程:
用户点击Feature
↓
获取Feature
↓
feature.getProperties()
↓
业务属性
↓
Overlay
↓
Popup
例如:
select.on('select', (event) => {
const feature = event.selected[0]
if (!feature) {
return
}
const name = feature.get('name')
console.log(name)
})
然后可以将数据放到Popup中。
Feature拖动
OpenLayers可以通过交互实现Feature拖动。
例如:
import Translate from 'ol/interaction/Translate.js'
const translate = new Translate({
features: select.getFeatures()
})
map.addInteraction(translate)
拖动完成后可以获取新的Geometry:
translate.on('translateend', (event) => {
event.features.forEach((feature) => {
const geometry = feature.getGeometry()
console.log(geometry)
})
})
典型流程:
用户拖动
↓
Feature
↓
Geometry坐标改变
↓
translateend
↓
保存新坐标
Feature编辑
Feature编辑是WebGIS中非常常见的功能。
典型工具:
Draw
Modify
Translate
Snap
Select
流程:
用户选择Feature
↓
Modify
↓
修改Geometry
↓
获取新Geometry
↓
提交后端
Feature与Draw
Draw可以创建新的Feature。
例如:
import Draw from 'ol/interaction/Draw.js'
const draw = new Draw({
source,
type: 'Point'
})
map.addInteraction(draw)
用户点击地图:
用户点击
↓
Draw
↓
创建Geometry
↓
创建Feature
↓
VectorSource
监听:
draw.on('drawend', (event) => {
const feature = event.feature
console.log(feature)
})
Feature与Modify
Modify用于修改Feature的Geometry。
import Modify from 'ol/interaction/Modify.js'
const modify = new Modify({
source
})
map.addInteraction(modify)
例如修改Polygon:
Polygon Feature
↓
Modify
↓
拖动顶点
↓
Geometry改变
↓
新的Polygon
Feature与Snap
编辑线和面时,经常需要吸附。
import Snap from 'ol/interaction/Snap.js'
const snap = new Snap({
source
})
map.addInteraction(snap)
可以实现:
顶点
↓
吸附
↓
已有Geometry顶点
这对于:
地籍编辑
道路编辑
规划数据编辑
管网编辑
非常重要。
Feature与空间数据
Feature可以看作OpenLayers中的业务空间对象。
例如:
城市
↓
Feature
道路
↓
Feature
建筑
↓
Feature
设备
↓
Feature
每个Feature通常包含:
Geometry
+
Properties
+
Style
+
ID
Feature与Layer的关系
Feature不是Layer。
两者职责不同:
Feature
↓
一个地图对象
VectorSource
↓
管理多个Feature
VectorLayer
↓
显示一组Feature
Map
↓
显示多个Layer
完整结构:
Map
├── VectorLayer
│ └── VectorSource
│ ├── Feature
│ ├── Feature
│ └── Feature
│
└── TileLayer
└── TileSource
Feature与VectorSource的区别
Feature:
一个对象
VectorSource:
一组Feature的容器
例如:
VectorSource
├── 商店A
├── 商店B
├── 商店C
└── 医院A
这些对象都是Feature。
Feature与GeoJSON Feature的区别
这两个概念名称相同,但不是完全相同的东西。
GeoJSON Feature:
{
"type": "Feature",
"geometry": {},
"properties": {}
}
OpenLayers Feature:
ol/Feature
它是OpenLayers中的JavaScript对象。
可以理解为:
GeoJSON Feature
↓
数据格式中的Feature
OpenLayers Feature
↓
OpenLayers运行时对象
OpenLayers可以将GeoJSON Feature转换成自己的Feature对象。
Feature与Geometry的核心区别
可以记住:
Geometry
↓
只关心空间形状
Feature
↓
Geometry
+
属性
+
业务对象
例如:
Point
[116.397, 39.908]
只是Geometry。
而:
商店A
位置:[116.397, 39.908]
类型:shop
状态:open
就是一个完整的Feature。
Feature在WebGIS中的位置
OpenLayers的核心数据结构可以理解为:
Map
↓
Layer
↓
Source
↓
Feature
↓
Geometry
↓
Coordinates
对于矢量数据:
Map
↓
VectorLayer
↓
VectorSource
↓
Feature
↓
Geometry
这条关系非常重要。
Feature完整生命周期
一个Feature通常经历:
创建
↓
设置Geometry
↓
设置Properties
↓
加入VectorSource
↓
显示在VectorLayer
↓
用户选择
↓
修改Geometry
↓
修改Properties
↓
保存到后端
↓
更新或删除
可以理解为:
数据
↓
Feature
↓
地图
↓
交互
↓
编辑
↓
保存
Feature常见操作
| 操作 | OpenLayers方法 |
|---|---|
| 获取Geometry | getGeometry() |
| 设置Geometry | setGeometry() |
| 获取属性 | get() |
| 设置属性 | set() |
| 获取全部属性 | getProperties() |
| 设置ID | setId() |
| 获取ID | getId() |
| 设置Style | setStyle() |
| 添加到Source | source.addFeature() |
| 删除Feature | source.removeFeature() |
Feature常见应用
Feature可以用于构建:
POI地图
设备地图
车辆监控
轨迹地图
电子围栏
行政区地图
管网地图
地籍地图
规划地图
物流地图
例如智慧工厂:
设备
↓
Feature
↓
Point / Polygon
↓
设备状态
↓
动态Style
↓
地图
Feature与业务状态
实际项目中可以将业务状态保存在Feature属性中。
例如:
const feature = new Feature({
geometry: new Point([116.397, 39.908]),
deviceId: 'device-001',
status: 'warning',
name: '设备A'
})
然后根据:
feature.get('status')
决定显示样式。
例如:
normal
↓
正常样式
warning
↓
警告样式
offline
↓
离线样式
这是一种非常常见的WebGIS开发方式。
Feature数据更新
例如后端实时返回设备位置:
feature.setGeometry(
new Point([116.410, 39.920])
)
更新状态:
feature.set('status', 'online')
更新名称:
feature.set('name', '设备B')
这样就可以实现地图对象实时更新。
Feature与实时地图
实时GIS系统通常采用:
后端WebSocket
↓
业务数据
↓
找到Feature
↓
setGeometry()
↓
set()
↓
地图自动更新
例如车辆监控:
车辆GPS
↓
WebSocket
↓
vehicleId
↓
对应Feature
↓
更新Geometry
↓
车辆在地图上移动
Feature的核心关系
可以用下面的结构理解OpenLayers Feature:
OpenLayers
│
├── Map
│
├── Layer
│ └── VectorLayer
│
├── Source
│ └── VectorSource
│
├── Feature
│ ├── Geometry
│ │ ├── Point
│ │ ├── LineString
│ │ └── Polygon
│ │
│ ├── Properties
│ ├── Style
│ └── ID
│
└── Interaction
├── Select
├── Draw
├── Modify
├── Translate
└── Snap
OpenLayers Feature完整流程
可以记住:
数据
↓
GeoJSON / WKT / 后端API
↓
OpenLayers Format
↓
Feature
↓
Geometry + Properties
↓
VectorSource
↓
VectorLayer
↓
Map
用户进行操作:
Map
↓
Select / Draw / Modify / Translate
↓
Feature
↓
Geometry变化
↓
业务数据变化
↓
保存后端
总结
OpenLayers中的Feature是表示地图矢量对象的核心对象。
一个Feature通常包含:
Geometry
Properties
Style
ID
其中:
Geometry负责描述空间位置和形状,Properties负责描述业务属性,Feature则将空间信息与业务信息组织成一个完整的地图对象。
OpenLayers中常见结构是:
Map
↓
VectorLayer
↓
VectorSource
↓
Feature
↓
Geometry
常见Geometry包括:
Point
LineString
Polygon
MultiPoint
MultiLineString
MultiPolygon
Feature还可以配合:
Select
Draw
Modify
Translate
Snap
实现地图选择、绘制、编辑、拖动和吸附。
因此可以记住:
VectorSource管理Feature,VectorLayer显示Feature,Feature管理Geometry和属性,而Interaction负责让用户与Feature进行交互。
相关工具
使用 IYATools 在线工具快速处理 GIS 数据