1、子类图层简介
子类图层(Subclassed layer)是deck.gl提供的一种自定义图层的方式,它通过继承另一个图层并重写部分内容创建出新的图层。有别于复合图层重在组合已有图层,子类图层重在重写,没有组合相关的内容。
子类图层允许开发者重新定义已有图层的生命周期方法和着色器代码。如果已有图层已经能满足你的大部分需求,只是缺少部分特性,那么通过子类图层来扩展是一个不错的选择。
继承 ScatterplotLayer 的饼状图子类图层
继承 ArcLayer 的尾迹线子类图层
2、自定义属性
添加新的功能往往需要增加新的属性,子类图层通常在 initializeState 生命周期方法中完成属性的新增。这个方法只在初始化的时候调用一次。
比如下面这段代码,在 initializeState 函数中先调用父类的 initializeState 方法完成基本的初始化。然后通过 AttributeManager 添加一个实例化属性 instanceBreakdown,它由2个分量组成,通过 props 中名称为 getBreakdown 的访问器取值。然后deck.gl在内部就会把 instanceBreakdown 这个属性通过 attribute 变量传入到顶点着色器中。
// 初始化的时候调用一次
initializeState() {
super.initializeState(); // 调用父类的initializeState()
// 通过attributeManager自定义属性
this.state.attributeManager.addInstanced({ // 添加实例化属性
instanceBreakdown: {
size: 2,
accessor: 'getBreakdown'
}
});
}
添加自定义属性
3、着色器扩展
在图层的 getShaders 生命周期方法中,我们可以通过着色器的生命周期钩子函数将自定义的着色器片段插入到父类着色器的指定位置。deck.gl 在内部把所有的着色器生命周期钩子函数对应的着色器片段拼接成完整的GLSL代码。
比如下面这个例子,在 getShaders 方法中先调用父类的 getShaders 方法获取父类的着色器对象,这个对象的通常包含 vs、fs、modules 三个属性。给这个对象指定 inject 属性,通过着色器生命周期钩子函数注入我们自定义的代码片段到指定位置即可。
getShaders() {
const shaders = super.getShaders();
shaders.inject = {
'vs:#decl': vsDeclaration, // 注入到顶点着色器顶部的声明部分
'vs:#main-end': vsMain, // 注入到顶点着色器main函数的底部
'fs:#decl': fsDeclaration, // 注入到片元着色器顶部的声明部分
'fs:DECKGL_FILTER_COLOR': fsColorFilter // 注入到处理片元颜色的函数,传入两个参数(inout vec4 color, FragmentGeometry geometry) 当前几何体的颜色,当前几何体
};
return shaders;
}
注入自定义着色器片段
4、传入uniform变量
为了传入新增的 uniform 变量,我们需要重写图层的生命周期方法 draw。
比如下面这个例子,在父类已有 uniform 变量的基础上,在调用从父类继承过来的 draw方法时传入了新增的 uniform 变量 color0、color1、color2,deck.gl 会把他们传给片元着色器。
draw({uniforms}) {
const { colors } = this.props;
const color0 = colors[0].map(x => x / 255);
const color1 = colors[1].map(x => x / 255);
const color2 = colors[2].map(x => x / 255);
super.draw({
uniforms: {
...uniforms,
color0,
color1,
color2
}
});
}
重写draw方法以传入新增的uniform变量