Rendering points with WebGL 用WebGL渲染点
在之前的步骤中,我们使用一个普通的vector layer渲染点特征.这个图层使用的是2D的画布上下文来渲染的.用这个图层,你可以渲染数以万计的点,只不过你要注意编写高效的样式代码.为了渲染一个很大数量的点,或者为了更加高效地动态的定义样式,WebGL是一个较好的解决方案.OpenLayers已经具备了一套用WebGL渲染的工具.用WebGL目前局限于渲染点,这也是我们将要在这个练习中做的.
首先,我们引入启用WebGL的点图层的构造器.这个图层是一个利用WebGl的技术优势的易用的入口点.
官方文档中提示这样使用:
import {WebGLPoints as WebGLPointsLayer} from 'ol/layer';
但是会报错:
...Uncaught TypeError: ol_layer__WEBPACK_IMPORTED_MODULE_4__.WebGLPoints is not a constructor
GitHub中给出了一个解决方案:
import WebGLPointsLayer from 'ol/layer/WebGLPoints';
原因是原来的写法是从一个模块中为一个构造方法定义了一个别名,但是这个构造方法已经不存在了.
在地图的layers数组中,用WebGLPointsLayer
的一个实例替换VectorLayer
,并且使用之前的vector source.
layers: [
new TileLayer({
source: new Stamen({
layer: 'toner'
})
}),
new WebGLPointsLayer({
source: source,
style: {
symbol: {
symbolType: 'square',
size: 10,
color: 'rgba(255,0,0,0.5)'
}
}
})
],
这么一折腾之后,陨石撞击的位置就被WebGL渲染出来了:
正如你所见的,我们在创建图层是指定了style参数,这个参数允许我们指定了点的外观(即红色正方形).
改变一个WebGL的图层的样式与库的其它部分完全不同.与哪些使用Fill,Stroke和Image类的其它vector图层不同,我们只需要提供一个含有样式参数的对象.这个对象支持的属性十分简单:opacity
透明度, color
颜色, size
大小, offset
偏移量, src
(for images)图片源文件 和 symbolType
(which can be circle
, square
, triangle
or image
)符号类型.
WebGL layers use a completely different rendering system, and the style object is actually transformed dynamically into fragment and vertex shaders.
WebGL的图层使用了一个完全不同的渲染系统,并且实际上样式对象将被动态的转换成片段和顶点的着色器.
在移动地图的过程中你可以发现使用WebGL的显示效果要比之前用Canvas 2D的好得多.
现在,我认为我们都会觉得这个地图不是很好看:这可能是因为每一个点都是相同的样式.
让我们使用圆形来替换掉之前的正方形:
new WebGLPointsLayer({
source: source,
style: {
symbol: {
symbolType: 'circle',
// equivalent to: 18 * clamp('mass' / 200000, 0, 1) + 8
size: ['+', ['*', ['clamp', ['*', ['get', 'mass'], 1/20000], 0, 1], 18], 8],
color: 'rgba(255,0,0,0.5)'
}
}
})
这就是有意思的地方.我们不止指定了我们要将点渲染成圆形,我们还指定了越大的陨石它的圆也越大.
动态大小的表达式使用了一个OpenLayers的实验性的API,并且有可能以后会发生改变.尽管如此,我们还是要具体看看这个表达式.
// equivalent to: 18 * clamp('mass' / 200000, 0, 1) + 8
size: ['+', ['*', ['clamp', ['*', ['get', 'mass'], 1/20000], 0, 1], 18], 8],
WebGLPointsLayer
类在数值类型的属性中支持这种表达式,比如大小,透明度,颜色组件等等.
一个表达式由表现为数组的操作符组成.比如:
['get', 'mass']
['clamp', value, 0, 1]
['*', value, 3]
第一个运算符get将根据后面的名称(mass)读取特征的属性.其它的属性比如clamp和*将允许对另一个操作符的结果进行运算.在之前的样例中我们使用这些运算符来利用陨石的质量并转换成最终要显示的大小值,范围从8到26.
size: ['+', ['*', ['clamp', ['*', ['get', 'mass'], 1/20000], 0, 1], 18], 8]
那么这个表达式的值等价于:
let rawMass = getMass();
let mass = rawMass * 1/20000;
let clampedMass = clamp(mass, 0, 1);
let sizeT = clampedMass * 18;
let size = sizeT + 8;
最终效果图: