feat: 去除 style 更新时 options 的更新、earth 图层解耦 (#1232)

* feat: 在点图层中去除 global 的耦合

* style: lint style

* fix: 修复更新 style 的同时更新了 option 带来的问题

* style: lint style

* feat: 拆除 arc3d 地球模式和普通模式的耦合

* style: lint style
This commit is contained in:
YiQianYao 2022-07-14 14:47:52 +08:00 committed by GitHub
parent 0a9ad6c6f7
commit c2812205c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1247 additions and 184 deletions

View File

@ -246,9 +246,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
public updateLayerConfig(
configToUpdate: Partial<ILayerConfig | ChildLayerStyleOptions>,
) {
// 同步 options 记录
this.updateRawConfig(configToUpdate);
if (!this.inited) {
this.needUpdateConfig = {
...this.needUpdateConfig,
@ -638,12 +635,13 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
);
}
this.rawConfig = {
...this.rawConfig,
...rest,
};
// this.rawConfig = {
// ...this.rawConfig,
// ...rest,
// };
if (this.container) {
this.updateLayerConfig(this.rawConfig);
// this.updateLayerConfig(this.rawConfig);
this.updateLayerConfig(rest);
this.styleNeedUpdate = true;
}
@ -1315,18 +1313,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
return {};
}
private updateRawConfig(
configToUpdate: Partial<ILayerConfig | ChildLayerStyleOptions>,
) {
Object.keys(configToUpdate).map((key) => {
// @ts-ignore
if (this.rawConfig[key] && this.rawConfig[key] !== configToUpdate[key]) {
// @ts-ignore
this.rawConfig[key] = configToUpdate[key];
}
});
}
private sourceEvent = () => {
this.dataState.dataSourceNeedUpdate = true;
const { autoFit, fitBoundsOptions } = this.getLayerConfig();

View File

@ -39,10 +39,14 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
vectorline: {},
tileLine: {},
halfLine: {},
earthArc3d: {},
};
return defaultConfig[type];
}
protected getModelType(): LineModelType {
if (this.layerType) {
return this.layerType as LineModelType;
}
if (this.layerSource.parser.type === 'mvt') {
return 'vectorline';
}

View File

@ -0,0 +1,274 @@
import {
AttributeType,
gl,
IAnimateOption,
IEncodeFeature,
ILayerConfig,
IModel,
IModelUniform,
ITexture2D,
} from '@antv/l7-core';
import { getMask, rgb2arr } from '@antv/l7-utils';
import { isNumber } from 'lodash';
import BaseModel from '../../core/BaseModel';
import { ILineLayerStyleOptions } from '../../core/interface';
import { LineArcTriangulation } from '../../core/triangulation';
import { EARTH_RADIUS } from '../../earth/utils';
// arc3d line layer
import arc3d_line_frag from '../shaders/line_arc_3d_frag.glsl';
import arc3d_line_vert from '../shaders/line_arc_3d_vert.glsl';
// arc3d linear layer
import arc3d_linear_frag from '../shaders/linear/arc3d_linear_frag.glsl';
import arc3d_linear_vert from '../shaders/linear/arc3d_linear_vert.glsl';
const lineStyleObj: { [key: string]: number } = {
solid: 0.0,
dash: 1.0,
};
export default class Arc3DModel extends BaseModel {
protected texture: ITexture2D;
public getUninforms(): IModelUniform {
const {
opacity = 1,
sourceColor,
targetColor,
textureBlend = 'normal',
lineType = 'solid',
dashArray = [10, 5],
lineTexture = false,
iconStep = 100,
segmentNumber = 30,
globalArcHeight = 10,
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
if (dashArray.length === 2) {
dashArray.push(0, 0);
}
// 转化渐变色
let useLinearColor = 0; // 默认不生效
let sourceColorArr = [0, 0, 0, 0];
let targetColorArr = [0, 0, 0, 0];
if (sourceColor && targetColor) {
sourceColorArr = rgb2arr(sourceColor);
targetColorArr = rgb2arr(targetColor);
useLinearColor = 1;
}
if (this.rendererService.getDirty()) {
this.texture.bind();
}
if (this.dataTextureTest && this.dataTextureNeedUpdate({ opacity })) {
this.judgeStyleAttributes({ opacity });
const encodeData = this.layer.getEncodedData();
const { data, width, height } = this.calDataFrame(
this.cellLength,
encodeData,
this.cellProperties,
);
this.rowCount = height; // 当前数据纹理有多少行
this.dataTexture =
this.cellLength > 0 && data.length > 0
? this.createTexture2D({
flipY: true,
data,
format: gl.LUMINANCE,
type: gl.FLOAT,
width,
height,
})
: this.createTexture2D({
flipY: true,
data: [1],
format: gl.LUMINANCE,
type: gl.FLOAT,
width: 1,
height: 1,
});
}
return {
u_globel: this.mapService.version === 'GLOBEL' ? 1 : 0,
u_globel_radius: EARTH_RADIUS, // 地球半径
u_global_height: globalArcHeight,
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
u_cellTypeLayout: this.getCellTypeLayout(),
u_opacity: isNumber(opacity) ? opacity : 1.0,
u_textureBlend: textureBlend === 'normal' ? 0.0 : 1.0,
segmentNumber,
u_line_type: lineStyleObj[lineType as string] || 0.0,
u_dash_array: dashArray,
// 纹理支持参数
u_texture: this.texture, // 贴图
u_line_texture: lineTexture ? 1.0 : 0.0, // 传入线的标识
u_icon_step: iconStep,
u_textSize: [1024, this.iconService.canvasHeight || 128],
// 渐变色支持参数
u_linearColor: useLinearColor,
u_sourceColor: sourceColorArr,
u_targetColor: targetColorArr,
};
}
public getAnimateUniforms(): IModelUniform {
const { animateOption } = this.layer.getLayerConfig() as ILayerConfig;
return {
u_aimate: this.animateOption2Array(animateOption as IAnimateOption),
u_time: this.layer.getLayerAnimateTime(),
};
}
public initModels(): IModel[] {
this.updateTexture();
this.iconService.on('imageUpdate', this.updateTexture);
return this.buildModels();
}
public clearModels() {
this.texture?.destroy();
this.dataTexture?.destroy();
this.iconService.off('imageUpdate', this.updateTexture);
}
public getShaders(): { frag: string; vert: string; type: string } {
const {
sourceColor,
targetColor,
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
if (sourceColor && targetColor) {
// 分离 linear 功能
return {
frag: arc3d_linear_frag,
vert: arc3d_linear_vert,
type: 'linear',
};
} else {
return {
frag: arc3d_line_frag,
vert: arc3d_line_vert,
type: 'normal',
};
}
}
public buildModels(): IModel[] {
const {
segmentNumber = 30,
mask = false,
maskInside = true,
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
const { frag, vert, type } = this.getShaders();
return [
this.layer.buildLayerModel({
moduleName: 'arc3Dline' + type,
vertexShader: vert,
fragmentShader: frag,
triangulation: LineArcTriangulation,
blend: this.getBlend(),
segmentNumber,
// primitive: gl.POINTS,
stencil: getMask(mask, maskInside),
}),
];
}
protected registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'size',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Size',
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,
) => {
const { size = 1 } = feature;
return Array.isArray(size) ? [size[0]] : [size as number];
},
},
});
this.styleAttributeService.registerStyleAttribute({
name: 'instance', // 弧线起始点信息
type: AttributeType.Attribute,
descriptor: {
name: 'a_Instance',
buffer: {
usage: gl.STATIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 4,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
) => {
return [vertex[3], vertex[4], vertex[5], vertex[6]];
},
},
});
this.styleAttributeService.registerStyleAttribute({
name: 'uv',
type: AttributeType.Attribute,
descriptor: {
name: 'a_iconMapUV',
buffer: {
// give the WebGL driver a hint that this buffer may change
usage: gl.DYNAMIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 2,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
) => {
const iconMap = this.iconService.getIconMap();
const { texture } = feature;
const { x, y } = iconMap[texture as string] || { x: 0, y: 0 };
return [x, y];
},
},
});
}
private updateTexture = () => {
const { createTexture2D } = this.rendererService;
if (this.texture) {
this.texture.update({
data: this.iconService.getCanvas(),
});
this.layer.render();
return;
}
this.texture = createTexture2D({
data: this.iconService.getCanvas(),
mag: gl.NEAREST,
min: gl.NEAREST,
premultiplyAlpha: false,
width: 1024,
height: this.iconService.canvasHeight || 128,
});
};
}

