OpenLayers 3.1.0 发布详解:WebGL 点渲染、UTFGrid 交互与样式体系全面升级
2026/9/24 4:54:39 网站建设 项目流程
  • 前端
  • GIS
  • 数据可视化

【免费下载链接】openlayers

OpenLayers

项目地址:https://gitcode.com/gh_mirrors/op/openlayers
点击查看免费下载

导读

本文基于 OpenLayers 官方发布说明 changelog/v3.1.0.md,系统梳理 3.1.0 版本在 WebGL 渲染、UTFGrid 交互、样式系统与工程化构建四个方向的核心变化,并逐一解读官方升级注意事项。全文结合当前仓库源码(src/ol/examples/)给出可对照的实现证据与示例,帮助从 3.0.x 升级的开发者快速掌握新 API 的用法、底层原理与迁移要点。

版本概览:214 个合并 PR 带来的能力跃升

3.1.0 是 OpenLayers 3 系列的首个次版本,自 3.0.0 起共合并 214 个 Pull Request,是当时规模最大的一次功能迭代。官方发布说明 changelog/v3.1.0.md 将本版本的核心看点归纳为以下几点:

  • WebGL 渲染器开始支持点要素(point)渲染:矢量点图层从此可以借助 GPU 管线获得更高性能的绘制路径,对应源码实现见 src/ol/renderer/webgl/PointsLayer.js。
  • UTFGrid 交互支持:可以通过 UTFGrid 编码的瓦片数据实现要素的拾取与交互(如鼠标悬停显示国家/地区信息),对应实现见 src/ol/source/UTFGrid.js 与完整示例 examples/utfgrid.js。
  • 样式可指定替代几何(alternate geometries)进行渲染:一个要素的样式可以不使用要素自身的几何,而改用其他几何或几何函数,对应实现见 src/ol/style/Style.js。
  • 支持模块加载器加载库构建:编译产物支持 UMD 格式,可被 Browserify、RequireJS 等模块加载器直接引用。
  • 点要素符号化能力扩展:星形、方形、十九边形(enneadecagon)乃至任意正多边形/类正多边形均可作为点符号,核心实现为ol.style.RegularShape,见 src/ol/style/RegularShape.js。

升级指南:四个必须关注的 API 变化

3.1.0 与 3.0.0 保持 API 向后兼容,常规升级"无痛",但官方在升级说明中特别列出了以下四个需要留意的行为变化:

1.ol.source.ImageStatic不再强制要求imageSize

如果你使用静态图片图层源ol.source.ImageStatic,且不需要对图片做特殊缩放,则不再需要提供imageSize选项。图片的实际尺寸会在加载完成后自动确定,并据此计算分辨率,避免手动声明尺寸与实际像素不符带来的变形问题。

从当前源码看,这一设计被完整保留并进一步演化:src/ol/source/static.js 中的createLoader在图片加载完成后,用extent的宽高除以图片真实像素宽高来推导分辨率:

const resolutionX = getWidth(extent) / image.width; const resolutionY = getHeight(extent) / image.height; const resolution = resolutionX !== resolutionY ? [resolutionX, resolutionY] : resolutionY; return {image, extent, resolution, pixelRatio: 1};

也就是说,现代版本的ol.source.ImageStatic(见 src/ol/source/ImageStatic.js)只需提供urlimageExtent(图片在地图坐标系中的[left, bottom, right, top]范围)即可正确渲染;当 x、y 两个方向分辨率不同时,还会返回非均匀分辨率(数组形式)以精确对应图片像素。

2. 事件解绑改为ol.Observable.unByKey(key)

此前需要在对象实例上调用obj.unByKey(key)解除事件监听,3.1.0 起推荐(也支持)直接调用静态方法ol.Observable.unByKey(key)keyon()/once()返回,用于唯一标识一个监听器。

当前源码中该方法位于 src/ol/Observable.js 第 185 行附近,作为模块级导出函数存在,并且支持传入单个 key 或 key 数组(数组场景对应on()以事件类型数组注册的情况):

export function unByKey(key) { if (Array.isArray(key)) { for (let i = 0, ii = key.length; i < ii; ++i) { unlistenByKey(key[i]); } } else { unlistenByKey(/** @type {import("./events.js").EventsKey} */ (key)); } }

