feat: 样式数据映射 1.2 代码结构优化

This commit is contained in:
2912401452 2021-06-22 20:58:12 +08:00
parent 535665ba31
commit 3b06bd6738
9 changed files with 448 additions and 424 deletions

View File

@ -12,7 +12,7 @@ import pickingVert from '../../shaders/picking.vert.glsl';
import project from '../../shaders/project.glsl'; import project from '../../shaders/project.glsl';
import projection from '../../shaders/projection.glsl'; import projection from '../../shaders/projection.glsl';
import sdf2d from '../../shaders/sdf_2d.glsl'; import sdf2d from '../../shaders/sdf_2d.glsl';
// import styleTextureMapping_frag from '../../shaders/styleTextureMapping_frag.glsl' import styleMapping from '../../shaders/styleMapping.glsl';
const precisionRegExp = /precision\s+(high|low|medium)p\s+float/; const precisionRegExp = /precision\s+(high|low|medium)p\s+float/;
const globalDefaultprecision = const globalDefaultprecision =
@ -34,7 +34,7 @@ export default class ShaderModuleService implements IShaderModuleService {
this.registerModule('lighting', { vs: lighting, fs: '' }); this.registerModule('lighting', { vs: lighting, fs: '' });
this.registerModule('light', { vs: light, fs: '' }); this.registerModule('light', { vs: light, fs: '' });
this.registerModule('picking', { vs: pickingVert, fs: pickingFrag }); this.registerModule('picking', { vs: pickingVert, fs: pickingFrag });
// this.registerModule('styleTextureMapping_frag', { vs: '', fs: styleTextureMapping_frag }); this.registerModule('styleMapping', { vs: styleMapping, fs: '' });
} }
public registerModule(moduleName: string, moduleParams: IModuleParams) { public registerModule(moduleName: string, moduleParams: IModuleParams) {

View File

@ -0,0 +1,95 @@
attribute float a_vertexId;
uniform mat4 u_cellTypeLayout; // 描述数据纹理 cell 结构的矩阵
uniform sampler2D u_dataTexture; // 数据纹理
bool hasOpacity() { // 判断 cell 中是否存在 opacity 的数据
return u_cellTypeLayout[1][0] > 0.0;
}
bool hasStrokeOpacity() { // 判断 cell 中是否存在 strokeOpacity 的数据
return u_cellTypeLayout[1][1] > 0.0;
}
bool hasStrokeWidth() { // 判断 cell 中是否存在 strokeWidth 的数据
return u_cellTypeLayout[1][2] > 0.0;
}
bool hasStroke() { // 判断 cell 中是否存在 stroke 的数据
return u_cellTypeLayout[1][3] > 0.0;
}
bool hasOffsets() { // 判断 cell 中是否存在 offsets 的数据
return u_cellTypeLayout[2][0] > 0.0;
}
// 根据坐标位置先是计算 uv ,然后根据 uv 从数据纹理中取值
float pos2value(vec2 pos, float columnWidth, float rowHeight) {
float u = (pos.r - 1.0) * columnWidth + columnWidth/2.0;
float v = 1.0 - ((pos.g - 1.0) * rowHeight + rowHeight/2.0);
return texture2D(u_dataTexture, vec2(u, v)).r;
}
/*
currentRow 当前行
currentColumn 当前列
columnCount 有多少列
nextStep 需要计算当前 cell 后的第几个 cell (当前 cell 则 nextStep = 0
*/
vec2 nextPos(float currentRow, float currentColumn, float columnCount, float nextStep) {
float nextColumn = currentColumn;
float nextRow = currentRow;
if(currentColumn + nextStep <= columnCount){
nextColumn = currentColumn + nextStep;
} else {
nextColumn = mod(currentColumn + nextStep, columnCount); // 不会出现跨两行
nextRow = currentRow + 1.0;
}
return vec2(nextColumn, nextRow);
}
// 计算 opacity 和标示在 cell 中取值位置的偏移量 textureOffset
vec2 calOpacityAndOffset(float cellCurrentRow, float cellCurrentColumn, float columnCount, float textureOffset, float columnWidth, float rowHeight) {
if(!hasOpacity()) { // 数据纹理中不存在 opacity 的时候取默认值(用户在 style 中传入的是常量)
return vec2(u_opacity, textureOffset);
} else {
vec2 valuePos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
float textureOpacity = pos2value(valuePos, columnWidth, rowHeight);
return vec2(textureOpacity, textureOffset + 1.0);
}
}
// 计算 strokeOpaicty 和标示在 cell 中取值位置的偏移量 textureOffset
vec2 calStrokeOpacityAndOffset(float cellCurrentRow, float cellCurrentColumn, float columnCount, float textureOffset, float columnWidth, float rowHeight) {
if(!hasStrokeOpacity()) {
return vec2(u_stroke_opacity, textureOffset);
} else {
vec2 valuePos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
float textureStrokeOpacity = pos2value(valuePos, columnWidth, rowHeight);
return vec2(textureStrokeOpacity, textureOffset + 1.0);
}
}
// 计算 strokeWidth 和标示在 cell 中取值位置的偏移量 textureOffset
vec2 calStrokeWidthAndOffset(float cellCurrentRow, float cellCurrentColumn, float columnCount, float textureOffset, float columnWidth, float rowHeight) {
if(!hasStrokeWidth()) {
return vec2(u_stroke_width, textureOffset);
} else {
vec2 valuePos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
float textureStrokeWidth = pos2value(valuePos, columnWidth, rowHeight);
return vec2(textureStrokeWidth, textureOffset + 1.0);
}
}
// 计算当前单个 cell 的大小
float calCellCount() {
// u_cellTypeLayout
// cal_height, WIDTH, 0.0, 0.0, // rowCount columnCount - 几行几列
// 1.0, 1.0, 1.0, 0.0, // opacity strokeOpacity strokeWidth stroke - 1.0 表示有数据映射、0.0 表示没有
// 1.0, 0.0, 0.0, 0.0, // offsets
// 0.0, 0.0, 0.0, 0.0
return u_cellTypeLayout[1][0] + // opacity
u_cellTypeLayout[1][1] + // strokeOpacity
u_cellTypeLayout[1][2] + // strokeWidth
u_cellTypeLayout[1][3] * 4.0 + // stroke
u_cellTypeLayout[2][0] * 2.0; // offsets
}

View File

@ -1,10 +1,12 @@
import { import {
BlendType, BlendType,
gl,
IAnimateOption, IAnimateOption,
IAttribute, IAttribute,
IBlendOptions, IBlendOptions,
ICameraService, ICameraService,
IElements, IElements,
IEncodeFeature,
IFontService, IFontService,
IGlobalConfigService, IGlobalConfigService,
IIconService, IIconService,
@ -24,13 +26,34 @@ import {
Triangulation, Triangulation,
TYPES, TYPES,
} from '@antv/l7-core'; } from '@antv/l7-core';
import { isColor, rgb2arr } from '@antv/l7-utils'; import { rgb2arr } from '@antv/l7-utils';
import { color } from 'd3-color';
import { isArray, isEqual, isFunction, isNumber, isString } from 'lodash';
import { BlendTypes } from '../utils/blend'; import { BlendTypes } from '../utils/blend';
interface ICellProperty { interface ICellProperty {
attr: string; attr: string;
count: number; count: number;
} }
export type styleSingle =
| number
| string
| [string, (single: any) => number]
| [string, [number, number]];
export type styleOffset =
| string
| [number, number]
| [string, (single: any) => number];
export type styleColor =
| string
| [string, (single: any) => string]
| [string, [string, string]];
export interface IDataTextureFrame {
data: number[];
width: number;
height: number;
}
export default class BaseModel<ChildLayerStyleOptions = {}> export default class BaseModel<ChildLayerStyleOptions = {}>
implements ILayerModel { implements ILayerModel {
public triangulation: Triangulation; public triangulation: Triangulation;
@ -41,13 +64,15 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
) => ITexture2D; ) => ITexture2D;
protected layer: ILayer; protected layer: ILayer;
protected defaultDataTexture: ITexture2D; // 默认的数据纹理
protected dataTexture: ITexture2D; // 用于数据传递的数据纹理
protected DATA_TEXTURE_WIDTH: number; // 默认有多少列(宽度) protected DATA_TEXTURE_WIDTH: number; // 默认有多少列(宽度)
protected rowCount: number; // 计算得到的当前数据纹理有多少行(高度) protected rowCount: number; // 计算得到的当前数据纹理有多少行(高度)
protected curretnOpacity: any = ''; // 当前的 opacity 值 protected curretnOpacity: styleSingle | undefined = undefined; // 当前的 opacity 值
protected curretnStrokeOpacity: any = ''; // 当前的 strokeOpacity 值 protected curretnStrokeOpacity: styleSingle | undefined = undefined; // 当前的 strokeOpacity 值
protected currentStrokeColor: any = ''; // 当前的 strokeColor 值 protected currentStrokeColor: styleColor | undefined = undefined; // 当前的 strokeColor 值
protected currentStrokeWidth: any = ''; // 当前的 strokeWidth 值 protected currentStrokeWidth: styleSingle | undefined = undefined; // 当前的 strokeWidth 值
protected currentOffsets: any = ''; // 当前的 strokeOffsets 值 protected currentOffsets: styleOffset | undefined = undefined; // 当前的 strokeOffsets 值
protected cellLength: number; // 单个 cell 的长度 protected cellLength: number; // 单个 cell 的长度
protected cellProperties: ICellProperty[]; // 需要进行数据映射的属性集合 protected cellProperties: ICellProperty[]; // 需要进行数据映射的属性集合
protected hasOpacity: number = 0; protected hasOpacity: number = 0;
@ -111,10 +136,161 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
this.rowCount = 1; this.rowCount = 1;
this.cellLength = 0; this.cellLength = 0;
this.cellProperties = []; this.cellProperties = [];
this.defaultDataTexture = createTexture2D({
flipY: true,
data: [1],
format: gl.LUMINANCE,
type: gl.FLOAT,
width: 1,
height: 1,
});
} }
// style datatexture mapping // style datatexture mapping
/**
* -
*/
public clearLastCalRes() {
this.cellProperties = []; // 清空上一次计算的需要进行数据映射的属性集合
this.cellLength = 0; // 清空上一次计算的 cell 的长度
this.hasOpacity = 0; // 清空上一次是否需要对 opacity 属性进行数据映射的判断
this.hasStrokeOpacity = 0; // 清空上一次是否需要对 strokeOpacity 属性进行数据映射的判断
this.hasStrokeWidth = 0; // 清空上一次是否需要对 strokeWidth 属性进行数据映射的判断
this.hasStroke = 0; // 清空上一次是否需要对 stroke 属性进行数据映射的判断
this.hasOffsets = 0; // 清空上一次是否需要对 offsets 属性进行数据映射的判断
}
/**
* -
* @param options
* @returns
*/
public dataTextureNeedUpdate(options: {
opacity?: styleSingle;
strokeOpacity?: styleSingle;
strokeWidth?: styleSingle;
stroke?: styleColor;
offsets?: styleOffset;
}): boolean {
let isUpdate = false;
if (!isEqual(options.opacity, this.curretnOpacity)) {
isUpdate = true;
this.curretnOpacity = options.opacity;
}
if (!isEqual(options.strokeOpacity, this.curretnStrokeOpacity)) {
isUpdate = true;
this.curretnStrokeOpacity = options.strokeOpacity;
}
if (!isEqual(options.strokeWidth, this.currentStrokeWidth)) {
isUpdate = true;
this.currentStrokeWidth = options.strokeWidth;
}
if (!isEqual(options.stroke, this.currentStrokeColor)) {
isUpdate = true;
this.currentStrokeColor = options.stroke;
}
if (!isEqual(options.offsets, this.currentOffsets)) {
isUpdate = true;
this.currentOffsets = options.offsets;
}
if (this.defaultDataTexture) {
isUpdate = true;
}
if (this.dataTexture === undefined) {
isUpdate = true;
}
return isUpdate;
}
/**
*
* @param options
*/
public judgeStyleAttributes(options: {
opacity?: styleSingle;
strokeOpacity?: styleSingle;
strokeWidth?: styleSingle;
stroke?: styleColor;
offsets?: styleOffset;
}) {
this.clearLastCalRes(); // 清除上一次的计算结果 - 全量清除
if (options.opacity !== undefined && !isNumber(options.opacity)) {
// 数据映射
this.cellProperties.push({ attr: 'opacity', count: 1 });
this.hasOpacity = 1;
this.cellLength += 1;
}
if (
options.strokeOpacity !== undefined &&
!isNumber(options.strokeOpacity)
) {
// 数据映射
this.cellProperties.push({ attr: 'strokeOpacity', count: 1 });
this.hasStrokeOpacity = 1;
this.cellLength += 1;
}
if (options.strokeWidth !== undefined && !isNumber(options.strokeWidth)) {
// 数据映射
this.cellProperties.push({ attr: 'strokeWidth', count: 1 });
this.hasStrokeWidth = 1;
this.cellLength += 1;
}
if (options.stroke !== undefined && !this.isStaticColor(options.stroke)) {
// 数据映射
this.cellProperties.push({ attr: 'stroke', count: 4 });
this.cellLength += 4;
this.hasStroke = 1;
}
if (
options.offsets !== undefined &&
!this.isOffsetStatic(options.offsets)
) {
// 数据映射
this.cellProperties.push({ attr: 'offsets', count: 2 });
this.cellLength += 2;
this.hasOffsets = 1;
}
}
/**
* stroke
* @param stroke
* @returns
*/
public isStaticColor(stroke: styleColor): boolean {
if (isString(stroke)) {
if (color(stroke)) {
return true;
} else {
return false;
}
}
return false;
}
/**
* offsets
* @param offsets
* @returns
*/
public isOffsetStatic(offsets: styleOffset) {
if (
isArray(offsets) &&
offsets.length === 2 &&
isNumber(offsets[0]) &&
isNumber(offsets[1])
) {
return true;
} else {
return false;
}
}
/** /**
* *
* @param d * @param d
@ -132,34 +308,29 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
* @param cellData * @param cellData
* @param cellPropertiesLayouts * @param cellPropertiesLayouts
*/ */
public patchData(d: number[], cellData: any, cellPropertiesLayouts: any) { public patchData(
d: number[],
cellData: IEncodeFeature,
cellPropertiesLayouts: ICellProperty[],
) {
for (const layout of cellPropertiesLayouts) { for (const layout of cellPropertiesLayouts) {
const { attr, count } = layout; const { attr, count } = layout;
if (!cellData) {
const value = cellData[attr];
if (value) {
// 数据中存在该属性
if (attr === 'stroke') { if (attr === 'stroke') {
d.push(-1, -1, -1, -1); d.push(...rgb2arr(value));
} else if (attr === 'offsets') { } else if (attr === 'offsets') {
d.push(-1, -1); // d.push(...value)
d.push(-value[0], value[1]);
} else { } else {
d.push(-1); d.push(value);
} }
} else { } else {
const value = cellData[attr]; // 若不存在时则补位
this.patchMod(d, count);
if (value) {
// 数据中存在该属性
if (attr === 'stroke') {
d.push(...rgb2arr(value));
} else if (attr === 'offsets') {
// d.push(...value)
d.push(-value[0], value[1]);
} else {
d.push(value);
}
} else {
// 若不存在时则补位
this.patchMod(d, count);
}
} }
} }
} }
@ -173,14 +344,9 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
*/ */
public calDataFrame( public calDataFrame(
cellLength: number, cellLength: number,
encodeData: any, encodeData: IEncodeFeature[],
cellPropertiesLayouts: any, cellPropertiesLayouts: ICellProperty[],
): any { ): IDataTextureFrame {
if (cellLength > this.DATA_TEXTURE_WIDTH) {
// console.log('failed');
return false;
}
const encodeDatalength = encodeData.length; const encodeDatalength = encodeData.length;
const rowCount = Math.ceil( const rowCount = Math.ceil(
(encodeDatalength * cellLength) / this.DATA_TEXTURE_WIDTH, (encodeDatalength * cellLength) / this.DATA_TEXTURE_WIDTH,

View File

@ -91,25 +91,28 @@ export default class RegisterStyleAttributePlugin implements ILayerPlugin {
}, },
}, },
}); });
// styleAttributeService.registerStyleAttribute({ styleAttributeService.registerStyleAttribute({
// name: 'strokeOpacity', // 统一注册每个顶点的唯一编号(目前用于样式的数据映射计算使用)
// type: AttributeType.Attribute, name: 'vertexId',
// descriptor: { type: AttributeType.Attribute,
// name: 'a_stroke_opacity', descriptor: {
// buffer: { name: 'a_vertexId',
// // give the WebGL driver a hint that this buffer may change buffer: {
// usage: gl.DYNAMIC_DRAW, // give the WebGL driver a hint that this buffer may change
// data: [], usage: gl.DYNAMIC_DRAW,
// type: gl.FLOAT, data: [],
// }, type: gl.FLOAT,
// size: 1, },
// update: (feature: IEncodeFeature, featureIdx: number) => { size: 1,
// const { strokeOpacity } = feature; update: (
// // console.log('feature', feature) feature: IEncodeFeature,
// // console.log('strokeOpacity', strokeOpacity) featureIdx: number,
// return !isNumber(strokeOpacity) ? [1.0] : [strokeOpacity]; vertex: number[],
// }, attributeIdx: number,
// }, ) => {
// }); return [featureIdx];
},
},
});
} }
} }