View File

@ -2,6 +2,7 @@ import LineTileModel from '../../tile/models/tileModel';
import ArcModel from './arc';
import Arc3DModel from './arc_3d';
import ArcMiniModel from './arcmini';
import EarthArc3DModel from './earthArc_3d';
import GreatCircleModel from './great_circle';
import LineHalfModel from './half';
import LineModel from './line';
@ -21,7 +22,8 @@ export type LineModelType =
| 'halfLine'
| 'linearline'
| 'vectorline'
| 'tileLine';
| 'tileLine'
| 'earthArc3d';
const LineModels: { [key in LineModelType]: any } = {
arc: ArcModel,
@ -35,6 +37,7 @@ const LineModels: { [key in LineModelType]: any } = {
linearline: LinearLine,
vectorline: LineTileModel,
tileLine: TileLineModel,
earthArc3d: EarthArc3DModel,
};
export default LineModels;

View File

@ -68,6 +68,8 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
},
vectorpoint: {},
tile: {},
earthFill: {},
earthExtrude: {},
};
return defaultConfig[type];
}
@ -85,6 +87,8 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
'icon',
'vectorpoint',
'tile',
'earthFill',
'earthExtrude',
];
if (this.layerSource.parser.type === 'mvt') {
return 'vectorpoint';

View File

@ -0,0 +1,256 @@
import {
AttributeType,
gl,
IEncodeFeature,
ILayerConfig,
IModel,
} from '@antv/l7-core';
import { getCullFace, rgb2arr } from '@antv/l7-utils';
import { isNumber } from 'lodash';
import BaseModel from '../../core/BaseModel';
import { IPointLayerStyleOptions } from '../../core/interface';
import { PointExtrudeTriangulation } from '../../core/triangulation';
import { lglt2xyz } from '../../earth/utils';
import { calculateCentroid } from '../../utils/geo';
import pointExtrudeFrag from '../shaders/earth/extrude/extrude_frag.glsl';
import pointExtrudeVert from '../shaders/earth/extrude/extrude_vert.glsl';
export default class ExtrudeModel extends BaseModel {
private raiseCount: number = 0;
private raiserepeat: number = 0;
public getUninforms() {
const {
animateOption = {
enable: false,
speed: 0.01,
repeat: false,
},
opacity = 1,
sourceColor,
targetColor,
pickLight = false,
heightfixed = false,
opacityLinear = {
enable: false,
dir: 'up',
},
lightEnable = true,
} = this.layer.getLayerConfig() as Partial<
ILayerConfig & IPointLayerStyleOptions
>;
if (
this.dataTextureTest &&
this.dataTextureNeedUpdate({
opacity,
})
) {
this.judgeStyleAttributes({
opacity,
});
const encodeData = this.layer.getEncodedData();
const { data, width, height } = this.calDataFrame(
this.cellLength,
encodeData,
this.cellProperties,
);
this.rowCount = height; // 当前数据纹理有多少行
this.dataTexture =
this.cellLength > 0 && data.length > 0
? this.createTexture2D({
flipY: true,
data,
format: gl.LUMINANCE,
type: gl.FLOAT,
width,
height,
})
: this.createTexture2D({
flipY: true,
data: [1],
format: gl.LUMINANCE,
type: gl.FLOAT,
width: 1,
height: 1,
});
}
// 转化渐变色
let useLinearColor = 0; // 默认不生效
let sourceColorArr = [0, 0, 0, 0];
let targetColorArr = [0, 0, 0, 0];
if (sourceColor && targetColor) {
sourceColorArr = rgb2arr(sourceColor);
targetColorArr = rgb2arr(targetColor);
useLinearColor = 1;
}
if (this.raiseCount < 1 && this.raiserepeat > 0) {
if (animateOption.enable) {
const { speed = 0.01, repeat = false } = animateOption;
this.raiseCount += speed;
if (this.raiseCount >= 1) {
if (this.raiserepeat > 1) {
this.raiseCount = 0;
this.raiserepeat--;
} else {
this.raiseCount = 1;
}
}
}
}
return {
// 圆柱体的拾取高亮是否要计算光照
u_pickLight: Number(pickLight),
// 圆柱体是否固定高度
u_heightfixed: Number(heightfixed),
u_r: animateOption.enable && this.raiserepeat > 0 ? this.raiseCount : 1.0,
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
u_cellTypeLayout: this.getCellTypeLayout(),
u_opacity: isNumber(opacity) ? opacity : 1.0,
// 渐变色支持参数
u_linearColor: useLinearColor,
u_sourceColor: sourceColorArr,
u_targetColor: targetColorArr,
// 透明度渐变
u_opacitylinear: Number(opacityLinear.enable),
u_opacitylinear_dir: opacityLinear.dir === 'up' ? 1.0 : 0.0,
// 光照计算开关
u_lightEnable: Number(lightEnable),
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
// GAODE1.x GAODE2.x MAPBOX
const {
depth = true,
animateOption: { repeat = 1 },
} = this.layer.getLayerConfig() as ILayerConfig;
this.raiserepeat = repeat;
return [
this.layer.buildLayerModel({
moduleName: 'pointExtrude2',
vertexShader: pointExtrudeVert,
fragmentShader: pointExtrudeFrag,
triangulation: PointExtrudeTriangulation,
blend: this.getBlend(),
cull: {
enable: true,
face: getCullFace(this.mapService.version),
},
depth: {
enable: depth,
},
}),
];
}
public clearModels() {
this.dataTexture?.destroy();
}
protected registerBuiltinAttributes() {
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
const isGlobel = this.mapService.version === 'GLOBEL';
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'size',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Size',
buffer: {
// give the WebGL driver a hint that this buffer may change
usage: gl.DYNAMIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 3,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
) => {
const { size } = feature;
if (size) {
let buffersize: number[] = [];
if (Array.isArray(size)) {
buffersize =
size.length === 2 ? [size[0], size[0], size[1]] : size;
}
if (!Array.isArray(size)) {
buffersize = [size, size, size];
}
return buffersize;
} else {
return [2, 2, 2];
}
},
},
});
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'normal',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Normal',
buffer: {
// give the WebGL driver a hint that this buffer may change
usage: gl.STATIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 3,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
normal: number[],
) => {
return normal;
},
},
});
this.styleAttributeService.registerStyleAttribute({
name: 'pos',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Pos',
buffer: {
// give the WebGL driver a hint that this buffer may change
usage: gl.DYNAMIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 3,
update: (feature: IEncodeFeature, featureIdx: number) => {
const coordinates = calculateCentroid(feature.coordinates);
if (isGlobel) {
// TODO: 在地球模式下需要将传入 shader 的经纬度转化成对应的 xyz 坐标
return lglt2xyz([coordinates[0], coordinates[1]]) as [
number,
number,
number,
];
} else {
return [coordinates[0], coordinates[1], 0];
}
},
},
});
}
}

View File

@ -0,0 +1,252 @@
import {
AttributeType,
gl,
IAnimateOption,
IEncodeFeature,
ILayerConfig,
IModel,
IModelUniform,
} from '@antv/l7-core';
import { isNumber } from 'lodash';
import BaseModel from '../../core/BaseModel';
import { IPointLayerStyleOptions } from '../../core/interface';
import { GlobelPointFillTriangulation } from '../../core/triangulation';
import pointFillFrag from '../shaders/earth/fill_frag.glsl';
import pointFillVert from '../shaders/earth/fill_vert.glsl';
import { mat4, vec3 } from 'gl-matrix';
export default class FillModel extends BaseModel {
public getUninforms(): IModelUniform {
const {
opacity = 1,
strokeOpacity = 1,
strokeWidth = 0,
stroke = 'rgba(0,0,0,0)',
offsets = [0, 0],
blend,
blur = 0,
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
if (
this.dataTextureTest &&
this.dataTextureNeedUpdate({
opacity,
strokeOpacity,
strokeWidth,
stroke,
offsets,
})
) {
// 判断当前的样式中哪些是需要进行数据映射的,哪些是常量,同时计算用于构建数据纹理的一些中间变量
this.judgeStyleAttributes({
opacity,
strokeOpacity,
strokeWidth,
stroke,
offsets,
});
const encodeData = this.layer.getEncodedData();
const { data, width, height } = this.calDataFrame(
this.cellLength,
encodeData,
this.cellProperties,
);
this.rowCount = height; // 当前数据纹理有多少行
this.dataTexture =
this.cellLength > 0 && data.length > 0
? this.createTexture2D({
flipY: true,
data,
format: gl.LUMINANCE,
type: gl.FLOAT,
width,
height,
})
: this.createTexture2D({
flipY: true,
data: [1],
format: gl.LUMINANCE,
type: gl.FLOAT,
width: 1,
height: 1,
});
}
return {
u_blur: blur,
u_additive: blend === 'additive' ? 1.0 : 0.0,
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
u_cellTypeLayout: this.getCellTypeLayout(),
u_opacity: isNumber(opacity) ? opacity : 1.0,
u_stroke_opacity: isNumber(strokeOpacity) ? strokeOpacity : 1.0,
u_stroke_width: isNumber(strokeWidth) ? strokeWidth : 1.0,
u_stroke_color: this.getStrokeColor(stroke),
u_offsets: this.isOffsetStatic(offsets)
? (offsets as [number, number])
: [0, 0],
};
}
public getAnimateUniforms(): IModelUniform {
const {
animateOption = { enable: false },
} = this.layer.getLayerConfig() as ILayerConfig;
return {
u_aimate: this.animateOption2Array(animateOption),
u_time: this.layer.getLayerAnimateTime(),
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
const { frag, vert, type } = this.getShaders();
this.layer.triangulation = GlobelPointFillTriangulation;
return [
this.layer.buildLayerModel({
moduleName: 'pointfill_' + type,
vertexShader: vert,
fragmentShader: frag,
triangulation: GlobelPointFillTriangulation,
depth: { enable: true },
blend: this.getBlend(),
}),
];
}
/**
* animateOption shader
* @returns
*/
public getShaders(): { frag: string; vert: string; type: string } {
return {
frag: pointFillFrag,
vert: pointFillVert,
type: 'point_earth_fill',
};
}
public clearModels() {
this.dataTexture?.destroy();
}
// overwrite baseModel func
protected animateOption2Array(option: Partial<IAnimateOption>): number[] {
return [option.enable ? 0 : 1.0, option.speed || 1, option.rings || 3, 0];
}
protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({
name: 'extrude',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Extrude',
buffer: {
// give the WebGL driver a hint that this buffer may change
usage: gl.DYNAMIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 3,
update: (
feature: IEncodeFeature,
featureIdx: number,
vertex: number[],
attributeIdx: number,
) => {
const [x, y, z] = vertex;
const n1 = vec3.fromValues(0, 0, 1);
const n2 = vec3.fromValues(x, 0, z);
const xzReg =
x >= 0 ? vec3.angle(n1, n2) : Math.PI * 2 - vec3.angle(n1, n2);
const yReg = Math.PI * 2 - Math.asin(y / 100);
const m = mat4.create();
mat4.rotateY(m, m, xzReg);
mat4.rotateX(m, m, yReg);
const v1 = vec3.fromValues(1, 1, 0);
vec3.transformMat4(v1, v1, m);
vec3.normalize(v1, v1);
const v2 = vec3.fromValues(-1, 1, 0);
vec3.transformMat4(v2, v2, m);
vec3.normalize(v2, v2);
const v3 = vec3.fromValues(-1, -1, 0);
vec3.transformMat4(v3, v3, m);
vec3.normalize(v3, v3);
const v4 = vec3.fromValues(1, -1, 0);
vec3.transformMat4(v4, v4, m);
vec3.normalize(v4, v4);
const extrude = [...v1, ...v2, ...v3, ...v4];
const extrudeIndex = (attributeIdx % 4) * 3;
return [
extrude[extrudeIndex],
extrude[extrudeIndex + 1],
extrude[extrudeIndex + 2],
];
},
},
});
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'size',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Size',
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,
) => {
const { size = 5 } = feature;
return Array.isArray(size) ? [size[0]] : [size as number];
},
},
});
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'shape',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Shape',
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,
) => {
const { shape = 2 } = feature;
const shape2d = this.layer.getLayerConfig().shape2d as string[];
const shapeIndex = shape2d.indexOf(shape as string);
return [shapeIndex];
},
},
});
}
}

View File

@ -111,8 +111,6 @@ export default class ExtrudeModel extends BaseModel {
u_heightfixed: Number(heightfixed),
u_r: animateOption.enable && this.raiserepeat > 0 ? this.raiseCount : 1.0,
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
u_globel: this.mapService.version === 'GLOBEL' ? 1 : 0,
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
u_cellTypeLayout: this.getCellTypeLayout(),

View File

@ -9,14 +9,11 @@ import {
IModel,
IModelUniform,
} from '@antv/l7-core';
import { $window, getCullFace, getMask } from '@antv/l7-utils';
import { $window, getMask } from '@antv/l7-utils';
import { isNumber } from 'lodash';
import BaseModel from '../../core/BaseModel';
import { IPointLayerStyleOptions } from '../../core/interface';
import {
GlobelPointFillTriangulation,
PointFillTriangulation,
} from '../../core/triangulation';
import { PointFillTriangulation } from '../../core/triangulation';
// animate pointLayer shader - support animate
import waveFillFrag from '../shaders/animate/wave_frag.glsl';
// static pointLayer shader - not support animate
@ -24,7 +21,6 @@ import pointFillFrag from '../shaders/fill_frag.glsl';
import pointFillVert from '../shaders/fill_vert.glsl';
import { Version } from '@antv/l7-maps';
import { mat4, vec3 } from 'gl-matrix';
export default class FillModel extends BaseModel {
private meter2coord: number = 1;
private meteryScale: number = 1; // 兼容 mapbox
@ -100,7 +96,6 @@ export default class FillModel extends BaseModel {
u_blur: blur,
u_additive: blend === 'additive' ? 1.0 : 0.0,
u_globel: this.mapService.version === Version.GLOBEL ? 1 : 0,
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
u_cellTypeLayout: this.getCellTypeLayout(),
@ -201,20 +196,14 @@ export default class FillModel extends BaseModel {
>;
const { frag, vert, type } = this.getShaders(animateOption);
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
const isGlobel = this.mapService.version === 'GLOBEL';
this.layer.triangulation = isGlobel
? GlobelPointFillTriangulation
: PointFillTriangulation;
this.layer.triangulation = PointFillTriangulation;
return [
this.layer.buildLayerModel({
moduleName: 'pointfill_' + type,
vertexShader: vert,
fragmentShader: frag,
triangulation: isGlobel
? GlobelPointFillTriangulation
: PointFillTriangulation,
depth: { enable: isGlobel },
triangulation: PointFillTriangulation,
depth: { enable: false },
blend: this.getBlend(),
stencil: getMask(mask, maskInside),
}),
@ -261,9 +250,6 @@ export default class FillModel extends BaseModel {
return [option.enable ? 0 : 1.0, option.speed || 1, option.rings || 3, 0];
}
protected registerBuiltinAttributes() {
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
const isGlobel = this.mapService.version === 'GLOBEL';
this.styleAttributeService.registerStyleAttribute({
name: 'extrude',
type: AttributeType.Attribute,
@ -282,44 +268,7 @@ export default class FillModel extends BaseModel {
vertex: number[],
attributeIdx: number,
) => {
let extrude;
// 地球模式
if (isGlobel) {
const [x, y, z] = vertex;
const n1 = vec3.fromValues(0, 0, 1);
const n2 = vec3.fromValues(x, 0, z);
const xzReg =
x >= 0 ? vec3.angle(n1, n2) : Math.PI * 2 - vec3.angle(n1, n2);
const yReg = Math.PI * 2 - Math.asin(y / 100);
const m = mat4.create();
mat4.rotateY(m, m, xzReg);
mat4.rotateX(m, m, yReg);
const v1 = vec3.fromValues(1, 1, 0);
vec3.transformMat4(v1, v1, m);
vec3.normalize(v1, v1);
const v2 = vec3.fromValues(-1, 1, 0);
vec3.transformMat4(v2, v2, m);
vec3.normalize(v2, v2);
const v3 = vec3.fromValues(-1, -1, 0);
vec3.transformMat4(v3, v3, m);
vec3.normalize(v3, v3);
const v4 = vec3.fromValues(1, -1, 0);
vec3.transformMat4(v4, v4, m);
vec3.normalize(v4, v4);
extrude = [...v1, ...v2, ...v3, ...v4];
} else {
// 平面模式
extrude = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0];
}
const extrude = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0];
const extrudeIndex = (attributeIdx % 4) * 3;
return [
extrude[extrudeIndex],

View File

@ -1,4 +1,7 @@
import PointTileModel from '../../tile/models/tileModel';
import EarthExtrudeModel from './earthExtrude';
// earth
import EarthFillModel from './earthFill';
import ExtrudeModel from './extrude';
import FillModel from './fill';
import FillImageModel from './fillmage';
@ -21,7 +24,9 @@ export type PointType =
| 'text'
| 'icon'
| 'vectorpoint'
| 'tile';
| 'tile'
| 'earthFill'
| 'earthExtrude';
const PointModels: { [key in PointType]: any } = {
fillImage: FillImageModel,
@ -35,6 +40,8 @@ const PointModels: { [key in PointType]: any } = {
icon: IconModel,
vectorpoint: PointTileModel,
tile: TileFillModel,
earthFill: EarthFillModel,
earthExtrude: EarthExtrudeModel,
};
export default PointModels;

View File

@ -0,0 +1,44 @@
varying vec4 v_color;
uniform float u_opacity: 1.0;
uniform float u_pickLight: 0.0;
#pragma include "picking"
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
uniform float u_linearColor: 0;
uniform vec4 u_sourceColor;
uniform vec4 u_targetColor;
uniform float u_opacitylinear: 0.0;
uniform float u_opacitylinear_dir: 1.0;
void main() {
float opacity = styleMappingMat[0][0];
float lightWeight = styleMappingMat[1][3];
float barLinearZ = styleMappingMat[2][3];
// 设置圆柱的底色
if(u_linearColor == 1.0) { // 使用渐变颜色
gl_FragColor = mix(u_sourceColor, u_targetColor, barLinearZ);
gl_FragColor.rgb *= lightWeight;
} else { // 使用 color 方法传入的颜色
gl_FragColor = v_color;
}
// 应用透明度
gl_FragColor.a *= opacity;
// 开启透明度渐变
if(u_opacitylinear > 0.0) {
gl_FragColor.a *= u_opacitylinear_dir > 0.0 ? (1.0 - barLinearZ): barLinearZ;
}
// picking
if(u_pickLight > 0.0) {
gl_FragColor = filterColorAlpha(gl_FragColor, lightWeight);
} else {
gl_FragColor = filterColor(gl_FragColor);
}
}

View File

@ -0,0 +1,140 @@
precision highp float;
#define pi 3.1415926535
#define ambientRatio 0.5
#define diffuseRatio 0.3
#define specularRatio 0.2
attribute vec3 a_Position;
attribute vec3 a_Pos;
attribute vec4 a_Color;
attribute vec3 a_Size;
attribute vec3 a_Normal;
uniform float u_heightfixed: 0.0; // 默认不固定
uniform float u_globel;
uniform float u_r;
uniform mat4 u_ModelMatrix;
uniform mat4 u_Mvp;
varying vec4 v_color;
uniform float u_opacity : 1;
uniform float u_lightEnable: 1;
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
#pragma include "styleMapping"
#pragma include "styleMappingCalOpacity"
#pragma include "projection"
#pragma include "light"
#pragma include "picking"
float getYRadian(float x, float z) {
if(x > 0.0 && z > 0.0) {
return atan(x/z);
} else if(x > 0.0 && z <= 0.0){
return atan(-z/x) + pi/2.0;
} else if(x <= 0.0 && z <= 0.0) {
return pi + atan(x/z); //atan(x/z) +
} else {
return atan(z/-x) + pi*3.0/2.0;
}
}
float getXRadian(float y, float r) {
return atan(y/r);
}
void main() {
// cal style mapping - 数据纹理映射部分的计算
styleMappingMat = mat4(
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA - lightWeight
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1] - linearZ(垂直方向 0 - 1 的值)
0.0, 0.0, 0.0, 0.0
);
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
float columnCount = u_cellTypeLayout[0][1]; // 当看到数据纹理有几列
float columnWidth = 1.0/columnCount; // 列宽
float rowHeight = 1.0/rowCount; // 行高
float cellCount = calCellCount(); // opacity - strokeOpacity - strokeWidth - stroke - offsets
float id = a_vertexId; // 第n个顶点
float cellCurrentRow = floor(id * cellCount / columnCount) + 1.0; // 起始点在第几行
float cellCurrentColumn = mod(id * cellCount, columnCount) + 1.0; // 起始点在第几列
// cell 固定顺序 opacity -> strokeOpacity -> strokeWidth -> stroke ...
// 按顺序从 cell 中取值、若没有则自动往下取值
float textureOffset = 0.0; // 在 cell 中取值的偏移量
vec2 opacityAndOffset = calOpacityAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
styleMappingMat[0][0] = opacityAndOffset.r;
textureOffset = opacityAndOffset.g;
// cal style mapping - 数据纹理映射部分的计算
vec3 size = a_Size * a_Position;
// a_Position.z 是在构建网格的时候传入的标准值 0 - 1在插值器插值可以获取 01 线性渐变的值
styleMappingMat[2][3] = a_Position.z;
vec3 offset = size; // 控制圆柱体的大小 - 从标准单位圆柱体进行偏移
if(u_heightfixed < 1.0) { // 圆柱体不固定高度
if (u_CoordinateSystem == COORDINATE_SYSTEM_P20 || u_CoordinateSystem == COORDINATE_SYSTEM_P20_OFFSET) {
// P20 坐标系下,为了和 Web 墨卡托坐标系统一zoom 默认减1
offset = offset * pow(2.0, (19.0 - u_Zoom));
}
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) {
// P20_2 坐标系下,为了和 Web 墨卡托坐标系统一zoom 默认减3
offset = offset * pow(2.0, (19.0 - 3.0 - u_Zoom));
}
} else {// 圆柱体固定高度 处理 mapbox
if(u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT || u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) {
offset *= 4.0/pow(2.0, 21.0 - u_Zoom);
}
}
vec4 project_pos = project_position(vec4(a_Pos.xy, 0., 1.0));
// u_r 控制圆柱的生长
vec4 pos = vec4(project_pos.xy + offset.xy, offset.z * u_r, 1.0);
// 圆柱光照效果
float lightWeight = 1.0;
if(u_lightEnable > 0.0) { // 取消三元表达式,增强健壮性
lightWeight = calc_lighting(pos);
}
styleMappingMat[1][3] = lightWeight;
v_color =vec4(a_Color.rgb * lightWeight, a_Color.w);
// 在地球模式下,将原本垂直于 xy 平面的圆柱调整姿态到适应圆的角度
//旋转矩阵mx创建绕x轴旋转矩阵
float r = sqrt(a_Pos.z*a_Pos.z + a_Pos.x*a_Pos.x);
float xRadian = getXRadian(a_Pos.y, r);
float xcos = cos(xRadian);//求解旋转角度余弦值
float xsin = sin(xRadian);//求解旋转角度正弦值
mat4 mx = mat4(
1,0,0,0,
0,xcos,-xsin,0,
0,xsin,xcos,0,
0,0,0,1);
//旋转矩阵my创建绕y轴旋转矩阵
float yRadian = getYRadian(a_Pos.x, a_Pos.z);
float ycos = cos(yRadian);//求解旋转角度余弦值
float ysin = sin(yRadian);//求解旋转角度正弦值
mat4 my = mat4(
ycos,0,-ysin,0,
0,1,0,0,
ysin,0,ycos,0,
0,0,0,1);
gl_Position = u_ViewProjectionMatrix * vec4(( my * mx * vec4(a_Position * a_Size, 1.0)).xyz + a_Pos, 1.0);
setPickingColor(a_PickingColor);
}

View File

@ -0,0 +1,86 @@
uniform float u_additive;
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
varying vec4 v_data;
varying vec4 v_color;
varying float v_radius;
#pragma include "sdf_2d"
#pragma include "picking"
void main() {
int shape = int(floor(v_data.w + 0.5));
vec4 textrueStroke = vec4(
styleMappingMat[1][0],
styleMappingMat[1][1],
styleMappingMat[1][2],
styleMappingMat[1][3]
);
float opacity = styleMappingMat[0][0];
float stroke_opacity = styleMappingMat[0][1];
float strokeWidth = styleMappingMat[0][2];
vec4 strokeColor = textrueStroke == vec4(0) ? v_color : textrueStroke;
lowp float antialiasblur = v_data.z;
float r = v_radius / (v_radius + strokeWidth);
float outer_df;
float inner_df;
// 'circle', 'triangle', 'square', 'pentagon', 'hexagon', 'octogon', 'hexagram', 'rhombus', 'vesica'
if (shape == 0) {
outer_df = sdCircle(v_data.xy, 1.0);
inner_df = sdCircle(v_data.xy, r);
} else if (shape == 1) {
outer_df = sdEquilateralTriangle(1.1 * v_data.xy);
inner_df = sdEquilateralTriangle(1.1 / r * v_data.xy);
} else if (shape == 2) {
outer_df = sdBox(v_data.xy, vec2(1.));
inner_df = sdBox(v_data.xy, vec2(r));
} else if (shape == 3) {
outer_df = sdPentagon(v_data.xy, 0.8);
inner_df = sdPentagon(v_data.xy, r * 0.8);
} else if (shape == 4) {
outer_df = sdHexagon(v_data.xy, 0.8);
inner_df = sdHexagon(v_data.xy, r * 0.8);
} else if (shape == 5) {
outer_df = sdOctogon(v_data.xy, 1.0);
inner_df = sdOctogon(v_data.xy, r);
} else if (shape == 6) {
outer_df = sdHexagram(v_data.xy, 0.52);
inner_df = sdHexagram(v_data.xy, r * 0.52);
} else if (shape == 7) {
outer_df = sdRhombus(v_data.xy, vec2(1.0));
inner_df = sdRhombus(v_data.xy, vec2(r));
} else if (shape == 8) {
outer_df = sdVesica(v_data.xy, 1.1, 0.8);
inner_df = sdVesica(v_data.xy, r * 1.1, r * 0.8);
}
if(outer_df > antialiasblur + 0.018) discard;
float opacity_t = smoothstep(0.0, antialiasblur, outer_df);
float color_t = strokeWidth < 0.01 ? 0.0 : smoothstep(
antialiasblur,
0.0,
inner_df
);
if(strokeWidth < 0.01) {
gl_FragColor = vec4(v_color.rgb, v_color.a * opacity);
} else {
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * opacity), strokeColor * stroke_opacity, color_t);
}
if(u_additive > 0.0) {
gl_FragColor *= opacity_t;
gl_FragColor = filterColorAlpha(gl_FragColor, gl_FragColor.a);
} else {
gl_FragColor.a *= opacity_t;
gl_FragColor = filterColor(gl_FragColor);
}
}

View File

@ -0,0 +1,126 @@
attribute vec4 a_Color;
attribute vec3 a_Position;
attribute vec3 a_Extrude;
attribute float a_Size;
attribute float a_Shape;
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
uniform mat4 u_ModelMatrix;
uniform mat4 u_Mvp;
varying vec4 v_data;
varying vec4 v_color;
varying float v_radius;
uniform float u_opacity : 1;
uniform float u_stroke_opacity : 1;
uniform float u_stroke_width : 2;
uniform vec4 u_stroke_color : [0.0, 0.0, 0.0, 0.0];
uniform vec2 u_offsets;
uniform float u_blur : 0.0;
#pragma include "styleMapping"
#pragma include "styleMappingCalOpacity"
#pragma include "styleMappingCalStrokeOpacity"
#pragma include "styleMappingCalStrokeWidth"
#pragma include "projection"
#pragma include "picking"
void main() {
vec3 extrude = a_Extrude;
float shape_type = a_Shape;
/*
* setPickingSize 设置拾取大小
*/
float newSize = setPickingSize(a_Size);
// float newSize = setPickingSize(a_Size) * 0.00001038445708445579;
// cal style mapping - 数据纹理映射部分的计算
styleMappingMat = mat4(
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1]
0.0, 0.0, 0.0, 0.0
);
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
float columnCount = u_cellTypeLayout[0][1]; // 当看到数据纹理有几列
float columnWidth = 1.0/columnCount; // 列宽
float rowHeight = 1.0/rowCount; // 行高
float cellCount = calCellCount(); // opacity - strokeOpacity - strokeWidth - stroke - offsets
float id = a_vertexId; // 第n个顶点
float cellCurrentRow = floor(id * cellCount / columnCount) + 1.0; // 起始点在第几行
float cellCurrentColumn = mod(id * cellCount, columnCount) + 1.0; // 起始点在第几列
// cell 固定顺序 opacity -> strokeOpacity -> strokeWidth -> stroke ...
// 按顺序从 cell 中取值、若没有则自动往下取值
float textureOffset = 0.0; // 在 cell 中取值的偏移量
vec2 opacityAndOffset = calOpacityAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
styleMappingMat[0][0] = opacityAndOffset.r;
textureOffset = opacityAndOffset.g;
vec2 strokeOpacityAndOffset = calStrokeOpacityAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
styleMappingMat[0][1] = strokeOpacityAndOffset.r;
textureOffset = strokeOpacityAndOffset.g;
vec2 strokeWidthAndOffset = calStrokeWidthAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
styleMappingMat[0][2] = strokeWidthAndOffset.r;
textureOffset = strokeWidthAndOffset.g;
vec4 textrueStroke = vec4(-1.0, -1.0, -1.0, -1.0);
if(hasStroke()) {
vec2 valueRPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
styleMappingMat[1][0] = pos2value(valueRPos, columnWidth, rowHeight); // R
textureOffset += 1.0;
vec2 valueGPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
styleMappingMat[1][1] = pos2value(valueGPos, columnWidth, rowHeight); // G
textureOffset += 1.0;
vec2 valueBPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
styleMappingMat[1][2] = pos2value(valueBPos, columnWidth, rowHeight); // B
textureOffset += 1.0;
vec2 valueAPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
styleMappingMat[1][3] = pos2value(valueAPos, columnWidth, rowHeight); // A
textureOffset += 1.0;
} else {
if(u_stroke_color == vec4(0.0)) {
styleMappingMat[1][0] = v_color.r;
styleMappingMat[1][1] = v_color.g;
styleMappingMat[1][2] = v_color.b;
styleMappingMat[1][3] = v_color.a;
} else {
styleMappingMat[1][0] = u_stroke_color.r;
styleMappingMat[1][1] = u_stroke_color.g;
styleMappingMat[1][2] = u_stroke_color.b;
styleMappingMat[1][3] = u_stroke_color.a;
}
}
// cal style mapping
// unpack color(vec2)
v_color = a_Color;
// radius(16-bit)
v_radius = newSize;
// TODO: billboard
// anti-alias
// float antialiased_blur = -max(u_blur, antialiasblur);
float antialiasblur = -max(2.0 / u_DevicePixelRatio / newSize, u_blur);
// TODP: /abs(extrude.x) 是为了兼容地球模式
v_data = vec4(extrude.x/abs(extrude.x), extrude.y/abs(extrude.y), antialiasblur,shape_type);
gl_Position = u_ViewProjectionMatrix * vec4(a_Position + extrude * newSize * 0.1, 1.0);
setPickingColor(a_PickingColor);
}

View File

@ -12,7 +12,6 @@ attribute vec3 a_Size;
attribute vec3 a_Normal;
uniform float u_heightfixed: 0.0; // 默认不固定
uniform float u_globel;
uniform float u_r;
uniform mat4 u_ModelMatrix;
uniform mat4 u_Mvp;
@ -118,31 +117,5 @@ void main() {
gl_Position = project_common_position_to_clipspace(pos);
}
if(u_globel > 0.0) {
// 在地球模式下,将原本垂直于 xy 平面的圆柱调整姿态到适应圆的角度
//旋转矩阵mx创建绕x轴旋转矩阵
float r = sqrt(a_Pos.z*a_Pos.z + a_Pos.x*a_Pos.x);
float xRadian = getXRadian(a_Pos.y, r);
float xcos = cos(xRadian);//求解旋转角度余弦值
float xsin = sin(xRadian);//求解旋转角度正弦值
mat4 mx = mat4(
1,0,0,0,
0,xcos,-xsin,0,
0,xsin,xcos,0,
0,0,0,1);
//旋转矩阵my创建绕y轴旋转矩阵
float yRadian = getYRadian(a_Pos.x, a_Pos.z);
float ycos = cos(yRadian);//求解旋转角度余弦值
float ysin = sin(yRadian);//求解旋转角度正弦值
mat4 my = mat4(
ycos,0,-ysin,0,
0,1,0,0,
ysin,0,ycos,0,
0,0,0,1);
gl_Position = u_ViewProjectionMatrix * vec4(( my * mx * vec4(a_Position * a_Size, 1.0)).xyz + a_Pos, 1.0);
}
setPickingColor(a_PickingColor);
}

View File

@ -1,5 +1,3 @@
uniform float u_globel;
uniform float u_additive;
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
@ -62,11 +60,6 @@ void main() {
inner_df = sdVesica(v_data.xy, r * 1.1, r * 0.8);
}
if(u_globel > 0.0) {
// TODO: 地球模式下避免多余片元绘制,同时也能避免有用片元在透明且重叠的情况下无法写入
// 付出的代价是边缘会有一些锯齿
if(outer_df > antialiasblur + 0.018) discard;
}
float opacity_t = smoothstep(0.0, antialiasblur, outer_df);
float color_t = strokeWidth < 0.01 ? 0.0 : smoothstep(

View File

@ -6,7 +6,6 @@ attribute float a_Shape;
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
uniform float u_globel;
uniform mat4 u_ModelMatrix;
uniform mat4 u_Mvp;
uniform float u_meter2coord;
@ -177,10 +176,6 @@ void main() {
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, u_raisingHeight, 1.0));
}
if(u_globel > 0.0) {
gl_Position = u_ViewProjectionMatrix * vec4(a_Position + extrude * newSize * 0.1, 1.0);
}
// gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, 0.0, 1.0));
setPickingColor(a_PickingColor);

View File

@ -37,71 +37,39 @@ export default class Amap2demo extends React.Component {
this.scene = scene;
const layer = new LineLayer()
.source({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
color: '#0f0',
},
geometry: {
type: 'LineString',
coordinates: [
[120, 40],
[100, 30],
[110, 20],
],
},
},
{
type: 'Feature',
properties: {
color: '#f00',
},
geometry: {
type: 'LineString',
coordinates: [
[130, 30],
[100, 20],
],
},
},
{
type: 'Feature',
properties: {
color: '#ff0',
},
geometry: {
type: 'LineString',
coordinates: [
[100, 20],
[130, 30],
],
},
},
],
const layer = new PointLayer({
visible: false,
})
.shape('halfLine')
.size(20)
.color('color')
.active(true)
.style({
// opacity: 0.3,
sourceColor: '#f00',
targetColor: '#ff0',
arrow: {
enable: true,
arrowWidth: 2,
// arrowHeight: 3,
// tailWidth: 0,
.source(
[
{
lng: 120,
lat: 30,
},
});
],
{
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
},
)
.shape('circle')
.size(10)
.color('#f00');
scene.on('loaded', () => {
scene.addLayer(layer);
// console.log(scene.getMapService().lngLatToMercator([100, 30], 0))
setTimeout(() => {
layer.show();
layer.style({
opacity: 1,
});
console.log(layer.isVisible());
}, 3000);
});
}

View File

@ -277,7 +277,9 @@ export default class ScaleComponent extends React.Component {
{ lng: 127.657407, lat: 49.76027 },
];
let pointlayer = new PointLayer()
// let pointlayer = new PointLayer({ layerType: 'earthFill' })
// let pointlayer = new PointLayer({ })
let pointlayer = new PointLayer({ layerType: 'earthExtrude' })
.source(
d,
// [
@ -374,11 +376,11 @@ export default class ScaleComponent extends React.Component {
},
},
)
.shape('circle')
// .shape('cylinder')
// .shape('circle')
.shape('cylinder')
.color('#f00')
// .size('', () => [1, 1, 10])
.size(20)
.size('', () => [1, 1, 10])
// .size(20)
.style({
// opacity: 0.6,
})

View File

@ -36,7 +36,10 @@ export default class ScaleComponent extends React.Component {
});
return { coord: [latlng1, latlng2] };
});
const flyLine = new LineLayer({ blend: 'normal' })
const flyLine = new LineLayer({
blend: 'normal',
layerType: 'earthArc3d',
})
.source(flydata, {
parser: {
type: 'json',