mirror of https://gitee.com/antv-l7/antv-l7
feat: 样式数据映射 1.2 代码结构优化
This commit is contained in:
parent
535665ba31
commit
3b06bd6738
|
@ -12,7 +12,7 @@ import pickingVert from '../../shaders/picking.vert.glsl';
|
|||
import project from '../../shaders/project.glsl';
|
||||
import projection from '../../shaders/projection.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 globalDefaultprecision =
|
||||
|
@ -34,7 +34,7 @@ export default class ShaderModuleService implements IShaderModuleService {
|
|||
this.registerModule('lighting', { vs: lighting, fs: '' });
|
||||
this.registerModule('light', { vs: light, fs: '' });
|
||||
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) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
import {
|
||||
BlendType,
|
||||
gl,
|
||||
IAnimateOption,
|
||||
IAttribute,
|
||||
IBlendOptions,
|
||||
ICameraService,
|
||||
IElements,
|
||||
IEncodeFeature,
|
||||
IFontService,
|
||||
IGlobalConfigService,
|
||||
IIconService,
|
||||
|
@ -24,13 +26,34 @@ import {
|
|||
Triangulation,
|
||||
TYPES,
|
||||
} 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';
|
||||
interface ICellProperty {
|
||||
attr: string;
|
||||
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 = {}>
|
||||
implements ILayerModel {
|
||||
public triangulation: Triangulation;
|
||||
|
@ -41,13 +64,15 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
|
|||
) => ITexture2D;
|
||||
|
||||
protected layer: ILayer;
|
||||
protected defaultDataTexture: ITexture2D; // 默认的数据纹理
|
||||
protected dataTexture: ITexture2D; // 用于数据传递的数据纹理
|
||||
protected DATA_TEXTURE_WIDTH: number; // 默认有多少列(宽度)
|
||||
protected rowCount: number; // 计算得到的当前数据纹理有多少行(高度)
|
||||
protected curretnOpacity: any = ''; // 当前的 opacity 值
|
||||
protected curretnStrokeOpacity: any = ''; // 当前的 strokeOpacity 值
|
||||
protected currentStrokeColor: any = ''; // 当前的 strokeColor 值
|
||||
protected currentStrokeWidth: any = ''; // 当前的 strokeWidth 值
|
||||
protected currentOffsets: any = ''; // 当前的 strokeOffsets 值
|
||||
protected curretnOpacity: styleSingle | undefined = undefined; // 当前的 opacity 值
|
||||
protected curretnStrokeOpacity: styleSingle | undefined = undefined; // 当前的 strokeOpacity 值
|
||||
protected currentStrokeColor: styleColor | undefined = undefined; // 当前的 strokeColor 值
|
||||
protected currentStrokeWidth: styleSingle | undefined = undefined; // 当前的 strokeWidth 值
|
||||
protected currentOffsets: styleOffset | undefined = undefined; // 当前的 strokeOffsets 值
|
||||
protected cellLength: number; // 单个 cell 的长度
|
||||
protected cellProperties: ICellProperty[]; // 需要进行数据映射的属性集合
|
||||
protected hasOpacity: number = 0;
|
||||
|
@ -111,10 +136,161 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
|
|||
this.rowCount = 1;
|
||||
this.cellLength = 0;
|
||||
this.cellProperties = [];
|
||||
this.defaultDataTexture = createTexture2D({
|
||||
flipY: true,
|
||||
data: [1],
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width: 1,
|
||||
height: 1,
|
||||
});
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -132,34 +308,29 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
|
|||
* @param cellData
|
||||
* @param cellPropertiesLayouts
|
||||
*/
|
||||
public patchData(d: number[], cellData: any, cellPropertiesLayouts: any) {
|
||||
public patchData(
|
||||
d: number[],
|
||||
cellData: IEncodeFeature,
|
||||
cellPropertiesLayouts: ICellProperty[],
|
||||
) {
|
||||
for (const layout of cellPropertiesLayouts) {
|
||||
const { attr, count } = layout;
|
||||
if (!cellData) {
|
||||
|
||||
const value = cellData[attr];
|
||||
|
||||
if (value) {
|
||||
// 数据中存在该属性
|
||||
if (attr === 'stroke') {
|
||||
d.push(-1, -1, -1, -1);
|
||||
d.push(...rgb2arr(value));
|
||||
} else if (attr === 'offsets') {
|
||||
d.push(-1, -1);
|
||||
// d.push(...value)
|
||||
d.push(-value[0], value[1]);
|
||||
} else {
|
||||
d.push(-1);
|
||||
d.push(value);
|
||||
}
|
||||
} else {
|
||||
const value = cellData[attr];
|
||||
|
||||
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);
|
||||
}
|
||||
// 若不存在时则补位
|
||||
this.patchMod(d, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,14 +344,9 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
|
|||
*/
|
||||
public calDataFrame(
|
||||
cellLength: number,
|
||||
encodeData: any,
|
||||
cellPropertiesLayouts: any,
|
||||
): any {
|
||||
if (cellLength > this.DATA_TEXTURE_WIDTH) {
|
||||
// console.log('failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
encodeData: IEncodeFeature[],
|
||||
cellPropertiesLayouts: ICellProperty[],
|
||||
): IDataTextureFrame {
|
||||
const encodeDatalength = encodeData.length;
|
||||
const rowCount = Math.ceil(
|
||||
(encodeDatalength * cellLength) / this.DATA_TEXTURE_WIDTH,
|
||||
|
|
|
@ -91,25 +91,28 @@ export default class RegisterStyleAttributePlugin implements ILayerPlugin {
|
|||
},
|
||||
},
|
||||
});
|
||||
// styleAttributeService.registerStyleAttribute({
|
||||
// name: 'strokeOpacity',
|
||||
// type: AttributeType.Attribute,
|
||||
// descriptor: {
|
||||
// name: 'a_stroke_opacity',
|
||||
// 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) => {
|
||||
// const { strokeOpacity } = feature;
|
||||
// // console.log('feature', feature)
|
||||
// // console.log('strokeOpacity', strokeOpacity)
|
||||
// return !isNumber(strokeOpacity) ? [1.0] : [strokeOpacity];
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
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];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,106 +8,23 @@ import {
|
|||
ILayerConfig,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
ITexture2D,
|
||||
} from '@antv/l7-core';
|
||||
import { isColor, rgb2arr } from '@antv/l7-utils';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { rgb2arr } from '@antv/l7-utils';
|
||||
import BaseModel, { styleColor, styleOffset, styleSingle } from '../../core/BaseModel';
|
||||
import { PointFillTriangulation } from '../../core/triangulation';
|
||||
import pointFillFrag from '../shaders/fill_frag.glsl';
|
||||
import pointFillVert from '../shaders/fill_vert.glsl';
|
||||
|
||||
import { isArray, isNumber, isString } from 'lodash';
|
||||
import { isNumber, isString } from 'lodash';
|
||||
interface IPointLayerStyleOptions {
|
||||
opacity: any;
|
||||
strokeWidth: number;
|
||||
stroke: string;
|
||||
strokeOpacity: number;
|
||||
offsets: [number, number];
|
||||
opacity: styleSingle;
|
||||
strokeWidth: styleSingle;
|
||||
stroke: styleColor;
|
||||
strokeOpacity: styleSingle;
|
||||
offsets: styleOffset;
|
||||
}
|
||||
// 判断当前使用的 style 中的变量属性是否需要进行数据映射
|
||||
|
||||
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 {
|
||||
const {
|
||||
opacity = 1,
|
||||
|
@ -118,80 +35,42 @@ export default class FillModel extends BaseModel {
|
|||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||
|
||||
if (
|
||||
this.isDataTextureUpdate(
|
||||
this.dataTextureNeedUpdate({
|
||||
opacity,
|
||||
strokeOpacity,
|
||||
strokeWidth,
|
||||
stroke,
|
||||
offsets,
|
||||
)
|
||||
})
|
||||
) {
|
||||
this.clearLastCalRes(); // 清除上一次的计算结果
|
||||
|
||||
if (!isNumber(opacity)) {
|
||||
// 数据映射
|
||||
this.cellProperties.push({ attr: 'opacity', count: 1 });
|
||||
this.hasOpacity = 1;
|
||||
this.cellLength += 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// 判断当前的样式中哪些是需要进行数据映射的,哪些是常量,同时计算用于构建数据纹理的一些中间变量
|
||||
this.judgeStyleAttributes({
|
||||
opacity,
|
||||
strokeOpacity,
|
||||
strokeWidth,
|
||||
stroke,
|
||||
offsets,
|
||||
});
|
||||
|
||||
const encodeData = this.layer.getEncodedData();
|
||||
if (this.cellLength > 0) {
|
||||
// 需要构建数据纹理
|
||||
const { data, width, height } = this.calDataFrame(
|
||||
this.cellLength,
|
||||
encodeData,
|
||||
this.cellProperties,
|
||||
);
|
||||
this.rowCount = height; // 当前数据纹理有多少行
|
||||
const { data, width, height } = this.calDataFrame(
|
||||
this.cellLength,
|
||||
encodeData,
|
||||
this.cellProperties,
|
||||
);
|
||||
this.rowCount = height; // 当前数据纹理有多少行
|
||||
|
||||
this.dataTexture = this.createTexture2D({
|
||||
flipY: true,
|
||||
data,
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
} else {
|
||||
// 不需要构建数据纹理 - 构建一个空纹理
|
||||
this.dataTexture = this.createTexture2D({
|
||||
flipY: true,
|
||||
data: [1],
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width: 1,
|
||||
height: 1,
|
||||
});
|
||||
}
|
||||
this.dataTexture =
|
||||
this.cellLength > 0
|
||||
? this.createTexture2D({
|
||||
flipY: true,
|
||||
data,
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
: this.defaultDataTexture;
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -220,9 +99,11 @@ export default class FillModel extends BaseModel {
|
|||
u_stroke_opacity: isNumber(strokeOpacity) ? strokeOpacity : 1.0,
|
||||
u_stroke_width: isNumber(strokeWidth) ? strokeWidth : 0.0,
|
||||
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)
|
||||
? [-offsets[0], offsets[1]]
|
||||
? (offsets as [number, number])
|
||||
: [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;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'shape',
|
||||
|
|
|
@ -4,10 +4,7 @@ attribute vec2 a_Extrude;
|
|||
attribute float a_Size;
|
||||
attribute float a_Shape;
|
||||
|
||||
attribute float a_vertexId;
|
||||
uniform mat4 u_cellTypeLayout;
|
||||
uniform sampler2D u_dataTexture;
|
||||
varying mat4 styleMappingMat;
|
||||
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
|
||||
|
||||
uniform mat4 u_ModelMatrix;
|
||||
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 vec2 u_offsets;
|
||||
|
||||
|
||||
#pragma include "styleMapping"
|
||||
#pragma include "projection"
|
||||
#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() {
|
||||
vec2 extrude = a_Extrude;
|
||||
float shape_type = a_Shape;
|
||||
|
|
|
@ -15,10 +15,6 @@ export function rgb2arr(str: string) {
|
|||
return arr;
|
||||
}
|
||||
|
||||
export function isColor(str: string) {
|
||||
return d3.color(str);
|
||||
}
|
||||
|
||||
export function decodePickingColor(color: Uint8Array): number {
|
||||
const i1 = color && color[0];
|
||||
const i2 = color && color[1];
|
||||
|
|
|
@ -17,7 +17,7 @@ export default class Amap2demo extends React.Component {
|
|||
center: [121.107846, 30.267069],
|
||||
pitch: 0,
|
||||
style: 'normal',
|
||||
zoom: 2,
|
||||
zoom: 20,
|
||||
animateEnable: false,
|
||||
}),
|
||||
});
|
||||
|
@ -26,7 +26,7 @@ export default class Amap2demo extends React.Component {
|
|||
lng: 121.107846,
|
||||
lat: 30.267069,
|
||||
opacity2: 0.2,
|
||||
strokeOpacity2: 0.2,
|
||||
strokeOpacity2: 0.4,
|
||||
strokeColor: '#000',
|
||||
strokeWidth: 0.5,
|
||||
// offsets2: [0, 0]
|
||||
|
@ -36,7 +36,7 @@ export default class Amap2demo extends React.Component {
|
|||
lng: 121.107,
|
||||
lat: 30.267069,
|
||||
opacity2: 0.4,
|
||||
strokeOpacity2: 0.4,
|
||||
strokeOpacity2: 0.6,
|
||||
strokeColor: '#0f0',
|
||||
strokeWidth: 2,
|
||||
offsets2: [100, 100],
|
||||
|
@ -45,7 +45,7 @@ export default class Amap2demo extends React.Component {
|
|||
lng: 121.107846,
|
||||
lat: 30.26718,
|
||||
opacity2: 0.6,
|
||||
strokeOpacity2: 0.6,
|
||||
strokeOpacity2: 0.8,
|
||||
strokeColor: '#f00',
|
||||
strokeWidth: 4,
|
||||
// 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';
|
||||
scene.on('loaded', () => {
|
||||
for (let i = 0; i < 1; i++) {
|
||||
fetch(thousandMhundred)
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
// console.log('data', data)
|
||||
// lng: Math.random() * 180, // 0 ~ 180
|
||||
// lat: Math.random() * 100 - 50, // -50 ~ 50
|
||||
// customOpacity: Math.random(),
|
||||
// customStroke: `rgb(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 1)`,
|
||||
// customStrokeOpacity: Math.random(),
|
||||
// customStrokeWidth: Math.random() * 5,
|
||||
let layer = new PointLayer()
|
||||
.source(JSON.parse(data), {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
.color('rgba(255, 0, 0, 1.0)')
|
||||
.size(10)
|
||||
.style({
|
||||
opacity: 'customOpacity',
|
||||
// strokeOpacity: 'customStrokeOpacity',
|
||||
// strokeWidth: 'customStrokeWidth',
|
||||
// stroke: 'customStroke',
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
});
|
||||
// let layer = new PointLayer()
|
||||
// .source(originData, {
|
||||
// parser: {
|
||||
// type: 'json',
|
||||
// x: 'lng',
|
||||
// y: 'lat',
|
||||
// },
|
||||
// })
|
||||
// .shape('circle')
|
||||
// // .shape('normal')
|
||||
// // .shape('fill')
|
||||
// // .color('rgba(255, 0, 0, 0.9)')
|
||||
// .color('rgba(255, 0, 0, 1.0)')
|
||||
// .size(10)
|
||||
// // .offsets('123')
|
||||
// .style({
|
||||
// // stroke: '#000',
|
||||
// // stroke: 'rgba(0, 255, 0, 1)',
|
||||
// stroke: 'strokeColor',
|
||||
// // stroke: ['strokeColor', (d: any) => {
|
||||
// // return d
|
||||
// // }],
|
||||
// // stroke: ['strokeColor', ["#f00", "#ff0"]],
|
||||
// fetch(thousandMhundred)
|
||||
// .then((res) => res.text())
|
||||
// .then((data) => {
|
||||
// // console.log('data', data)
|
||||
// // lng: Math.random() * 180, // 0 ~ 180
|
||||
// // lat: Math.random() * 100 - 50, // -50 ~ 50
|
||||
// // customOpacity: Math.random(),
|
||||
// // customStroke: `rgb(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 1)`,
|
||||
// // customStrokeOpacity: Math.random(),
|
||||
// // customStrokeWidth: Math.random() * 5,
|
||||
// let layer = new PointLayer()
|
||||
// .source(JSON.parse(data), {
|
||||
// parser: {
|
||||
// type: 'json',
|
||||
// x: 'lng',
|
||||
// y: 'lat',
|
||||
// },
|
||||
// })
|
||||
// .shape('circle')
|
||||
// .color('rgba(255, 0, 0, 1.0)')
|
||||
// .size(10)
|
||||
// .style({
|
||||
// opacity: 'customOpacity',
|
||||
// // strokeOpacity: 'customStrokeOpacity',
|
||||
// // strokeWidth: 'customStrokeWidth',
|
||||
// // stroke: 'customStroke',
|
||||
// });
|
||||
// scene.addLayer(layer);
|
||||
// });
|
||||
let layer = new PointLayer()
|
||||
.source(originData, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
// .shape('normal')
|
||||
// .shape('fill')
|
||||
// .color('rgba(255, 0, 0, 0.9)')
|
||||
.color('rgba(255, 0, 0, 1.0)')
|
||||
.size(10)
|
||||
// .offsets('123')
|
||||
.style({
|
||||
// stroke: '#000',
|
||||
// stroke: 'rgba(0, 255, 0, 1)',
|
||||
// stroke: 'strokeColor',
|
||||
// stroke: ['strokeColor', (d: any) => {
|
||||
// return d
|
||||
// }],
|
||||
// stroke: ['strokeColor', ["#f00", "#ff0"]],
|
||||
|
||||
// // strokeWidth: 4,
|
||||
// // strokeWidth: "strokeWidth",
|
||||
// // strokeWidth: ["strokeWidth", [1, 2]],
|
||||
// strokeWidth: ["strokeWidth", (d: any) => {
|
||||
// return d * 2
|
||||
// }],
|
||||
// strokeWidth: 4,
|
||||
// strokeWidth: "strokeWidth",
|
||||
// strokeWidth: ["strokeWidth", [1, 2]],
|
||||
// strokeWidth: ["strokeWidth", (d: any) => {
|
||||
// return d * 2
|
||||
// }],
|
||||
|
||||
// // strokeOpacity: 0.5,
|
||||
// // strokeOpacity: 'strokeOpacity2',
|
||||
// // strokeOpacity: 1.0,
|
||||
// // strokeOpacity: [
|
||||
// // 'strokeOpacity2',
|
||||
// // (d: any) => {
|
||||
// // // console.log('strokeOpacity2', d)
|
||||
// // return d*2;
|
||||
// // },
|
||||
// // ],
|
||||
// // strokeOpacity: ['opacity2', [0.2, 0.6]],
|
||||
// strokeOpacity: 0.5,
|
||||
strokeOpacity: 'strokeOpacity2',
|
||||
// strokeOpacity: 1.0,
|
||||
// strokeOpacity: [
|
||||
// 'strokeOpacity2',
|
||||
// (d: any) => {
|
||||
// // console.log('strokeOpacity2', d)
|
||||
// return d*2;
|
||||
// },
|
||||
// ],
|
||||
// strokeOpacity: ['opacity2', [0.2, 0.6]],
|
||||
|
||||
// // offsets: [100, 100],
|
||||
// offsets: 'offsets2',
|
||||
// // offsets: ['offsets2', (d: any) => d],
|
||||
// offsets: [100, 100],
|
||||
// offsets: 'offsets2',
|
||||
// offsets: ['offsets2', (d: any) => d],
|
||||
|
||||
// opacity: 'opacity2',
|
||||
// // opacity: 0.2
|
||||
// // opacity: 0,
|
||||
// // opacity: ['opacity2', (d: any) => {
|
||||
// // return d
|
||||
// // }]
|
||||
// // opacity: ['opacity2', [0.2, 0.6]],
|
||||
// })
|
||||
// .active(true);
|
||||
// scene.addLayer(layer);
|
||||
opacity: 'opacity2',
|
||||
// opacity: 0.2
|
||||
// opacity: 0,
|
||||
// opacity: ['opacity2', (d: any) => {
|
||||
// return d
|
||||
// }]
|
||||
// opacity: ['opacity2', [0.2, 0.6]],
|
||||
})
|
||||
.active(true);
|
||||
scene.addLayer(layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue