在叠加海量数据量,使用
WebGL
可以提升性能,因为
WebGL
是基于
GPU
来渲染的。这里主要介绍将
CSV
中的数据叠加到地图上来,首先使用的是用普通的
canvas
来叠加二维数据,然后再使用
WebGL
来叠加数据。
1.Canvas 2D渲染
在
Openlayers 6
中,地图的每个图层都是单独进行渲染的。之前所有图层都是在一个单独的渲染器上完成的。所以在
Openlayers 6
之前,只能选择
Canvas 2D
或者
WebGL
渲染所有图层,但在
Openlayers 6
可以为不同的图层选择不同的渲染策略,也就是说有些图层可用
Canvas 2D
渲染,有些图层可以用
WebGL
渲染。
ol/layer/Vector
可以用
Canvas 2D
来渲染点、线、面,这个图层具有丰富的渲染可能,可以渲染不同的样式。但是对于海量的数据来说,
WebGL
是最佳的选择。下面使用
Canvas 2D
来加载
*45,000 **个点。
加载CSV
这里主要使用
csv
文件来加载数据,文件中的数据格式为如下所示:
name,mass,year,reclat,reclong
Aachen,21,1880,50.775000,6.083330
修改main.js
后的代码如下所示:
import 'ol/ol.css';
import {fromLonLat} from 'ol/proj';
import {Map, View} from 'ol';
import {Vector as VectorLayer, Tile as TileLayer} from 'ol/layer';
import {Vector as VectorSource, Stamen} from 'ol/source';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
const source = new VectorSource();
const client = new XMLHttpRequest();
client.open('GET', 'data/meteorites.csv');
client.onload = function() {
const csv = client.responseText;
const features = [];
let prevIndex = csv.indexOf('\n') + 1; // scan past the header line
let curIndex;
while ((curIndex = csv.indexOf('\n', prevIndex)) != -1) {
const line = csv.substr(prevIndex, curIndex - prevIndex).split(',');
prevIndex = curIndex + 1;
const coords = fromLonLat([parseFloat(line[4]), parseFloat(line[3])]);
if (isNaN(coords[0]) || isNaN(coords[1])) {
// guard against bad data
continue;
features.push(new Feature({
mass: parseFloat(line[1]) || 0,
year: parseInt(line[2]) || 0,
geometry: new Point(coords)
source.addFeatures(features);
client.send();
new Map({
target: 'map-container',
layers: [
new TileLayer({
source: new Stamen({
layer: 'toner'
new VectorLayer({
source: source
view: new View({
center: [0, 0],
zoom: 2
全部叠加后的数据如下所示:
2.WebGL渲染
前面使用的是用Canvas 2D
来渲染的,这里主要介绍一下WebGL
怎么渲染要矢量图层。使用的是静态样式,如果使用动态样式来渲染,WebGL
是最好的选择。在Openlayers
中可以使用一起工具来使用WebGL
渲染数据。步骤如下所示:
2.1引入相关工具
这里渲染的是点坐标,需要引入PointsLayer
和一个数学函数工具。
import Renderer from 'ol/renderer/webgl/PointsLayer';
import {clamp} from 'ol/math';
2.2创建自定义图层
继承VectorLayer
创建一个子类,重写createRenderer
方法,并返回新的Renderer
对象,在构造函数中设置colorCallback
和sizeCallback
,分别用于设置颜色和尺寸。
const color = [1, 0, 0, 0.5];
class CustomLayer extends VectorLayer {
createRenderer() {
return new Renderer(this, {
colorCallback: function(feature, vertex, component) {
return color[component];
sizeCallback: function(feature) {
return 18 * clamp(feature.get('mass') / 200000, 0, 1) + 8;
创建好自定义图层后,然后再进行实例化,并指定source
,如下所示:
new CustomLayer({
source: source
渲染后的效果如下所示:
createRenderer() {
return new Renderer(this, {
colorCallback: function(feature, vertex, component) {
return color[component];
sizeCallback: function(feature) {
return 18 * clamp(feature.get('mass') / 200000, 0, 1) + 8;
//! [fragment]
fragmentShader: `
precision mediump float;
varying vec2 v_texCoord;
varying vec4 v_color;
void main(void) {
vec2 texCoord = v_texCoord * 2.0 - vec2(1.0, 1.0);
float sqRadius = texCoord.x * texCoord.x + texCoord.y * texCoord.y;
float value = 2.0 * (1.0 - sqRadius);
float alpha = smoothstep(0.0, 1.0, value);
gl_FragColor = v_color;
gl_FragColor.a *= alpha;
//! [fragment]
使用片段着色器处理后,将看到圆形了,如下所示: