OpenLayers 7.5.2 常用 API 使用文档
目录
- 快速入门
- 地图 (Map)
- 视图 (View)
- 图层 (Layer)
- 数据源 (Source)
- 几何图形 (Geometry)
- 样式 (Style)
- 要素 (Feature)
- 交互 (Interaction)
- 控件 (Control)
- 叠加层 (Overlay)
- 投影 (Projection)
- 完整示例
一、快速入门
1.1 基础地图创建
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>OpenLayers 快速入门</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.5.2/ol.css">
<style>
html, body { margin: 0; padding: 0; }
#map { width: 100%; height: 100vh; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://cdn.jsdelivr.net/npm/ol@v7.5.2/dist/ol.js"></script>
<script>
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([116.4, 39.9]), // 北京
zoom: 10
})
});
</script>
</body>
</html>
1.2 模块导入方式 (ES6)
// 核心类导入
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
import OSM from 'ol/source/OSM.js';
import { fromLonLat } from 'ol/proj.js';
// 创建地图
const map = new Map({
target: 'map',
layers: [new TileLayer({ source: new OSM() })],
view: new View({
center: fromLonLat([116.4, 39.9]),
zoom: 10
})
});
二、地图 (Map)
2.1 创建地图
import Map from 'ol/Map.js';
const map = new Map({
target: 'map', // 容器元素 ID
layers: [], // 图层数组
view: view, // 视图对象
controls: [], // 控件数组(可选)
interactions: [], // 交互数组(可选)
overlays: [], // 叠加层数组(可选)
pixelRatio: 1, // 像素比率(可选)
keyboardEventTarget: null, // 键盘事件目标(可选)
loadTilesWhileAnimating: false, // 动画时加载瓦片
loadTilesWhileInteracting: false // 交互时加载瓦片
});
2.2 常用方法
// 添加/移除图层
map.addLayer(layer);
map.removeLayer(layer);
map.getLayers(); // 获取图层集合
// 添加/移除控件
map.addControl(control);
map.removeControl(control);
// 添加/移除交互
map.addInteraction(interaction);
map.removeInteraction(interaction);
// 添加/移除叠加层
map.addOverlay(overlay);
map.removeOverlay(overlay);
// 坐标转换
map.getCoordinateFromPixel(pixel); // 像素 → 坐标
map.getPixelFromCoordinate(coordinate); // 坐标 → 像素
// 获取要素
map.getFeaturesAtPixel(pixel, options);
map.forEachFeatureAtPixel(pixel, callback, options);
// 获取/设置视图
map.getView();
map.setView(view);
// 获取地图尺寸
map.getSize(); // [width, height]
// 渲染
map.render();
map.renderSync();
map.updateSize(); // 更新地图尺寸
2.3 常用事件
// 点击事件
map.on('click', function(e) {
console.log('点击坐标:', e.coordinate);
console.log('像素位置:', e.pixel);
});
// 单击/双击
map.on('singleclick', function(e) {
console.log('单击事件');
});
map.on('dblclick', function(e) {
console.log('双击事件');
});
// 鼠标移动
map.on('pointermove', function(e) {
console.log('鼠标移动:', e.coordinate);
});
// 视图变化
map.on('movestart', function() {
console.log('移动开始');
});
map.on('moveend', function() {
console.log('移动结束');
});
// 渲染事件
map.on('precompose', function(e) {
console.log('渲染前');
});
map.on('postcompose', function(e) {
console.log('渲染后');
});
// 移除监听
map.un('click', callback);
三、视图 (View)
3.1 创建视图
import View from 'ol/View.js';
const view = new View({
center: fromLonLat([116.4, 39.9]), // 中心点坐标
zoom: 10, // 初始缩放级别
rotation: 0, // 旋转角度(弧度)
minZoom: 5, // 最小缩放
maxZoom: 18, // 最大缩放
minResolution: 1, // 最小分辨率
maxResolution: 4096, // 最大分辨率
projection: 'EPSG:3857', // 投影坐标系
extent: [], // 视图范围限制
constrainResolution: true, // 限制为整数缩放级别
constrainOnlyCenter: false, // 仅限制中心点
smoothExtentConstraint: true, // 平滑范围约束
showFullExtent: false // 显示完整范围
});
3.2 常用方法
const view = map.getView();
// 获取/设置中心点
view.getCenter();
view.setCenter([x, y]);
// 获取/设置缩放级别
view.getZoom();
view.setZoom(12);
view.getMinZoom();
view.getMaxZoom();
// 获取/设置分辨率
view.getResolution();
view.setResolution(100);
view.getResolutionForZoom(10); // 获取指定缩放的分辨率
// 获取/设置旋转
view.getRotation();
view.setRotation(Math.PI / 4); // 旋转 45 度
// 获取范围
view.calculateExtent(); // 当前视图范围
view.calculateExtent(map.getSize());
view.fit(extent, { duration: 1000 }); // 适配范围
view.fit(geometry, { duration: 1000 }); // 适配几何
// 获取比例尺
view.getResolutionForScale(scale);
// 动画
view.animate({
center: fromLonLat([116.4, 39.9]),
zoom: 15,
rotation: 0,
duration: 1000
});
// 链式动画
view.animate(
{ center: [x1, y1], duration: 1000 },
{ center: [x2, y2], duration: 1000 }
);
// 取消动画
view.cancelAnimations();
3.3 视图适配示例
// 适配到范围
const extent = [12900000, 4800000, 13000000, 4900000];
view.fit(extent, {
size: map.getSize(),
padding: [50, 50, 50, 50], // 内边距
duration: 1000,
callback: function() {
console.log('适配完成');
}
});
// 适配到几何
const feature = vectorSource.getFeatures()[0];
view.fit(feature.getGeometry(), {
padding: [100, 100, 100, 100],
duration: 1500
});
// 缩放到指定坐标
view.animate({
center: fromLonLat([116.4, 39.9]),
zoom: 15,
duration: 1000
});
四、图层 (Layer)
4.1 图层类型
瓦片图层 (TileLayer)
import TileLayer from 'ol/layer/Tile.js';
const tileLayer = new TileLayer({
source: new OSM(),
opacity: 1,
visible: true,
zIndex: 0,
minZoom: 0,
maxZoom: 28,
extent: null,
preload: 0,
useInterimTilesOnError: true
});
图像图层 (ImageLayer)
import ImageLayer from 'ol/layer/Image.js';
import ImageStatic from 'ol/source/ImageStatic.js';
const imageLayer = new ImageLayer({
source: new ImageStatic({
url: 'path/to/image.png',
imageExtent: [0, 0, 1000, 1000]
})
});
矢量图层 (VectorLayer)
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
const vectorLayer = new VectorLayer({
source: new VectorSource({
features: []
}),
style: style,
opacity: 1,
visible: true,
zIndex: 1,
minResolution: 0,
maxResolution: Infinity,
extent: null,
renderBuffer: 100,
declutter: false
});
矢量瓦片图层 (VectorTileLayer)
import VectorTileLayer from 'ol/layer/VectorTile.js';
import VectorTileSource from 'ol/source/VectorTile.js';
import MVT from 'ol/format/MVT.js';
const vectorTileLayer = new VectorTileLayer({
source: new VectorTileSource({
format: new MVT(),
url: 'https://example.com/tiles/{z}/{x}/{y}.pbf'
}),
style: style
});
WebGL 瓦片图层 (WebGLTileLayer)
import WebGLTileLayer from 'ol/layer/WebGLTile.js';
const webglLayer = new WebGLTileLayer({
source: new OSM(),
style: {
color: ['array', [1, 0.5, 0.5, 1]] // 红色滤镜
}
});
4.2 图层通用属性
const layer = new TileLayer({
// 基础属性
opacity: 1, // 透明度 (0-1)
visible: true, // 是否可见
zIndex: 0, // 层级顺序(数字小的在下层)
// 渲染控制
minZoom: 0, // 最小可见缩放级别
maxZoom: 28, // 最大可见缩放级别
minResolution: 0, // 最小可见分辨率
maxResolution: Infinity, // 最大可见分辨率
// 范围控制
extent: null, // 渲染范围限制 [minX, minY, maxX, maxY]
// 其他
className: '', // CSS 类名
background: null, // 背景颜色
properties: {} // 自定义属性
});
// 图层方法
layer.getOpacity();
layer.setOpacity(0.5);
layer.getVisible();
layer.setVisible(false);
layer.getZIndex();
layer.setZIndex(1);
layer.getExtent();
layer.setExtent(extent);
layer.getProperties();
layer.setProperties({ name: 'layer1' });
4.3 图层管理
// 获取所有图层
const layers = map.getLayers();
// 遍历图层
layers.forEach(function(layer) {
console.log(layer.get('name'));
});
// 添加/移除图层
map.addLayer(newLayer);
map.removeLayer(oldLayer);
// 插入图层
layers.insertAt(0, newLayer); // 在索引 0 处插入
// 移除所有图层
layers.clear();
// 根据条件查找
const targetLayer = layers.item(0); // 获取第一个图层
const layerByName = layers.getArray().find(l => l.get('name') === 'myLayer');
五、数据源 (Source)
5.1 瓦片数据源
OSM 源
import OSM from 'ol/source/OSM.js';
const osmSource = new OSM({
crossOrigin: 'anonymous',
attributions: '© OpenStreetMap contributors',
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
maxZoom: 19,
reprojectionErrorThreshold: 0.5,
tileLoadFunction: null,
wrapX: true
});
XYZ 源
import XYZ from 'ol/source/XYZ.js';
const xyzSource = new XYZ({
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
minZoom: 0,
maxZoom: 19,
tileSize: 256,
tileUrlFunction: null,
wrapX: true,
attributions: '© OSM'
});
// 使用天地图
const tiandituSource = new XYZ({
url: 'http://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=你的密钥',
tileLoadFunction: function(tile, src) {
tile.getImage().src = src;
}
});
TileWMS 源
import TileWMS from 'ol/source/TileWMS.js';
const wmsSource = new TileWMS({
url: 'https://geoserver.example.com/geoserver/wms',
params: {
'LAYERS': 'workspace:layer',
'TILED': true,
'VERSION': '1.3.0'
},
serverType: 'geoserver',
crossOrigin: 'anonymous',
tileGrid: null
});
5.2 图像数据源
ImageStatic 源
import ImageStatic from 'ol/source/ImageStatic.js';
const staticSource = new ImageStatic({
url: 'path/to/image.png',
imageExtent: [0, 0, 1000, 1000],
projection: 'EPSG:3857',
crossOrigin: 'anonymous'
});
ImageWMS 源
import ImageWMS from 'ol/source/ImageWMS.js';
const imageWMSSource = new ImageWMS({
url: 'https://geoserver.example.com/geoserver/wms',
params: {
'LAYERS': 'workspace:layer',
'VERSION': '1.3.0'
},
ratio: 1,
serverType: 'geoserver'
});
5.3 矢量数据源
import VectorSource from 'ol/source/Vector.js';
import Feature from 'ol/Feature.js';
import Point from 'ol/geom/Point.js';
const vectorSource = new VectorSource({
features: [],
url: 'data.geojson',
format: null,
loader: null,
strategy: null,
wrapX: true,
attributions: null
});
// 添加要素
const feature = new Feature(new Point([0, 0]));
vectorSource.addFeature(feature);
vectorSource.addFeatures([feature1, feature2]);
// 移除要素
vectorSource.removeFeature(feature);
vectorSource.clear();
// 获取要素
vectorSource.getFeatures();
vectorSource.getFeaturesAtCoordinate(coordinate);
vectorSource.getFeaturesInExtent(extent);
vectorSource.getFeatureById('id');
// 清空并添加
vectorSource.refresh();
5.4 矢量瓦片源
import VectorTileSource from 'ol/source/VectorTile.js';
import MVT from 'ol/format/MVT.js';
const vectorTileSource = new VectorTileSource({
format: new MVT(),
url: 'https://example.com/tiles/{z}/{x}/{y}.pbf',
minZoom: 0,
maxZoom: 14,
tileGrid: null,
attributions: null
});
5.5 数据源通用方法
// 获取/设置属性
source.getAttributions();
source.get('name');
source.set('name', 'mySource');
// 刷新
source.refresh();
source.clear();
// 获取状态
source.getState();
source.getLoadedTileCount();
source.getTileCount();
六、几何图形 (Geometry)
6.1 创建几何
import Point from 'ol/geom/Point.js';
import LineString from 'ol/geom/LineString.js';
import Polygon from 'ol/geom/Polygon.js';
import Circle from 'ol/geom/Circle.js';
import MultiPoint from 'ol/geom/MultiPoint.js';
import MultiLineString from 'ol/geom/MultiLineString.js';
import MultiPolygon from 'ol/geom/MultiPolygon.js';
import GeometryCollection from 'ol/geom/GeometryCollection.js';
// 点
const point = new Point([116.4, 39.9]);
// 线
const line = new LineString([
[116.3, 39.8],
[116.4, 39.9],
[116.5, 40.0]
]);
// 多边形(外环 + 内环)
const polygon = new Polygon([
// 外环(顺时针)
[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]],
// 内环(逆时针,可选)
[[2, 2], [2, 4], [4, 4], [4, 2], [2, 2]]
]);
// 圆(中心 + 半径)
const circle = new Circle([0, 0], 100);
// 多点
const multiPoint = new MultiPoint([
[0, 0], [10, 10], [20, 20]
]);
// 多线
const multiLine = new MultiLineString([
[[0, 0], [10, 10]],
[[20, 20], [30, 30]]
]);
// 多多边形
const multiPolygon = new MultiPolygon([
[[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]],
[[[20, 20], [30, 20], [30, 30], [20, 30], [20, 20]]]
]);
// 几何集合
const collection = new GeometryCollection([point, line, polygon]);
6.2 几何方法
// 获取/设置坐标
geometry.getCoordinates();
geometry.setCoordinates(newCoords);
// 获取范围
geometry.getExtent(); // [minX, minY, maxX, maxY]
// 获取类型
geometry.getType(); // 'Point', 'LineString', 'Polygon' 等
// 克隆
const cloned = geometry.clone();
// 平移
geometry.translate(100, 100);
// 旋转(角度为弧度)
geometry.rotate(Math.PI / 4, [0, 0]); // 绕原点旋转 45 度
// 缩放
geometry.scale(2, 2); // X 和 Y 方向放大 2 倍
geometry.scale(2, 2, [0, 0]); // 绕指定点缩放
// 变换投影
geometry.transform('EPSG:4326', 'EPSG:3857');
// 简化(Douglas-Peucker 算法)
const simplified = geometry.simplify(100); // 容差 100
// 获取最近点
const closest = geometry.getClosestPoint([x, y], undefined);
// 判断是否包含坐标
const contains = geometry.intersectsCoordinate([x, y]);
// 判断是否与范围相交
const intersects = geometry.intersectsExtent(extent);
// 获取长度(线)
const length = line.getLength();
// 获取面积(多边形)
const area = polygon.getArea();
// 获取周长(多边形)
const perimeter = polygon.getPerimeter();
6.3 多边形特殊方法
// 从范围创建多边形
const extentPolygon = Polygon.fromExtent([0, 0, 100, 100]);
// 从圆创建多边形
const circlePolygon = Polygon.fromCircle(circle, 32); // 32 个点
// 获取外环
const exterior = polygon.getExteriorRing();
// 获取内环
const interior = polygon.getInteriorRing(0); // 第一个内环
// 获取所有线性环
polygon.getLinearRing(0); // 第一个环(外环)
6.4 判断点与多边形关系
/**
* 判断点与多边形的位置关系
* @param {Polygon} polygon - 多边形几何
* @param {Array} point - 测试点坐标 [x, y]
* @param {number} edgeTolerance - 边判断容差
* @returns {Object} 位置关系
*/
function getPointPolygonRelation(polygon, point, edgeTolerance = 0.001) {
// 获取最近点
const closestPoint = polygon.getClosestPoint(point, undefined);
// 计算距离
const dx = point[0] - closestPoint[0];
const dy = point[1] - closestPoint[1];
const distance = Math.sqrt(dx * dx + dy * dy);
// 判断是否在边上
const onEdge = distance <= edgeTolerance;
// 判断是否在内部
const inside = polygon.intersectsCoordinate(point);
return {
inside: inside,
onEdge: onEdge,
closestPoint: closestPoint,
distance: distance
};
}
// 使用示例
const polygon = new Polygon([[
[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]
]]);
console.log(getPointPolygonRelation(polygon, [5, 5])); // {inside: true, onEdge: false}
console.log(getPointPolygonRelation(polygon, [5, 0])); // {inside: false, onEdge: true}
console.log(getPointPolygonRelation(polygon, [15, 15])); // {inside: false, onEdge: false}
七、样式 (Style)
7.1 基础样式
import Style from 'ol/style/Style.js';
import Fill from 'ol/style/Fill.js';
import Stroke from 'ol/style/Stroke.js';
import Circle from 'ol/style/Circle.js';
import Icon from 'ol/style/Icon.js';
import Text from 'ol/style/Text.js';
// 填充样式
const fill = new Fill({
color: 'rgba(255, 0, 0, 0.5)' // 支持 rgba, hex, rgb, 颜色名
});
// 描边样式
const stroke = new Stroke({
color: '#ff0000',
width: 2,
lineCap: 'round', // 'butt', 'round', 'square'
lineJoin: 'round', // 'bevel', 'round', 'miter'
lineDash: [10, 5], // 虚线 [实线长度,间隔长度]
lineDashOffset: 0, // 虚线偏移
miterLimit: 10 // 斜接限制
});
// 圆形样式(点)
const circleStyle = new Circle({
radius: 7,
fill: new Fill({ color: '#ff0000' }),
stroke: new Stroke({ color: '#fff', width: 2 })
});
// 图标样式
const iconStyle = new Icon({
src: 'path/to/icon.png',
scale: 1, // 缩放比例
rotation: 0, // 旋转角度(弧度)
rotateWithView: false, // 是否随视图旋转
opacity: 1, // 透明度
anchor: [0.5, 0.5], // 锚点(归一化坐标)
anchorXUnits: 'fraction', // 'fraction' 或 'pixels'
anchorYUnits: 'fraction',
size: [32, 32], // 图标尺寸
color: [255, 0, 0, 1] // 颜色滤镜 [r, g, b, a]
});
// 文本样式
const textStyle = new Text({
text: '标注内容',
font: '14px sans-serif', // CSS font 语法
fill: new Fill({ color: '#000' }),
stroke: new Stroke({ color: '#fff', width: 2 }),
offsetX: 0, // 水平偏移
offsetY: -10, // 垂直偏移
rotation: 0,
rotateWithView: false,
scale: 1,
placement: 'point', // 'point' 或 'line'
textAlign: 'center', // 'left', 'center', 'right'
textBaseline: 'middle', // 'top', 'middle', 'bottom'
padding: [2, 2, 2, 2] // 文本内边距
});
// 组合样式
const style = new Style({
fill: fill,
stroke: stroke,
image: circleStyle, // 或 iconStyle
text: textStyle,
zIndex: 0
});
7.2 样式函数
// 根据要素属性动态设置样式
const styleFunction = function(feature, resolution) {
const type = feature.get('type');
if (type === 'city') {
return new Style({
image: new Circle({
radius: 10,
fill: new Fill({ color: '#ff0000' })
}),
text: new Text({
text: feature.get('name'),
font: '12px sans-serif',
fill: new Fill({ color: '#000' }),
offsetY: -15
})
});
} else if (type === 'road') {
return new Style({
stroke: new Stroke({
color: '#666666',
width: 3
})
});
}
return null; // 使用默认样式
};
// 使用样式函数
const vectorLayer = new VectorLayer({
source: vectorSource,
style: styleFunction
});
7.3 样式应用
// 给图层设置样式
vectorLayer.setStyle(style);
// 给要素设置样式
feature.setStyle(style);
// 获取样式
layer.getStyle();
feature.getStyle();
// 样式数组(多个样式叠加)
const multiStyle = [
new Style({
stroke: new Stroke({ color: '#fff', width: 5 })
}),
new Style({
stroke: new Stroke({ color: '#f00', width: 3 })
})
];
八、要素 (Feature)
8.1 创建要素
import Feature from 'ol/Feature.js';
import Point from 'ol/geom/Point.js';
// 创建带几何的要素
const feature = new Feature({
geometry: new Point(fromLonLat([116.4, 39.9])),
name: '北京',
type: 'city',
population: 2154
});
// 仅创建几何
const pointFeature = new Feature(new Point([0, 0]));
// 设置/获取属性
feature.set('name', '上海');
feature.get('name');
// 获取所有属性
feature.getProperties();
// 设置多个属性
feature.setProperties({
name: '广州',
population: 1500
});
// 设置/获取 ID
feature.setId('feature_001');
feature.getId();
// 获取/设置几何
feature.getGeometry();
feature.setGeometry(new Point([100, 100]));
// 设置样式
feature.setStyle(style);
// 获取样式
feature.getStyle();
8.2 要素事件
// 监听属性变化
feature.on('propertychange', function(e) {
console.log('属性变化:', e.key, e.target.get(e.key));
});
// 监听几何变化
feature.getGeometry().on('change', function() {
console.log('几何变化');
});
// 移除监听
feature.un('propertychange', callback);
九、交互 (Interaction)
9.1 默认交互
import { defaults as defaultInteractions } from 'ol/interaction.js';
// 创建地图时使用默认交互
const map = new Map({
interactions: defaultInteractions({
doubleClickZoom: true, // 双击缩放
mouseWheelZoom: true, // 滚轮缩放
shiftDragZoom: true, // Shift+ 拖拽缩放
dragPan: true, // 拖拽平移
keyboardPan: true, // 键盘平移
keyboardZoom: true, // 键盘缩放
rotate: true, // 旋转
pinchZoom: true, // 捏合缩放(移动端)
pinchRotate: true // 捏合旋转(移动端)
})
});
9.2 绘制交互 (Draw)
import Draw from 'ol/interaction/Draw.js';
import VectorSource from 'ol/source/Vector.js';
const vectorSource = new VectorSource();
// 创建绘制交互
const draw = new Draw({
source: vectorSource,
type: 'Point', // 'Point', 'LineString', 'Polygon', 'Circle'
freehand: false, // 自由绘制模式
snapTolerance: 12, // 捕捉容差(像素)
style: style, // 绘制样式
minPoints: 2, // 最小点数
maxPoints: null, // 最大点数
stopClick: true // 阻止点击事件
});
map.addInteraction(draw);
// 绘制事件
draw.on('drawstart', function(e) {
console.log('开始绘制', e.feature);
});
draw.on('drawend', function(e) {
console.log('绘制完成', e.feature);
});
// 撤销最后一个点
draw.removeLastPoint();
// 获取草图要素
const sketch = draw.getSketchFeature();
// 激活/停用
draw.setActive(false);
// 移除交互
map.removeInteraction(draw);
9.3 选择交互 (Select)
import Select from 'ol/interaction/Select.js';
import { click, pointerMove, altKeyOnly } from 'ol/events/condition.js';
// 创建选择交互
const select = new Select({
condition: click, // 触发条件
layers: [vectorLayer], // 可选的图层
style: selectedStyle, // 选中样式
multi: false, // 是否多选
toggleCondition: altKeyOnly, // 切换选择条件
filter: function(feature, layer) {
return feature.get('selectable') !== false; // 过滤条件
}
});
map.addInteraction(select);
// 选择事件
select.on('select', function(e) {
console.log('选中的要素:', e.selected);
console.log('取消选择的要素:', e.deselected);
});
// 获取选中的要素集合
const selectedFeatures = select.getFeatures();
// 清空选择
selectedFeatures.clear();
9.4 修改交互 (Modify)
import Modify from 'ol/interaction/Modify.js';
// 创建修改交互
const modify = new Modify({
source: vectorSource, // 数据源
features: select.getFeatures(), // 或直接指定要素集合
style: modifyStyle, // 修改样式
pixelTolerance: 20, // 像素容差
wrapX: false, // 是否环绕 X 轴
insertVertexCondition: function() {
return true; // 是否允许插入顶点
}
});
map.addInteraction(modify);
// 修改事件
modify.on('modifystart', function(e) {
console.log('开始修改');
});
modify.on('modifyend', function(e) {
console.log('修改完成');
});
9.5 捕捉交互 (Snap)
import Snap from 'ol/interaction/Snap.js';
// 创建捕捉交互
const snap = new Snap({
source: vectorSource,
pixelTolerance: 10, // 捕捉容差(像素)
features: null // 可选的要素集合
});
map.addInteraction(snap);
9.6 平移交互 (Translate)
import Translate from 'ol/interaction/Translate.js';
// 创建平移交互
const translate = new Translate({
features: select.getFeatures(), // 要平移的要素集合
layers: [vectorLayer] // 可选的图层
});
map.addInteraction(translate);
// 平移事件
translate.on('translatestart', function(e) {
console.log('开始平移');
});
translate.on('translateend', function(e) {
console.log('平移完成', e.features);
});
9.7 拉框交互 (DragBox)
import DragBox from 'ol/interaction/DragBox.js';
import { always } from 'ol/events/condition.js';
// 创建拉框交互
const dragBox = new DragBox({
condition: always, // 触发条件
style: new Style({
stroke: new Stroke({
color: '#00f',
width: 2
})
})
});
map.addInteraction(dragBox);
// 拉框事件
dragBox.on('boxstart', function(e) {
console.log('开始拉框');
});
dragBox.on('boxend', function(e) {
const extent = dragBox.getGeometry().getExtent();
console.log('拉框范围:', extent);
});
9.8 拖放交互 (DragAndDrop)
import DragAndDrop from 'ol/interaction/DragAndDrop.js';
import GeoJSON from 'ol/format/GeoJSON.js';
// 创建拖放交互
const dragAndDrop = new DragAndDrop({
formatConstructors: [GeoJSON, KML], // 支持的格式
projection: 'EPSG:3857' // 投影
});
map.addInteraction(dragAndDrop);
// 拖放事件
dragAndDrop.on('addfeatures', function(e) {
const vectorSource = new VectorSource({
features: e.features,
featureProjection: e.projection
});
const vectorLayer = new VectorLayer({
source: vectorSource
});
map.addLayer(vectorLayer);
});
十、控件 (Control)
10.1 默认控件
import { defaults as defaultControls } from 'ol/control.js';
const map = new Map({
controls: defaultControls({
attribution: true, // 版权信息
rotate: true, // 旋转复位
zoom: true // 缩放按钮
})
});
10.2 缩放控件 (Zoom)
import Zoom from 'ol/control/Zoom.js';
const zoomControl = new Zoom({
duration: 250, // 动画时长 (ms)
className: 'ol-zoom', // CSS 类名
zoomInLabel: '+', // 放大按钮标签
zoomOutLabel: '-', // 缩小按钮标签
zoomInTipLabel: '放大', // 放大提示
zoomOutTipLabel: '缩小', // 缩小提示
target: null // 目标容器(可选)
});
map.addControl(zoomControl);
10.3 比例尺控件 (ScaleLine)
import ScaleLine from 'ol/control/ScaleLine.js';
const scaleLine = new ScaleLine({
className: 'ol-scale-line',
minWidth: 64, // 最小宽度(像素)
maxUnits: 'metric', // 'metric' 或 'degrees'
bar: false, // 是否显示条形比例尺
steps: 4, // 条形比例尺步数
text: true, // 是否显示文本
units: 'metric', // 单位类型
target: null
});
map.addControl(scaleLine);
10.4 鼠标位置控件 (MousePosition)
import MousePosition from 'ol/control/MousePosition.js';
import { createStringXY } from 'ol/coordinate.js';
const mousePosition = new MousePosition({
className: 'ol-mouse-position',
coordinateFormat: function(coordinate) {
return coordinate[0].toFixed(4) + ', ' + coordinate[1].toFixed(4);
},
projection: 'EPSG:4326', // 显示坐标系
undefinedHTML: ' ', // 未定义时显示的内容
target: null,
placeholder: ' ' // 鼠标移出时的占位符
});
map.addControl(mousePosition);
10.5 全屏控件 (FullScreen)
import FullScreen from 'ol/control/FullScreen.js';
const fullScreen = new FullScreen({
className: 'ol-full-screen',
tipLabel: '全屏',
label: '⛶', // 按钮标签
labelActive: '⛶', // 激活状态标签
target: null
});
map.addControl(fullScreen);
10.6 旋转控件 (Rotate)
import Rotate from 'ol/control/Rotate.js';
const rotateControl = new Rotate({
className: 'ol-rotate',
duration: 250, // 复位动画时长
label: '↻', // 按钮标签
tipLabel: '复位北向',
target: null
});
map.addControl(rotateControl);
10.7 鹰眼图控件 (OverviewMap)
import OverviewMap from 'ol/control/OverviewMap.js';
import TileLayer from 'ol/layer/Tile.js';
import OSM from 'ol/source/OSM.js';
const overviewMap = new OverviewMap({
className: 'ol-overviewmap',
collapsed: true, // 是否折叠
collapseLabel: '«', // 折叠按钮标签
label: '»', // 展开按钮标签
layers: [
new TileLayer({
source: new OSM()
})
],
view: null, // 鹰眼图视图(可选)
target: null
});
map.addControl(overviewMap);
10.8 缩放滑块控件 (ZoomSlider)
import ZoomSlider from 'ol/control/ZoomSlider.js';
const zoomSlider = new ZoomSlider({
className: 'ol-zoomslider',
duration: 200, // 动画时长
minResolution: 0,
maxResolution: 0,
target: null
});
map.addControl(zoomSlider);
10.9 区域定位控件 (ZoomToExtent)
import ZoomToExtent from 'ol/control/ZoomToExtent.js';
const zoomToExtent = new ZoomToExtent({
className: 'ol-zoom-extent',
extent: null, // 目标范围(默认视图范围)
label: 'E', // 按钮标签
tipLabel: '缩放到范围',
target: null
});
map.addControl(zoomToExtent);
10.10 自定义控件
import Control from 'ol/control/Control.js';
// 创建 HTML 元素
const button = document.createElement('button');
button.innerHTML = '定位';
button.className = 'my-button';
button.onclick = function() {
map.getView().setCenter(fromLonLat([116.4, 39.9]));
};
const element = document.createElement('div');
element.className = 'my-control';
element.appendChild(button);
// 创建控件
const myControl = new Control({
element: element,
target: null
});
map.addControl(myControl);
十一、叠加层 (Overlay)
11.1 创建叠加层
import Overlay from 'ol/Overlay.js';
// 创建 HTML 元素
const popupElement = document.createElement('div');
popupElement.className = 'popup';
popupElement.innerHTML = '<div class="popup-content">内容</div>';
// 创建叠加层
const popup = new Overlay({
element: popupElement,
position: fromLonLat([116.4, 39.9]),
positioning: 'center-center', // 'top-left', 'top-center', 'top-right',
// 'center-left', 'center-center', 'center-right',
// 'bottom-left', 'bottom-center', 'bottom-right'
offset: [0, -10], // 偏移量(像素)
autoPan: true, // 自动平移地图
autoPanAnimation: {
duration: 250
},
autoPanMargin: 20, // 自动平周边距
stopEvent: true, // 是否阻止事件传播
insertFirst: true, // 是否插入到最前
className: 'ol-overlay'
});
map.addOverlay(popup);
11.2 叠加层方法
// 设置/获取位置
popup.setPosition(fromLonLat([116.4, 39.9]));
popup.getPosition();
// 设置/获取元素
popup.setElement(newElement);
popup.getElement();
// 设置/获取偏移
popup.setOffset([0, -20]);
popup.getOffset();
// 设置/获取定位
popup.setPositioning('bottom-center');
popup.getPositioning();
// 显示/隐藏
popup.setPosition(undefined); // 隐藏
// 获取地图
popup.getMap();
// 移除
map.removeOverlay(popup);
11.3 弹窗示例
// 点击显示弹窗
map.on('click', function(e) {
const features = map.getFeaturesAtPixel(e.pixel);
if (features && features.length > 0) {
const feature = features[0];
const content = feature.get('name') || '未知';
popupElement.innerHTML = `<h3>${content}</h3>`;
popup.setPosition(e.coordinate);
} else {
popup.setPosition(undefined);
}
});
// 鼠标悬停显示
map.on('pointermove', function(e) {
const features = map.getFeaturesAtPixel(e.pixel);
if (features && features.length > 0) {
map.getTargetElement().style.cursor = 'pointer';
} else {
map.getTargetElement().style.cursor = 'auto';
}
});
十二、投影 (Projection)
12.1 坐标转换
import { fromLonLat, toLonLat, transform } from 'ol/proj.js';
// 经纬度转 Web Mercator (EPSG:3857)
const webCoord = fromLonLat([116.4, 39.9]); // [12955662.92, 4866611.98]
// Web Mercator 转经纬度
const lonLat = toLonLat(webCoord); // [116.4, 39.9]
// 任意投影转换
const coord = transform(
[116.4, 39.9],
'EPSG:4326',
'EPSG:3857'
);
// 范围转换
import { transformExtent } from 'ol/proj.js';
const extent4326 = [116, 39, 117, 40];
const extent3857 = transformExtent(extent4326, 'EPSG:4326', 'EPSG:3857');
12.2 获取投影信息
import { get, getPointResolution } from 'ol/proj.js';
// 获取投影对象
const projection = get('EPSG:3857');
// 获取投影代码
projection.getCode(); // 'EPSG:3857'
// 获取单位
projection.getUnits(); // 'm'
// 获取范围
projection.getExtent();
// 获取世界范围
projection.getWorldExtent();
// 判断是否为球面
projection.isGlobal();
// 判断是否轴向翻转
projection.getAxisOrientation();
// 获取点分辨率
const resolution = getPointResolution(
projection,
100, // 分辨率
fromLonLat([116.4, 39.9]) // 位置
);
12.3 定义自定义投影
import { register } from 'ol/proj/proj4.js';
import proj4 from 'proj4';
// 定义投影
proj4.defs('EPSG:27700', '+proj=tmerc +lat_0=49 +lon_0=-2 ...');
// 注册
register(proj4);
// 使用
const view = new View({
projection: 'EPSG:27700',
center: [500000, 200000],
zoom: 10
});
十三、完整示例
13.1 基础地图 + 矢量图层 + 交互
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>OpenLayers 完整示例</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.5.2/ol.css">
<style>
html, body { margin: 0; padding: 0; }
#map { width: 100%; height: 100vh; }
.popup {
position: absolute;
background: #fff;
border: 1px solid #ccc;
padding: 10px;
border-radius: 4px;
display: none;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="popup" class="popup"></div>
<script src="https://cdn.jsdelivr.net/npm/ol@v7.5.2/dist/ol.js"></script>
<script>
// 创建矢量源
const vectorSource = new ol.source.Vector();
// 创建样式
const style = new ol.style.Style({
fill: new ol.style.Fill({ color: 'rgba(255, 0, 0, 0.5)' }),
stroke: new ol.style.Stroke({ color: '#ff0000', width: 2 }),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({ color: '#ff0000' })
})
});
// 创建矢量图层
const vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: style
});
// 创建地图
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({ source: new ol.source.OSM() }),
vectorLayer
],
view: new ol.View({
center: ol.proj.fromLonLat([116.4, 39.9]),
zoom: 12
}),
controls: ol.control.defaults().extend([
new ol.control.ScaleLine(),
new ol.control.FullScreen()
])
});
// 添加绘制交互
const draw = new ol.interaction.Draw({
source: vectorSource,
type: 'Polygon'
});
map.addInteraction(draw);
// 添加选择交互
const select = new ol.interaction.Select();
map.addInteraction(select);
// 添加修改交互
const modify = new ol.interaction.Modify({
features: select.getFeatures()
});
map.addInteraction(modify);
// 添加捕捉交互
const snap = new ol.interaction.Snap({
source: vectorSource
});
map.addInteraction(snap);
// 弹窗
const popup = new ol.Overlay({
element: document.getElementById('popup'),
autoPan: true,
autoPanAnimation: { duration: 250 }
});
map.addOverlay(popup);
// 点击显示信息
map.on('click', function(e) {
const features = map.getFeaturesAtPixel(e.pixel);
if (features && features.length > 0) {
const feature = features[0];
const name = feature.get('name') || '未命名';
document.getElementById('popup').innerHTML =
'<h3>' + name + '</h3><p>类型:' + feature.getGeometry().getType() + '</p>';
popup.setPosition(e.coordinate);
} else {
popup.setPosition(undefined);
}
});
// 绘制完成事件
draw.on('drawend', function(e) {
const feature = e.feature;
feature.set('name', '要素_' + (vectorSource.getFeatures().length));
console.log('绘制完成:', feature);
});
</script>
</body>
</html>
13.2 加载 GeoJSON 数据
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';
import GeoJSON from 'ol/format/GeoJSON.js';
const vectorSource = new VectorSource({
url: 'data.geojson',
format: new GeoJSON()
});
const vectorLayer = new VectorLayer({
source: vectorSource,
style: new Style({
stroke: new Stroke({ color: '#0066cc', width: 2 }),
fill: new Fill({ color: 'rgba(0, 102, 204, 0.3)' })
})
});
map.addLayer(vectorLayer);
// 加载完成后适配视图
vectorSource.once('featuresloadend', function() {
const extent = vectorSource.getExtent();
map.getView().fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
});
13.3 加载 WMS 服务
import TileLayer from 'ol/layer/Tile.js';
import TileWMS from 'ol/source/TileWMS.js';
const wmsLayer = new TileLayer({
source: new TileWMS({
url: 'https://geoserver.example.com/geoserver/wms',
params: {
'LAYERS': 'workspace:layer',
'TILED': true,
'VERSION': '1.3.0'
},
serverType: 'geoserver',
crossOrigin: 'anonymous'
})
});
map.addLayer(wmsLayer);
附录:常用链接
- 官方 API 文档: openlayers.org/en/v7.5.2/a…
- 官方示例: openlayers.org/en/latest/e…
- GitHub 仓库: github.com/openlayers/…
- 下载 CDN: cdn.jsdelivr.net/npm/ol@v7.5…
本文档基于 OpenLayers 7.5.2 版本编写,部分 API 可能在其他版本中有所不同。