典型用法:

const key = map.on('moveend', onMoveEnd); // ... 之后解除监听 ol.Observable.unByKey(key); // 或等效地:map.unByKey(key)

3.format.writeFeatures(features)对全部要素格式统一返回字符串

在 3.1.0 之前,部分要素格式的writeFeatures(features)返回的是文档节点(DOM 节点)而非字符串,官方认为这属于缺陷并予以修正。3.1.0 起,所有要素格式的writeFeatures(features)方法一律返回字符串,如需 DOM 节点应使用对应的 Node 版本方法。

当前源码中,文本型格式的基类 src/ol/format/TextFeature.js 已明确将返回值类型标注为string

/** * Encode an array of features as string. * @param {Array<import("../Feature.js").default>} features Features. * @param {import("./Feature.js").WriteOptions} [options] Write options. * @return {string} Encoded features. * @api */ writeFeatures(features, options) { return this.writeFeaturesText(features, this.adaptOptions(options)); }

因此升级后若你的代码依赖旧行为(如直接对返回值调用 DOM API),需要改用writeFeaturesNode()之类的方法,或先把返回的字符串交给解析器处理。

4.dispatchChangeEvent()更名为changed()

对象主动派发变更事件的方法由obj.dispatchChangeEvent()改拼为obj.changed()。官方提示该方法仍属不稳定 API,但其语义与实现延续至今:changed()会递增对象的修订号(revision)并派发change事件,见 src/ol/Observable.js 第 72 行附近:

/** * Increases the revision counter and dispatches a 'change' event. * @api */ changed() { ++this.revision_; this.dispatchEvent(EventType.CHANGE); }

一个典型的应用场景是修改样式(如RegularShape的填充色)后主动调用图层的changed()触发重绘,示例见 examples/regularshape.js 中的颜色切换逻辑:

document.getElementById('color-changer').addEventListener('click', function () { styles.square .getImage() .setFill(new Fill({color: colors[currentColor % colors.length]})); vectorLayer.changed(); currentColor++; });

新特性深挖:四个方向的核心能力

WebGL 渲染器支持点要素渲染

3.1.0 之前 WebGL 渲染器主要面向图层级绘制,本版本通过 src/ol/renderer/webgl/PointsLayer.js 等实现引入了点要素的 GPU 渲染路径,为海量点数据的流畅绘制奠定了基础。在 3.1.0 时代,这通常配合ol.layer.Vector的 WebGL 渲染模式使用;如今仓库中的 WebGL 相关实现已进一步扩展(见 src/ol/renderer/webgl/VectorLayer.js),但在现代示例中仍有大量 WebGL 点图层用法(如 examples/webgl-points-layer.js),其数据路径可追溯到本版本的这一初始支持。

UTFGrid:轻量级瓦片交互数据

UTFGrid 是一种将交互数据编码进瓦片网格的机制:每个瓦片附带一份字符网格(grid)、一份键表(keys)与可选的属性数据(data),通过字符编码压缩体积,配合底图实现"点击/悬停即可查询要素属性"的交互体验,无需请求矢量要素服务。

当前实现 src/ol/source/UTFGrid.js 中的数据类型定义如下:

/** * @typedef {Object} UTFGridJSON * @property {Array<string>} grid The grid. * @property {Array<string>} keys The keys. * @property {Object<string, Object>} [data] Optional data. */

构造选项Options)包括:

选项默认值说明
preemptivetrue是否按瓦片可见性提前加载。为true时响应更快但流量更大;若设为false(懒加载),必须给forDataAtCoordinateAndResolutiontrue作为request参数,否则永远不会有数据被加载
jsonpfalse是否通过 JSONP 回调加载 TileJSON,适用于服务端不支持 CORS 的场景
tileJSON直接提供 TileJSON 配置对象;与url二选一
url提供 TileJSON 配置的端点;与tileJSON二选一
wrapXtrue是否在水平方向环绕世界
zDirection0当分辨率落在整数层级之间时,选择更高或更低 zoom 层级瓦片的策略

源码中两者都不提供时直接抛错(src/ol/source/UTFGrid.js第 335 行附近):

throw new Error('Either `url` or `tileJSON` options must be provided');

核心查询 APIforDataAtCoordinateAndResolution(coordinate, resolution, callback, request),其内部流程是:用当前分辨率确定 zoom 层级 → 取对应瓦片坐标 → 必要时触发瓦片加载 → 调用tile.forDataAtCoordinate(coordinate, callback, request)同步或异步回调坐标处的数据。字符解码采用 UTFGrid 标准编码(code >= 93code >= 35两档偏移修正后减 32)。

完整可运行示例见 examples/utfgrid.js:底图与交互网格使用同一个 Mapbox 地理分类数据源,pointermove时调用forDataAtCoordinateAndResolution查询所在国家,命中后展示国旗与国名:

const gridSource = new UTFGrid({ url: 'https://api.tiles.mapbox.com/v4/mapbox.geography-class.json?secure&access_token=' + key, }); // ... const displayCountryInfo = function (coordinate) { const viewResolution = /** @type {number} */ (view.getResolution()); gridSource.forDataAtCoordinateAndResolution(coordinate, viewResolution, function (data) { mapElement.style.cursor = data ? 'pointer' : ''; if (data) { flagElement.src = 'data:image/png;base64,' + data['flag_png']; nameElement.innerHTML = data['admin']; } infoOverlay.setPosition(data ? coordinate : undefined); }); }; map.on('pointermove', function (evt) { if (evt.dragging) return; displayCountryInfo(map.getEventCoordinate(evt.originalEvent)); });

示例中还通过gridSource.getTemplate()(对应源码第 375 行附近的getTemplate()方法)说明了如何结合 Mustache 模板渲染 TileJSON 中的template字段。

样式系统:替代几何与 RegularShape 符号化

样式覆盖要素几何(alternate geometry)

3.1.0 允许样式在渲染时使用替代几何——既可以是另一个Geometry对象,也可以是要素上的某个属性名,或一个接收 feature 并返回几何的函数。当前 src/ol/style/Style.js 中的setGeometry()(第 404 行附近)完整实现了这三种形态:

setGeometry(geometry) { if (typeof geometry === 'function') { this.geometryFunction_ = geometry; } else if (typeof geometry === 'string') { this.geometryFunction_ = function (feature) { // 从 feature.get(geometry) 取几何 }; } else if (!geometry) { this.geometryFunction_ = defaultGeometryFunction; } else if (geometry !== undefined) { this.geometryFunction_ = function () { return geometry; // 固定的几何对象 }; } this.geometry_ = geometry; }

由此衍生出很多实用技巧:例如用ol.geom.Polygon.fromExtent(extent)(见 src/ol/geom/Polygon.js 第 452 行附近)把范围快速构造成多边形,再配合样式几何函数实现"框选高亮"等效果。

RegularShape:星形、方形与任意正多边形

ol.style.RegularShape是本版本点符号化的核心。其选项(Options,见 src/ol/style/RegularShape.js)如下:

选项类型说明
pointsnumber多边形边数;对星形来说为"角数"(星形实际顶点数为points * 2
radiusnumber多边形/星形外接半径
radius2number第二个半径。只有同时提供radiusradius2时才会生成星形,否则生成正多边形
anglenumber起始角(弧度),默认0时形状的一个顶点朝上
rotationnumber整体旋转(弧度,顺时针为正),默认0
rotateWithViewboolean是否随视图旋转,默认false
scalenumber \| Size缩放,默认1;若只需一维缩放,优先调整radius/radius2
displacementArray<number>像素位移[x, y],正值向右、向上,默认[0, 0]
fillFill填充样式
strokeStroke描边样式

在生成路径的createPath_()(第 617 行附近)中可以看到星形的绘制原理——当radius2存在时顶点数翻倍,并按奇偶交替使用外半径与内半径:

const radius2 = this.radius2_ === undefined ? radius : this.radius2_; if (this.radius2_ !== undefined) { points *= 2; } const startAngle = this.angle_ - Math.PI / 2; const step = (2 * Math.PI) / points; for (let i = 0; i < points; i++) { const angle0 = startAngle + i * step; const radiusC = i % 2 === 0 ? radius : radius2; context.lineTo(radiusC * Math.cos(angle0), radiusC * Math.sin(angle0)); }

配套示例 examples/regularshape.js 给出了非常直观的用法合集:points: 4angle: Math.PI / 4得到旋转 45° 的方形;radiusradius2同时提供得到五角星(points: 5, radius: 10, radius2: 4);radius2: 0配合points: 4得到十字形;用scale: [1, 0.5]可将正方形压成矩形;多个RegularShape放在一个Style[]中配合displacement可实现"堆叠"符号。示例中points: Infinity的特殊写法(源码第 620 行if (points === Infinity) context.arc(...))还可以直接绘制圆形。

此外,3.1.0 为RegularShape补充了getPoints()getRadius()getRadius2()getAngle()等公开 getter(见 src/ol/style/RegularShape.js 第 312、321、343 行附近),并支持setRadius2()等 setter——修改后内部会自动调用render()重绘形状画布。

工程化:UMD 构建与模块加载器兼容

3.1.0 引入对 UMD(Universal Module Definition)构建产物的支持,编译后的库既可作为全局脚本直接引入,也可被 Browserify、RequireJS 等 CommonJS/AMD 模块加载器require。这一能力与闭包编译器构建任务(如config/jsdoc之外的构建脚本)配合,为后续 npm 发布与模块化使用铺平了道路。

其他值得关注的改进

除上述核心能力外,214 个 PR 中还包含一批对日常开发影响较大的改动:

  • ol.layer.Vector新增renderBuffer选项:为矢量图层渲染预留缓冲区,缓解要素在视图边缘被裁剪的问题。
  • ol.geom.Polygon.fromExtent(extent):从范围直接构造多边形(src/ol/geom/Polygon.js 第 452 行附近),空范围会抛出Cannot create polygon from empty extent
  • OverviewMap 控件:新增鹰眼图控件。
  • GetFeatureInfo 格式:新增ol.format.GetFeatureInfo,便于与 WMS GetFeatureInfo 响应对接。
  • 交互可激活/停用active成为ol.Object属性,交互支持程序化激活与停用;Select交互支持自定义mousemove条件函数;Draw支持程序化结束绘制。
  • 事件与 API 清理updatefeature事件更名为changefeatureol.Feature#setStyle接受null;属性变更事件携带旧值;移除beforepropertychange事件。
  • 数据源细节:TileJSON 源新增wrapX;BingMaps 新增maxZoom;XYZ 源支持自定义tileSize;WMTS 的requestEncoding允许直接传字符串;矢量源clear()性能优化、addFeatures使用批量插入。
  • GML 格式:增加版本化解析(GML2/GML3 分离)、科学计数法坐标支持,以及"仅 boundedBy"要素的容错解析。
  • DOM 渲染器矢量渲染:矢量要素可在 DOM 渲染器下绘制,为不支持 Canvas 的旧环境提供兜底路径。

迁移建议与兼容性小结

  • 3.1.0 相对 3.0.0保持 API 向后兼容,常规升级无需改动代码;仅四个点需要留意:ImageStaticimageSize变为可选、推荐使用ol.Observable.unByKeywriteFeatures统一返回字符串、dispatchChangeEvent更名为changed
  • 升级后建议优先验证三类场景:静态图片图层(分辨率计算方式变化)、要素格式导出(返回值类型变化)、样式动态更新(依赖changed()触发重绘)。
  • 本文所涉特性的现代实现均可直接在当前仓库中查看:UTFGrid 见 src/ol/source/UTFGrid.js、RegularShape 见 src/ol/style/RegularShape.js、样式几何覆盖见 src/ol/style/Style.js、静态图片源见 src/ol/source/ImageStatic.js,配套示例见 examples/utfgrid.js 与 examples/regularshape.js。
  • 完整变更条目清单可翻阅仓库 changelog 目录下的历史发布说明(如 changelog/v3.0.0.md、changelog/v3.1.0.md)以及 changelog/upgrade-notes.md 中的跨版本升级要点。
  • 前端
  • GIS
  • 数据可视化

【免费下载链接】openlayers

OpenLayers

项目地址:https://gitcode.com/gh_mirrors/op/openlayers
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询