Openlayers:海量图形渲染之WebGL渲染

最近由于在工作中涉及到了海量图形渲染的问题,因此我开始研究相关的解决方案。我在网络上寻找相关的解决方案时发现许多的文章都提到利用Openlayers中的WebGLPointsLayer类,可以实现渲染海量的点,之后我又了解到利用WebGLVectorLayer类可以渲染其它的图形。经过测试我发现利用WebGL图层真的可以简单方案实现对海量图形的渲染,但是其对ol版本有很高的要求。

一、WebGL渲染的现状

1.版本要求高

在使用的过程中我发现,WebGLPointsLayerWebGLVectorLayer属于是最新的实验性的API,它们对ol版本的要求很高(我一开始使用的10.1.0的ol当中居然都没有WebGLVectorLayer类,我升级到最新的10.5.0版本后才可以使用)。

WebGLVectorLayer需要至少10.3.0的版本才能使用。

2.缺乏参考资料

目前我再官方的API文档中搜索WebGLPointsLayerWebGLVectorLayer均无相关的API介绍。

想要了解它们的使用方式我推荐参考以下的几个官方示例:

  1. Icon Sprites with WebGL
  2. WebGL Vector Layer
  3. WebGL points layer

3.谨慎使用WebGL矢量图层

总的来说WebGL矢量图层是一种十分方便快捷的解决海量图形渲染问题的方案,我个人感觉这种WebGL渲染也应该是Openlayers未来的一个更新方向。

但是目前这些接口并不稳定未来可能会发生变化,并且目前恐怕也很少有项目会去使用最新版本的ol,因此不推荐在生产项目中使用这种方案来解决海量图形渲染问题。

二、使用WebGLPointsLayer渲染点

在下面的示例中我随机生成了10w个点并通过WebGLPointsLayer渲染到了地图中。

JavaScript 复制代码
/**
 *@abstract 生成当前地图范围内的随机点数据
 * @param {*} map
 * @param {number} count 点数量
 * @returns
 */
export const randomPointFeature = (map, count) => {
  const point = turf.randomPoint(count, {
    bbox: map.getView().calculateExtent(map.getSize()),
  });

  const features = new GeoJSON().readFeatures(point);

  return features;
};
JavaScript 复制代码
import { Vector as VectorSource } from "ol/source";
import WebGLPointsLayer from "ol/layer/WebGLPoints";

function addRiver_webgl_point() {
  //生成10w+点
  const features = randomPointFeature(window.map, 100000);


  const pointSource = new VectorSource({
    features,
  });


  let style = {
    "circle-radius": 3,
    "circle-fill-color": "red",
  };

  const pointLayer = new WebGLPointsLayer({
    source: pointSource,
    style,
  });

  window.map.addLayer(pointLayer);

  Message.success("10w+点添加成功!");
}

三、使用WebGLVectorLayer渲染图形

WebGLPointsLayer图层只能添加点要素,如果要添加线或面要素则需要使用WebGLVectorLayer图层,下面的示例中我展示了使用WebGLVectorLayer图层向地图中渲染了一个由20w+的多边形组成的河流三角网。

JavaScript 复制代码
import WebGLVectorLayer from "ol/layer/WebGLVector.js";
import { Vector as VectorSource } from "ol/source";
import GeoJSON from "ol/format/GeoJSON.js";

// 河流三角网数据
import riverGrid from "@/assets/geojson/LDJ.json";

function addRiver_webgl() {
  // 读取GeoJSON数据
  const riverMeshFeatures = new GeoJSON().readFeatures(riverGrid, {
    dataProjection: "EPSG:4547",
    featureProjection: "EPSG:4326",
  });

  const riverSource = new VectorSource({
    features: riverMeshFeatures,
  });

  const style = {
    "stroke-color": ["*", ["get", "COLOR"], [220, 0, 0]],
    "stroke-width": 4.5,
    "fill-color": ["*", ["get", "COLOR"], [255, 255, 255, 0.3]],
  };

  const riverLayer = new WebGLVectorLayer({
    source: riverSource,
    style,
  });

  window.map.addLayer(riverLayer);

  Message.success("河流三角网添加成功!");
}

四、flat样式

使用WebGL渲染矢量图形的流程非常简单,基本上就是创建一个矢量数据源,然后在将其添加到WebGL矢量图层中。

我个人感觉其中唯一的难点就是"给图层设置样式",WebGL图层不能使用Style类来设置样式(如果用了会报错),需要使用 flat样式。

JavaScript 复制代码
// ❌ 错误的样式设置方式
const style = new Style({
  image: new CircleStyle({
    radius: 5,
    fill: new Fill({
      color: "rgba(255, 0, 0, 0.5)",
    }),
    stroke: new Stroke({
      color: "#333",
      width: 1,
    }),
  }),
});

// ✅ 正确的样式设置方式
let style = {
  "circle-radius": 3,
  "circle-fill-color": "red",
};

我也是第一次接触到 flat样式 (感觉有种既视感,似乎在哪里见过类似的东西 mapbox?),之后有时间我会好好研究一下。

参考资料

  1. 259:vue+openlayers: 显示海量多边形数据,10ms加载完成_webglvectorlayerrenderer-CSDN博客
  2. OpenLayers教程11_在OpenLayers中启用WebGL渲染_openlayers webgl-CSDN博客
  3. Icon Sprites with WebGL
  4. WebGL Vector Layer
  5. WebGL points layer
相关推荐
gaolei_eit1 小时前
Vue3项目ES6转ES5,兼容低版本的硬件设备,React也
javascript·react.js·es6
一位搞嵌入式的 genius1 小时前
从 ES6 到 ESNext:JavaScript 现代语法全解析(含编译工具与实战)
前端·javascript·ecmascript·es6
linweidong3 小时前
C++ 模块化编程(Modules)在大规模系统中的实践难点?
linux·前端·c++
leobertlan7 小时前
2025年终总结
前端·后端·程序员
子兮曰7 小时前
OpenClaw架构揭秘:178k stars的个人AI助手如何用Gateway模式统一控制12+通讯频道
前端·javascript·github
百锦再8 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
莲华君8 小时前
React快速上手:从零到项目实战
前端·reactjs教程
百锦再8 小时前
React编程高级主题:测试代码
android·前端·javascript·react.js·前端框架·reactjs
易安说AI8 小时前
Ralph Loop 让Claude无止尽干活的牛马...
前端·后端
颜酱9 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法