View File

@ -8,106 +8,23 @@ import {
ILayerConfig, ILayerConfig,
IModel, IModel,
IModelUniform, IModelUniform,
ITexture2D,
} from '@antv/l7-core'; } from '@antv/l7-core';
import { isColor, rgb2arr } from '@antv/l7-utils'; import { rgb2arr } from '@antv/l7-utils';
import BaseModel from '../../core/BaseModel'; import BaseModel, { styleColor, styleOffset, styleSingle } from '../../core/BaseModel';
import { PointFillTriangulation } from '../../core/triangulation'; import { PointFillTriangulation } from '../../core/triangulation';
import pointFillFrag from '../shaders/fill_frag.glsl'; import pointFillFrag from '../shaders/fill_frag.glsl';
import pointFillVert from '../shaders/fill_vert.glsl'; import pointFillVert from '../shaders/fill_vert.glsl';
import { isArray, isNumber, isString } from 'lodash'; import { isNumber, isString } from 'lodash';
interface IPointLayerStyleOptions { interface IPointLayerStyleOptions {
opacity: any; opacity: styleSingle;
strokeWidth: number; strokeWidth: styleSingle;
stroke: string; stroke: styleColor;
strokeOpacity: number; strokeOpacity: styleSingle;
offsets: [number, number]; offsets: styleOffset;
} }
// 判断当前使用的 style 中的变量属性是否需要进行数据映射 // 判断当前使用的 style 中的变量属性是否需要进行数据映射
export default class FillModel extends BaseModel { export default class FillModel extends BaseModel {
protected dataTexture: ITexture2D;
/**
* offsets
* @param offsets
* @returns
*/
public isOffsetStatic(offsets: any) {
if (
isArray(offsets) &&
offsets.length === 2 &&
isNumber(offsets[0]) &&
isNumber(offsets[1])
) {
return true;
} else {
return false;
}
}
/**
* - layer
* @param opacity
* @param strokeOpacity
* @param strokeWidth
* @param stroke
* @param offsets
* @returns
*/
public isDataTextureUpdate(
opacity: any,
strokeOpacity: any,
strokeWidth: any,
stroke: any,
offsets: any,
) {
let isUpdate = false;
if (this.curretnOpacity !== JSON.stringify(opacity)) {
// 判断 opacity 是否发生改变
isUpdate = true;
this.curretnOpacity = JSON.stringify(opacity);
}
if (this.curretnStrokeOpacity !== JSON.stringify(strokeOpacity)) {
// 判断 strokeOpacity 是否发生改变
isUpdate = true;
this.curretnStrokeOpacity = JSON.stringify(strokeOpacity);
}
if (this.currentStrokeWidth !== JSON.stringify(strokeWidth)) {
// 判断 strokeWidth 是否发生改变
isUpdate = true;
this.currentStrokeWidth = JSON.stringify(strokeWidth);
}
if (this.currentStrokeColor !== JSON.stringify(stroke)) {
// 判断 stroke 是否发生改变
isUpdate = true;
this.currentStrokeColor = JSON.stringify(stroke);
}
if (this.currentOffsets !== JSON.stringify(offsets)) {
// 判断 offsets 是否发生改变
isUpdate = true;
this.currentOffsets = JSON.stringify(offsets);
}
if (this.dataTexture === undefined) {
isUpdate = true;
}
return isUpdate;
}
/**
* - layer
*/
public clearLastCalRes() {
this.cellProperties = []; // 清空上一次计算的需要进行数据映射的属性集合
this.cellLength = 0; // 清空上一次计算的 cell 的长度
this.hasOpacity = 0; // 清空上一次是否需要对 opacity 属性进行数据映射的判断
this.hasStrokeOpacity = 0; // 清空上一次是否需要对 strokeOpacity 属性进行数据映射的判断
this.hasStrokeWidth = 0; // 清空上一次是否需要对 strokeWidth 属性进行数据映射的判断
this.hasStroke = 0; // 清空上一次是否需要对 stroke 属性进行数据映射的判断
this.hasOffsets = 0; // 清空上一次是否需要对 offsets 属性进行数据映射的判断
}
public getUninforms(): IModelUniform { public getUninforms(): IModelUniform {
const { const {
opacity = 1, opacity = 1,
@ -118,80 +35,42 @@ export default class FillModel extends BaseModel {
} = this.layer.getLayerConfig() as IPointLayerStyleOptions; } = this.layer.getLayerConfig() as IPointLayerStyleOptions;
if ( if (
this.isDataTextureUpdate( this.dataTextureNeedUpdate({
opacity, opacity,
strokeOpacity, strokeOpacity,
strokeWidth, strokeWidth,
stroke, stroke,
offsets, offsets,
) })
) { ) {
this.clearLastCalRes(); // 清除上一次的计算结果 // 判断当前的样式中哪些是需要进行数据映射的,哪些是常量,同时计算用于构建数据纹理的一些中间变量
this.judgeStyleAttributes({
if (!isNumber(opacity)) { opacity,
// 数据映射 strokeOpacity,
this.cellProperties.push({ attr: 'opacity', count: 1 }); strokeWidth,
this.hasOpacity = 1; stroke,
this.cellLength += 1; offsets,
} });
if (!isNumber(strokeOpacity)) {
// 数据映射
this.cellProperties.push({ attr: 'strokeOpacity', count: 1 });
this.hasStrokeOpacity = 1;
this.cellLength += 1;
}
if (!isNumber(strokeWidth)) {
// 数据映射
this.cellProperties.push({ attr: 'strokeWidth', count: 1 });
this.hasStrokeWidth = 1;
this.cellLength += 1;
}
if (!isColor(stroke)) {
// 数据映射
this.cellProperties.push({ attr: 'stroke', count: 4 });
this.cellLength += 4;
this.hasStroke = 1;
}
if (!this.isOffsetStatic(offsets)) {
// 数据映射
this.cellProperties.push({ attr: 'offsets', count: 2 });
this.cellLength += 2;
this.hasOffsets = 1;
}
const encodeData = this.layer.getEncodedData(); const encodeData = this.layer.getEncodedData();
if (this.cellLength > 0) { const { data, width, height } = this.calDataFrame(
// 需要构建数据纹理 this.cellLength,
const { data, width, height } = this.calDataFrame( encodeData,
this.cellLength, this.cellProperties,
encodeData, );
this.cellProperties, this.rowCount = height; // 当前数据纹理有多少行
);
this.rowCount = height; // 当前数据纹理有多少行
this.dataTexture = this.createTexture2D({ this.dataTexture =
flipY: true, this.cellLength > 0
data, ? this.createTexture2D({
format: gl.LUMINANCE, flipY: true,
type: gl.FLOAT, data,
width, format: gl.LUMINANCE,
height, type: gl.FLOAT,
}); width,
} else { height,
// 不需要构建数据纹理 - 构建一个空纹理 })
this.dataTexture = this.createTexture2D({ : this.defaultDataTexture;
flipY: true,
data: [1],
format: gl.LUMINANCE,
type: gl.FLOAT,
width: 1,
height: 1,
});
}
} }
return { return {
@ -220,9 +99,11 @@ export default class FillModel extends BaseModel {
u_stroke_opacity: isNumber(strokeOpacity) ? strokeOpacity : 1.0, u_stroke_opacity: isNumber(strokeOpacity) ? strokeOpacity : 1.0,
u_stroke_width: isNumber(strokeWidth) ? strokeWidth : 0.0, u_stroke_width: isNumber(strokeWidth) ? strokeWidth : 0.0,
u_stroke_color: u_stroke_color:
isString(stroke) && isColor(stroke) ? rgb2arr(stroke) : [0, 0, 0, 0], isString(stroke) && this.isStaticColor(stroke)
? rgb2arr(stroke)
: [0, 0, 0, 0],
u_offsets: this.isOffsetStatic(offsets) u_offsets: this.isOffsetStatic(offsets)
? [-offsets[0], offsets[1]] ? (offsets as [number, number])
: [0, 0], : [0, 0],
}; };
} }
@ -317,30 +198,6 @@ export default class FillModel extends BaseModel {
}, },
}); });
// vertex id 用于作为数据纹理取值的唯一编号
this.styleAttributeService.registerStyleAttribute({
name: 'vertexId',
type: AttributeType.Attribute,
descriptor: {
name: 'a_vertexId',
buffer: {
// give the WebGL driver a hint that this buffer may change
usage: gl.DYNAMIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 1,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
) => {
return [featureIdx];
},
},
});
// point layer size; // point layer size;
this.styleAttributeService.registerStyleAttribute({ this.styleAttributeService.registerStyleAttribute({
name: 'shape', name: 'shape',

View File

@ -4,10 +4,7 @@ attribute vec2 a_Extrude;
attribute float a_Size; attribute float a_Size;
attribute float a_Shape; attribute float a_Shape;
attribute float a_vertexId; varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
uniform mat4 u_cellTypeLayout;
uniform sampler2D u_dataTexture;
varying mat4 styleMappingMat;
uniform mat4 u_ModelMatrix; uniform mat4 u_ModelMatrix;
uniform mat4 u_Mvp; uniform mat4 u_Mvp;
@ -22,101 +19,11 @@ uniform float u_stroke_width : 2;
uniform vec4 u_stroke_color : [0.0, 0.0, 0.0, 0.0]; uniform vec4 u_stroke_color : [0.0, 0.0, 0.0, 0.0];
uniform vec2 u_offsets; uniform vec2 u_offsets;
#pragma include "styleMapping"
#pragma include "projection" #pragma include "projection"
#pragma include "picking" #pragma include "picking"
/*
currentRow 当前行
currentColumn 当前列
columnCount 有多少列
nextStep 需要计算当前 cell 后的第几个 cell (当前 cell 则 nextStep = 0
*/
vec2 nextPos(float currentRow, float currentColumn, float columnCount, float nextStep) {
float nextColumn = currentColumn;
float nextRow = currentRow;
if(currentColumn + nextStep <= columnCount){
nextColumn = currentColumn + nextStep;
} else {
nextColumn = mod(currentColumn + nextStep, columnCount); // 不会出现跨两行
nextRow = currentRow + 1.0;
}
return vec2(nextColumn, nextRow);
}
// 根据坐标位置先是计算 uv ,然后根据 uv 从数据纹理中取值
float pos2value(vec2 pos, float columnWidth, float rowHeight) {
float u = (pos.r - 1.0) * columnWidth + columnWidth/2.0;
float v = 1.0 - ((pos.g - 1.0) * rowHeight + rowHeight/2.0);
return texture2D(u_dataTexture, vec2(u, v)).r;
}
bool hasOpacity() { // 判断 cell 中是否存在 opacity 的数据
return u_cellTypeLayout[1][0] > 0.0;
}
bool hasStrokeOpacity() { // 判断 cell 中是否存在 strokeOpacity 的数据
return u_cellTypeLayout[1][1] > 0.0;
}
bool hasStrokeWidth() { // 判断 cell 中是否存在 strokeWidth 的数据
return u_cellTypeLayout[1][2] > 0.0;
}
bool hasStroke() { // 判断 cell 中是否存在 stroke 的数据
return u_cellTypeLayout[1][3] > 0.0;
}
bool hasOffsets() { // 判断 cell 中是否存在 offsets 的数据
return u_cellTypeLayout[2][0] > 0.0;
}
// 计算 opacity 和标志在 cell 中取值用的 offset
vec2 calOpacityAndOffset(float cellCurrentRow, float cellCurrentColumn, float columnCount, float textureOffset, float columnWidth, float rowHeight) {
if(!hasOpacity()) { // 数据纹理中不存在 opacity 的时候取默认值(用户在 style 中传入的是常量)
return vec2(u_opacity, textureOffset);
} else {
vec2 valuePos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
float textureOpacity = pos2value(valuePos, columnWidth, rowHeight);
return vec2(textureOpacity, textureOffset + 1.0);
}
}
vec2 calStrokeOpacityAndOffset(float cellCurrentRow, float cellCurrentColumn, float columnCount, float textureOffset, float columnWidth, float rowHeight) {
if(!hasStrokeOpacity()) {
return vec2(u_stroke_opacity, textureOffset);
} else {
vec2 valuePos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
float textureStrokeOpacity = pos2value(valuePos, columnWidth, rowHeight);
return vec2(textureStrokeOpacity, textureOffset + 1.0);
}
}
vec2 calStrokeWidthAndOffset(float cellCurrentRow, float cellCurrentColumn, float columnCount, float textureOffset, float columnWidth, float rowHeight) {
if(!hasStrokeWidth()) {
return vec2(u_stroke_width, textureOffset);
} else {
vec2 valuePos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
float textureStrokeWidth = pos2value(valuePos, columnWidth, rowHeight);
return vec2(textureStrokeWidth, textureOffset + 1.0);
}
}
float calCellCount() { // 计算当前单个 cell 的大小
// u_cellTypeLayout
// cal_height, WIDTH, 0.0, 0.0, // rowCount columnCount - 几行几列
// 1.0, 1.0, 1.0, 0.0, // opacity strokeOpacity strokeWidth stroke - 1.0 表示有数据映射、0.0 表示没有
// 1.0, 0.0, 0.0, 0.0, // offsets
// 0.0, 0.0, 0.0, 0.0
return u_cellTypeLayout[1][0] + // opacity
u_cellTypeLayout[1][1] + // strokeOpacity
u_cellTypeLayout[1][2] + // strokeWidth
u_cellTypeLayout[1][3] * 4.0 + // stroke
u_cellTypeLayout[2][0] * 2.0; // offsets
}
void main() { void main() {
vec2 extrude = a_Extrude; vec2 extrude = a_Extrude;
float shape_type = a_Shape; float shape_type = a_Shape;

View File

@ -15,10 +15,6 @@ export function rgb2arr(str: string) {
return arr; return arr;
} }
export function isColor(str: string) {
return d3.color(str);
}
export function decodePickingColor(color: Uint8Array): number { export function decodePickingColor(color: Uint8Array): number {
const i1 = color && color[0]; const i1 = color && color[0];
const i2 = color && color[1]; const i2 = color && color[1];

View File

@ -17,7 +17,7 @@ export default class Amap2demo extends React.Component {
center: [121.107846, 30.267069], center: [121.107846, 30.267069],
pitch: 0, pitch: 0,
style: 'normal', style: 'normal',
zoom: 2, zoom: 20,
animateEnable: false, animateEnable: false,
}), }),
}); });
@ -26,7 +26,7 @@ export default class Amap2demo extends React.Component {
lng: 121.107846, lng: 121.107846,
lat: 30.267069, lat: 30.267069,
opacity2: 0.2, opacity2: 0.2,
strokeOpacity2: 0.2, strokeOpacity2: 0.4,
strokeColor: '#000', strokeColor: '#000',
strokeWidth: 0.5, strokeWidth: 0.5,
// offsets2: [0, 0] // offsets2: [0, 0]
@ -36,7 +36,7 @@ export default class Amap2demo extends React.Component {
lng: 121.107, lng: 121.107,
lat: 30.267069, lat: 30.267069,
opacity2: 0.4, opacity2: 0.4,
strokeOpacity2: 0.4, strokeOpacity2: 0.6,
strokeColor: '#0f0', strokeColor: '#0f0',
strokeWidth: 2, strokeWidth: 2,
offsets2: [100, 100], offsets2: [100, 100],
@ -45,7 +45,7 @@ export default class Amap2demo extends React.Component {
lng: 121.107846, lng: 121.107846,
lat: 30.26718, lat: 30.26718,
opacity2: 0.6, opacity2: 0.6,
strokeOpacity2: 0.6, strokeOpacity2: 0.8,
strokeColor: '#f00', strokeColor: '#f00',
strokeWidth: 4, strokeWidth: 4,
// offsets2: [200, 200] // offsets2: [200, 200]
@ -67,92 +67,92 @@ export default class Amap2demo extends React.Component {
'https://gw-office.alipayobjects.com/bmw-prod/ccc91465-d3ea-4eda-a178-7c1815dac32b.json'; 'https://gw-office.alipayobjects.com/bmw-prod/ccc91465-d3ea-4eda-a178-7c1815dac32b.json';
scene.on('loaded', () => { scene.on('loaded', () => {
for (let i = 0; i < 1; i++) { for (let i = 0; i < 1; i++) {
fetch(thousandMhundred) // fetch(thousandMhundred)
.then((res) => res.text()) // .then((res) => res.text())
.then((data) => { // .then((data) => {
// console.log('data', data) // // console.log('data', data)
// lng: Math.random() * 180, // 0 ~ 180 // // lng: Math.random() * 180, // 0 ~ 180
// lat: Math.random() * 100 - 50, // -50 ~ 50 // // lat: Math.random() * 100 - 50, // -50 ~ 50
// customOpacity: Math.random(), // // customOpacity: Math.random(),
// customStroke: `rgb(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 1)`, // // customStroke: `rgb(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 1)`,
// customStrokeOpacity: Math.random(), // // customStrokeOpacity: Math.random(),
// customStrokeWidth: Math.random() * 5, // // customStrokeWidth: Math.random() * 5,
let layer = new PointLayer() // let layer = new PointLayer()
.source(JSON.parse(data), { // .source(JSON.parse(data), {
parser: { // parser: {
type: 'json', // type: 'json',
x: 'lng', // x: 'lng',
y: 'lat', // y: 'lat',
}, // },
}) // })
.shape('circle') // .shape('circle')
.color('rgba(255, 0, 0, 1.0)') // .color('rgba(255, 0, 0, 1.0)')
.size(10) // .size(10)
.style({ // .style({
opacity: 'customOpacity', // opacity: 'customOpacity',
// strokeOpacity: 'customStrokeOpacity', // // strokeOpacity: 'customStrokeOpacity',
// strokeWidth: 'customStrokeWidth', // // strokeWidth: 'customStrokeWidth',
// stroke: 'customStroke', // // stroke: 'customStroke',
}); // });
scene.addLayer(layer); // scene.addLayer(layer);
}); // });
// let layer = new PointLayer() let layer = new PointLayer()
// .source(originData, { .source(originData, {
// parser: { parser: {
// type: 'json', type: 'json',
// x: 'lng', x: 'lng',
// y: 'lat', y: 'lat',
// }, },
// }) })
// .shape('circle') .shape('circle')
// // .shape('normal') // .shape('normal')
// // .shape('fill') // .shape('fill')
// // .color('rgba(255, 0, 0, 0.9)') // .color('rgba(255, 0, 0, 0.9)')
// .color('rgba(255, 0, 0, 1.0)') .color('rgba(255, 0, 0, 1.0)')
// .size(10) .size(10)
// // .offsets('123') // .offsets('123')
// .style({ .style({
// // stroke: '#000', // stroke: '#000',
// // stroke: 'rgba(0, 255, 0, 1)', // stroke: 'rgba(0, 255, 0, 1)',
// stroke: 'strokeColor', // stroke: 'strokeColor',
// // stroke: ['strokeColor', (d: any) => { // stroke: ['strokeColor', (d: any) => {
// // return d // return d
// // }], // }],
// // stroke: ['strokeColor', ["#f00", "#ff0"]], // stroke: ['strokeColor', ["#f00", "#ff0"]],
// // strokeWidth: 4, // strokeWidth: 4,
// // strokeWidth: "strokeWidth", // strokeWidth: "strokeWidth",
// // strokeWidth: ["strokeWidth", [1, 2]], // strokeWidth: ["strokeWidth", [1, 2]],
// strokeWidth: ["strokeWidth", (d: any) => { // strokeWidth: ["strokeWidth", (d: any) => {
// return d * 2 // return d * 2
// }], // }],
// // strokeOpacity: 0.5, // strokeOpacity: 0.5,
// // strokeOpacity: 'strokeOpacity2', strokeOpacity: 'strokeOpacity2',
// // strokeOpacity: 1.0, // strokeOpacity: 1.0,
// // strokeOpacity: [ // strokeOpacity: [
// // 'strokeOpacity2', // 'strokeOpacity2',
// // (d: any) => { // (d: any) => {
// // // console.log('strokeOpacity2', d) // // console.log('strokeOpacity2', d)
// // return d*2; // return d*2;
// // }, // },
// // ], // ],
// // strokeOpacity: ['opacity2', [0.2, 0.6]], // strokeOpacity: ['opacity2', [0.2, 0.6]],
// // offsets: [100, 100], // offsets: [100, 100],
// offsets: 'offsets2', // offsets: 'offsets2',
// // offsets: ['offsets2', (d: any) => d], // offsets: ['offsets2', (d: any) => d],
// opacity: 'opacity2', opacity: 'opacity2',
// // opacity: 0.2 // opacity: 0.2
// // opacity: 0, // opacity: 0,
// // opacity: ['opacity2', (d: any) => { // opacity: ['opacity2', (d: any) => {
// // return d // return d
// // }] // }]
// // opacity: ['opacity2', [0.2, 0.6]], // opacity: ['opacity2', [0.2, 0.6]],
// }) })
// .active(true); .active(true);
// scene.addLayer(layer); scene.addLayer(layer);
} }
}); });
} }