mirror of https://gitee.com/antv-l7/antv-l7
commit
d49ba3ee42
|
@ -1,10 +1,10 @@
|
|||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- '8'
|
||||
- '12'
|
||||
branches:
|
||||
only:
|
||||
- next
|
||||
script:
|
||||
- yarn test
|
||||
- yarn coveralls
|
||||
- yarn coveralls
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -115,5 +115,8 @@
|
|||
"commitizen": {
|
||||
"path": "cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"geotiff": "^1.0.0-beta.6"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
} from '../renderer/IAttribute';
|
||||
import { IBufferInitializationOptions } from '../renderer/IBuffer';
|
||||
import { IElements } from '../renderer/IElements';
|
||||
import { IParseDataItem, IParserData } from '../source/ISourceService';
|
||||
import { ILayer } from './ILayerService';
|
||||
|
||||
/**
|
||||
|
@ -64,6 +65,7 @@ export interface IEncodeFeature {
|
|||
pattern?: string;
|
||||
id?: number;
|
||||
coordinates: Position | Position[] | Position[][];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface IVertexAttributeDescriptor
|
||||
|
|
|
@ -4,6 +4,7 @@ import { gl } from '../renderer/gl';
|
|||
import { IAttribute } from '../renderer/IAttribute';
|
||||
import { IElements } from '../renderer/IElements';
|
||||
import { IRendererService } from '../renderer/IRendererService';
|
||||
import { IParseDataItem } from '../source/ISourceService'
|
||||
import { ILayer } from './ILayerService';
|
||||
import {
|
||||
IEncodeFeature,
|
||||
|
|
|
@ -39,7 +39,8 @@ export interface ITexture2DInitializationOptions {
|
|||
| number[][]
|
||||
| Uint8Array
|
||||
| Uint16Array
|
||||
| Uint32Array;
|
||||
| Uint32Array
|
||||
| Uint8ClampedArray;
|
||||
|
||||
/**
|
||||
* 纹理参数
|
||||
|
|
|
@ -48,3 +48,16 @@ export type IJsonData = IJsonItem[];
|
|||
export interface ISource {
|
||||
data: IParserData;
|
||||
}
|
||||
export interface IRasterCfg {
|
||||
extent: [number, number, number, number];
|
||||
width: number;
|
||||
height: number;
|
||||
max: number;
|
||||
min: number;
|
||||
}
|
||||
|
||||
export interface IRasterParserDataItem extends IParseDataItem {
|
||||
data: number[];
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
|
|
@ -22,9 +22,10 @@
|
|||
"@l7/core": "^0.0.1",
|
||||
"@l7/source": "^0.0.1",
|
||||
"@l7/utils": "^0.0.1",
|
||||
"@mapbox/martini": "^0.1.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"@turf/meta": "^6.0.2",
|
||||
"@types/d3-color": "^1.2.2",
|
||||
"inversify": "^5.0.1",
|
||||
"d3-array": "^2.3.1",
|
||||
"d3-color": "^1.4.0",
|
||||
"d3-scale": "^3.1.0",
|
||||
|
@ -32,6 +33,7 @@
|
|||
"eventemitter3": "^3.1.0",
|
||||
"gl-matrix": "^3.1.0",
|
||||
"gl-vec2": "^1.3.0",
|
||||
"inversify": "^5.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"merge-json-schemas": "1.0.0",
|
||||
"polyline-miter-util": "^1.0.1",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
ICameraService,
|
||||
IEncodeFeature,
|
||||
IFontService,
|
||||
IGlobalConfigService,
|
||||
|
@ -106,6 +107,12 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {
|
|||
@lazyInject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
@lazyInject(TYPES.IShaderModuleService)
|
||||
protected readonly shaderModuleService: IShaderModuleService;
|
||||
|
||||
@lazyInject(TYPES.IMapService)
|
||||
protected readonly map: IMapService;
|
||||
|
||||
private encodedData: IEncodeFeature[];
|
||||
|
||||
private configSchema: object;
|
||||
|
@ -117,12 +124,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {
|
|||
ILayerInitializationOptions & ChildLayerStyleOptions
|
||||
>;
|
||||
|
||||
@lazyInject(TYPES.IShaderModuleService)
|
||||
private readonly shaderModuleService: IShaderModuleService;
|
||||
|
||||
@lazyInject(TYPES.IMapService)
|
||||
private readonly map: IMapService;
|
||||
|
||||
@lazyInject(TYPES.IInteractionService)
|
||||
private readonly interactionService: IInteractionService;
|
||||
|
||||
|
@ -343,7 +344,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {
|
|||
});
|
||||
const { vs, fs, uniforms } = this.shaderModuleService.getModule(moduleName);
|
||||
const { createModel } = this.rendererService;
|
||||
|
||||
const parserData = this.getSource().data.dataArray;
|
||||
const {
|
||||
attributes,
|
||||
elements,
|
||||
|
|
|
@ -136,6 +136,78 @@ export function RasterImageTriangulation(feature: IEncodeFeature) {
|
|||
size: 5,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 计算3D弧线顶点
|
||||
* @param feature 映射数据
|
||||
* @param segNum 弧线线段数
|
||||
*/
|
||||
export function LineArcTriangulation(feature: IEncodeFeature) {
|
||||
const segNum = 30;
|
||||
const coordinates = feature.coordinates as IPosition[];
|
||||
const positions = [];
|
||||
const indexArray = [];
|
||||
for (let i = 0; i < segNum; i++) {
|
||||
// 上线两个顶点
|
||||
// [ x, y, z, sx,sy, tx,ty]
|
||||
positions.push(
|
||||
i,
|
||||
1,
|
||||
i,
|
||||
coordinates[0][0],
|
||||
coordinates[0][1],
|
||||
coordinates[1][0],
|
||||
coordinates[1][1],
|
||||
i,
|
||||
-1,
|
||||
i,
|
||||
coordinates[0][0],
|
||||
coordinates[0][1],
|
||||
coordinates[1][0],
|
||||
coordinates[1][1],
|
||||
);
|
||||
if (i !== segNum - 1) {
|
||||
indexArray.push(
|
||||
...[0, 1, 2, 1, 3, 2].map((v) => {
|
||||
return i * 2 + v;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
return {
|
||||
vertices: positions,
|
||||
indices: indexArray,
|
||||
size: 7,
|
||||
};
|
||||
}
|
||||
|
||||
export function HeatmapTriangulation(feature: IEncodeFeature) {
|
||||
const coordinates = feature.coordinates as number[];
|
||||
if (coordinates.length === 2) {
|
||||
coordinates.push(0);
|
||||
}
|
||||
const size = feature.size as number;
|
||||
const dir = addDir(-1, 1);
|
||||
const dir1 = addDir(1, 1);
|
||||
const dir2 = addDir(-1, -1);
|
||||
const dir3 = addDir(1, -1);
|
||||
// [x,y,z, dirx ,diry, weight]
|
||||
const positions = [
|
||||
...coordinates,
|
||||
...dir,
|
||||
...coordinates,
|
||||
...dir2,
|
||||
...coordinates,
|
||||
...dir3,
|
||||
...coordinates,
|
||||
...dir1,
|
||||
];
|
||||
const indexArray = [0, 1, 2, 3, 0, 2];
|
||||
return {
|
||||
vertices: positions,
|
||||
indices: indexArray,
|
||||
size: 5,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 点图层3d geomerty
|
||||
|
@ -217,3 +289,9 @@ function getHeatmapGeometry(shape: ShapeType2D | ShapeType3D): IExtrudeGeomety {
|
|||
const geometry = fillPolygon([path]);
|
||||
return geometry;
|
||||
}
|
||||
// 热力图计算范围
|
||||
function addDir(dirX: number, dirY: number) {
|
||||
const x = (dirX + 1) / 2;
|
||||
const y = (dirY + 1) / 2;
|
||||
return [x, y];
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
// import BufferBase, { IEncodeFeature, Position } from '../../core/BaseBuffer';
|
||||
// import extrudePolygon, {
|
||||
// fillPolygon,
|
||||
// IExtrudeGeomety,
|
||||
// } from '../../point/shape/extrude';
|
||||
// import {
|
||||
// geometryShape,
|
||||
// ShapeType2D,
|
||||
// ShapeType3D,
|
||||
// } from '../../point/shape/Path';
|
||||
// export default class GridHeatMapBuffer extends BufferBase {
|
||||
// private verticesOffset: number = 0;
|
||||
// protected buildFeatures() {
|
||||
// this.verticesOffset = 0;
|
||||
// const layerData = this.data as IEncodeFeature[];
|
||||
// layerData.forEach((feature: IEncodeFeature) => {
|
||||
// this.calculateFill(feature);
|
||||
// });
|
||||
// }
|
||||
// protected calculateFeatures() {
|
||||
// const layerData = this.data as IEncodeFeature[];
|
||||
// const shape = layerData[0].shape as ShapeType3D | ShapeType2D;
|
||||
// this.verticesCount = layerData.length;
|
||||
// this.indexCount = 0;
|
||||
// this.instanceGeometry = this.getGeometry(shape as
|
||||
// | ShapeType2D
|
||||
// | ShapeType3D);
|
||||
// }
|
||||
// protected calculateFill(feature: IEncodeFeature) {
|
||||
// feature.bufferInfo = { verticesOffset: this.verticesOffset };
|
||||
// const coordinates = feature.coordinates as Position;
|
||||
// this.encodeArray(feature, 1);
|
||||
// this.attributes.positions.set([...coordinates, 1], this.verticesOffset * 3);
|
||||
// this.verticesOffset++;
|
||||
// }
|
||||
// private getGeometry(shape: ShapeType2D | ShapeType3D): IExtrudeGeomety {
|
||||
// const path = geometryShape[shape]
|
||||
// ? geometryShape[shape]()
|
||||
// : geometryShape.circle();
|
||||
// // const geometry = ShapeType2D[str as ShapeType2D]
|
||||
// // ? fillPolygon([path])
|
||||
// // : extrudePolygon([path]);
|
||||
// const geometry = fillPolygon([path]);
|
||||
// return geometry;
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1,324 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
ICameraService,
|
||||
IEncodeFeature,
|
||||
IFramebuffer,
|
||||
ILayer,
|
||||
ILayerPlugin,
|
||||
ILogService,
|
||||
IModel,
|
||||
IStyleAttributeService,
|
||||
ITexture2D,
|
||||
lazyInject,
|
||||
TYPES,
|
||||
} from '@l7/core';
|
||||
import { mat4 } from 'gl-matrix';
|
||||
import BaseLayer from '../core/BaseLayer';
|
||||
import { HeatmapTriangulation } from '../core/triangulation';
|
||||
import { generateColorRamp, IColorRamp } from '../utils/color';
|
||||
import heatmap3DFrag from './shaders/heatmap_3d_frag.glsl';
|
||||
import heatmap3DVert from './shaders/heatmap_3d_vert.glsl';
|
||||
import heatmapColorFrag from './shaders/heatmap_frag.glsl';
|
||||
import heatmapFrag from './shaders/heatmap_framebuffer_frag.glsl';
|
||||
import heatmapVert from './shaders/heatmap_framebuffer_vert.glsl';
|
||||
import heatmapColorVert from './shaders/heatmap_vert.glsl';
|
||||
import { heatMap3DTriangulation } from './triangulation';
|
||||
|
||||
interface IHeatMapLayerStyleOptions {
|
||||
opacity: number;
|
||||
intensity: number;
|
||||
radius: number;
|
||||
rampColors: IColorRamp;
|
||||
}
|
||||
|
||||
export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
|
||||
public name: string = 'HeatMapLayer';
|
||||
protected texture: ITexture2D;
|
||||
protected colorTexture: ITexture2D;
|
||||
@lazyInject(TYPES.ICameraService)
|
||||
protected readonly camera: ICameraService;
|
||||
protected heatmapFramerBuffer: IFramebuffer;
|
||||
private intensityModel: IModel;
|
||||
private colorModel: IModel;
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected renderModels() {
|
||||
const { clear, useFramebuffer } = this.rendererService;
|
||||
|
||||
useFramebuffer(this.heatmapFramerBuffer, () => {
|
||||
clear({
|
||||
color: [0, 0, 0, 0],
|
||||
depth: 1,
|
||||
stencil: 0,
|
||||
framebuffer: this.heatmapFramerBuffer,
|
||||
});
|
||||
this.drawIntensityMode();
|
||||
});
|
||||
this.draw3DHeatMap();
|
||||
// this.drawIntensityMode();
|
||||
return this;
|
||||
}
|
||||
|
||||
protected buildModels() {
|
||||
this.registerBuiltinAttributes(this);
|
||||
this.intensityModel = this.buildHeatMapIntensity();
|
||||
this.models = [this.intensityModel];
|
||||
// this.colorModel = this.buildHeatmapColor();
|
||||
this.colorModel = this.build3dHeatMap();
|
||||
this.models.push(this.colorModel);
|
||||
const { rampColors } = this.getStyleOptions();
|
||||
const imageData = generateColorRamp(rampColors as IColorRamp);
|
||||
const {
|
||||
createFramebuffer,
|
||||
clear,
|
||||
getViewportSize,
|
||||
createTexture2D,
|
||||
useFramebuffer,
|
||||
} = this.rendererService;
|
||||
|
||||
const { width, height } = getViewportSize();
|
||||
this.heatmapFramerBuffer = createFramebuffer({
|
||||
color: createTexture2D({
|
||||
width,
|
||||
height,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
min: gl.NEAREST,
|
||||
mag: gl.NEAREST,
|
||||
}),
|
||||
});
|
||||
|
||||
this.colorTexture = createTexture2D({
|
||||
data: imageData.data,
|
||||
width: imageData.width,
|
||||
height: imageData.height,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
min: gl.NEAREST,
|
||||
mag: gl.NEAREST,
|
||||
flipY: true,
|
||||
});
|
||||
}
|
||||
|
||||
private registerBuiltinAttributes(layer: ILayer) {
|
||||
layer.styleAttributeService.registerStyleAttribute({
|
||||
name: 'dir',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Dir',
|
||||
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,
|
||||
) => {
|
||||
return [vertex[3], vertex[4]];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// point layer size;
|
||||
layer.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 = 2 } = feature;
|
||||
return [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private buildHeatMapIntensity(): IModel {
|
||||
return this.buildLayerModel({
|
||||
moduleName: 'heatmapintensity',
|
||||
vertexShader: heatmapVert,
|
||||
fragmentShader: heatmapFrag,
|
||||
triangulation: HeatmapTriangulation,
|
||||
depth: {
|
||||
enable: false,
|
||||
},
|
||||
blend: {
|
||||
enable: true,
|
||||
func: {
|
||||
srcRGB: gl.ONE,
|
||||
srcAlpha: 1,
|
||||
dstRGB: gl.ONE,
|
||||
dstAlpha: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private buildHeatmapColor(): IModel {
|
||||
this.shaderModuleService.registerModule('heatmapColor', {
|
||||
vs: heatmapColorVert,
|
||||
fs: heatmapColorFrag,
|
||||
});
|
||||
|
||||
const { vs, fs, uniforms } = this.shaderModuleService.getModule(
|
||||
'heatmapColor',
|
||||
);
|
||||
const {
|
||||
createAttribute,
|
||||
createElements,
|
||||
createBuffer,
|
||||
createModel,
|
||||
} = this.rendererService;
|
||||
return createModel({
|
||||
vs,
|
||||
fs,
|
||||
attributes: {
|
||||
a_Position: createAttribute({
|
||||
buffer: createBuffer({
|
||||
data: [-1, 1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0],
|
||||
type: gl.FLOAT,
|
||||
}),
|
||||
size: 3,
|
||||
}),
|
||||
a_Uv: createAttribute({
|
||||
buffer: createBuffer({
|
||||
data: [0, 1, 1, 1, 0, 0, 1, 0],
|
||||
type: gl.FLOAT,
|
||||
}),
|
||||
size: 2,
|
||||
}),
|
||||
},
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
},
|
||||
depth: {
|
||||
enable: false,
|
||||
},
|
||||
count: 6,
|
||||
elements: createElements({
|
||||
data: [0, 2, 1, 2, 3, 1],
|
||||
type: gl.UNSIGNED_INT,
|
||||
count: 6,
|
||||
}),
|
||||
});
|
||||
}
|
||||
private drawIntensityMode() {
|
||||
const { opacity, intensity = 10, radius = 5 } = this.getStyleOptions();
|
||||
this.intensityModel.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 1.0,
|
||||
u_radius: radius,
|
||||
u_intensity: intensity,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private drawColorMode() {
|
||||
const { opacity } = this.getStyleOptions();
|
||||
this.colorModel.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 1.0,
|
||||
u_colorTexture: this.colorTexture,
|
||||
u_texture: this.heatmapFramerBuffer,
|
||||
},
|
||||
});
|
||||
}
|
||||
private draw3DHeatMap() {
|
||||
const { opacity } = this.getStyleOptions();
|
||||
const mapbounds = this.map.getBounds();
|
||||
const invert = mat4.invert(
|
||||
mat4.create(),
|
||||
// @ts-ignore
|
||||
mat4.fromValues(...this.camera.getViewProjectionMatrix()),
|
||||
) as mat4;
|
||||
this.colorModel.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 1.0,
|
||||
u_colorTexture: this.colorTexture,
|
||||
u_texture: this.heatmapFramerBuffer,
|
||||
u_extent: [-179.9476, -60.0959, 179.9778, 79.5651],
|
||||
u_InverseViewProjectionMatrix: [...invert],
|
||||
},
|
||||
});
|
||||
}
|
||||
private build3dHeatMap() {
|
||||
const { getViewportSize } = this.rendererService;
|
||||
const { width, height } = getViewportSize();
|
||||
const triangulation = heatMap3DTriangulation(256, 128);
|
||||
this.shaderModuleService.registerModule('heatmap3dColor', {
|
||||
vs: heatmap3DVert,
|
||||
fs: heatmap3DFrag,
|
||||
});
|
||||
|
||||
const { vs, fs, uniforms } = this.shaderModuleService.getModule(
|
||||
'heatmap3dColor',
|
||||
);
|
||||
const {
|
||||
createAttribute,
|
||||
createElements,
|
||||
createBuffer,
|
||||
createModel,
|
||||
} = this.rendererService;
|
||||
return createModel({
|
||||
vs,
|
||||
fs,
|
||||
attributes: {
|
||||
a_Position: createAttribute({
|
||||
buffer: createBuffer({
|
||||
data: triangulation.vertices,
|
||||
type: gl.FLOAT,
|
||||
}),
|
||||
size: 3,
|
||||
}),
|
||||
a_Uv: createAttribute({
|
||||
buffer: createBuffer({
|
||||
data: triangulation.uvs,
|
||||
type: gl.FLOAT,
|
||||
}),
|
||||
size: 2,
|
||||
}),
|
||||
},
|
||||
primitive: gl.TRIANGLES,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
},
|
||||
depth: {
|
||||
enable: false,
|
||||
},
|
||||
elements: createElements({
|
||||
data: triangulation.indices,
|
||||
type: gl.UNSIGNED_INT,
|
||||
count: triangulation.indices.length,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
uniform sampler2D u_texture;
|
||||
uniform sampler2D u_colorTexture;
|
||||
uniform float u_Opacity;
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main(){
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
vec2 ramp_pos = vec2(
|
||||
fract(16.0 * (1.0 - intensity)),
|
||||
floor(16.0 * (1.0 - intensity)) / 16.0);
|
||||
// vec4 color = texture2D(u_colorTexture,vec2(0.5,1.0-intensity));
|
||||
vec4 color = texture2D(u_colorTexture,ramp_pos);
|
||||
gl_FragColor = color;
|
||||
// gl_FragColor.a = color.a * smoothstep(0.0,0.12,intensity) * u_Opacity;
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
precision highp float;
|
||||
attribute vec3 a_Position;
|
||||
attribute vec2 a_Uv;
|
||||
uniform sampler2D u_texture;
|
||||
uniform vec4 u_extent;
|
||||
varying vec2 v_texCoord;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_InverseViewProjectionMatrix;
|
||||
#pragma include "projection"
|
||||
void main() {
|
||||
v_texCoord = a_Uv;
|
||||
|
||||
vec2 pos = a_Uv * vec2(2.0) - vec2(1.0);
|
||||
|
||||
vec4 n_0 = vec4(pos, 0.0, 1.0) - u_ViewportCenterProjection;
|
||||
vec4 n_1 = vec4(pos, 1.0, 1.0) - u_ViewportCenterProjection;
|
||||
|
||||
vec4 m_0 = u_InverseViewProjectionMatrix * n_0 ;
|
||||
vec4 m_1 = u_InverseViewProjectionMatrix * n_1;
|
||||
m_0 = m_0 / m_0.w;
|
||||
m_1 = m_1 / m_1.w;
|
||||
|
||||
float zPos = (0.0 - m_0.z) / (m_1.z - m_0.z);
|
||||
vec4 mapCoord = m_0 + zPos * (m_1 - m_0);
|
||||
|
||||
// vec4 p = u_InverseViewProjectionMatrix * (vec4(pos,0,1) - u_ViewportCenterProjection);
|
||||
// p = p /p.w;
|
||||
// pos.y = 1.0 -pos.y;
|
||||
// vec2 minxy = project_position(vec4(u_extent.xy, 0, 1.0)).xy;
|
||||
// vec2 maxxy = project_position(vec4(u_extent.zw, 0, 1.0)).xy;
|
||||
|
||||
// vec2 step = (maxxy - minxy);
|
||||
|
||||
// vec2 pos = minxy + (vec2(a_Position.x, a_Position.y ) + vec2(1.0)) / vec2(2.0) * step;
|
||||
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
gl_Position = project_common_position_to_clipspace(vec4(mapCoord.xy, intensity * 100., 1.0));
|
||||
// gl_Position = vec4(pos,0.,1.0);
|
||||
// v_texCoord = (gl_Position.xy + vec2(1.0)) / vec2(2.0) / gl_Position.w;
|
||||
// v_texCoord.y = 1.0 - v_texCoord.y;
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
uniform sampler2D u_texture;
|
||||
uniform sampler2D u_colorTexture;
|
||||
uniform float u_Opacity;
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main(){
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
vec2 ramp_pos = vec2(
|
||||
fract(16.0 * (1.0 - intensity)),
|
||||
floor(16.0 * (1.0 - intensity)) / 16.0);
|
||||
// vec4 color = texture2D(u_colorTexture,vec2(0.5,1.0-intensity));
|
||||
vec4 color = texture2D(u_colorTexture,ramp_pos);
|
||||
gl_FragColor = color;
|
||||
gl_FragColor.a = color.a * smoothstep(0.1,0.5,intensity) * u_Opacity;
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
precision highp float;
|
||||
uniform float u_intensity;
|
||||
varying float v_weight;
|
||||
varying vec2 v_extrude;
|
||||
|
||||
|
||||
void main(){
|
||||
float GAUSS_COEF = 0.3989422804014327;
|
||||
float d = -0.5 * 3.0 * 3.0 * dot(v_extrude, v_extrude);
|
||||
float val = v_weight * u_intensity * GAUSS_COEF * exp(d);
|
||||
gl_FragColor = vec4(val, val, val, val);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
precision highp float;
|
||||
attribute vec3 a_Position;
|
||||
attribute float a_Size;
|
||||
attribute vec2 a_Dir;
|
||||
uniform float u_intensity;
|
||||
uniform float u_radius;
|
||||
varying vec2 v_extrude;
|
||||
varying float v_weight;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
|
||||
#pragma include "projection"
|
||||
|
||||
void main(){
|
||||
v_weight = a_Size;
|
||||
float GAUSS_COEF = 0.3989422804014327;
|
||||
float ZERO = 1.0 / 255.0 / 16.0;
|
||||
float extrude_x = a_Dir.x * 2.0 -1.0;
|
||||
float extrude_y = a_Dir.y * 2.0 -1.0;
|
||||
vec2 extrude_dir = normalize(vec2(extrude_x,extrude_y));
|
||||
float S = sqrt(-2.0 * log(ZERO / a_Size / u_intensity / GAUSS_COEF)) / 3.0;
|
||||
v_extrude = extrude_dir * S;
|
||||
|
||||
vec2 offset = project_pixel(v_extrude * u_radius);
|
||||
vec4 project_pos = project_position(vec4(a_Position.xy, 0.0, 1.0));
|
||||
|
||||
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, 0.0, 1.0));
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
precision highp float;
|
||||
attribute vec3 a_Position;
|
||||
attribute vec2 a_Uv;
|
||||
uniform sampler2D u_texture;
|
||||
varying vec2 v_texCoord;
|
||||
void main() {
|
||||
v_texCoord = a_Uv;
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
gl_Position = vec4(a_Position.xy,intensity -0.5, 1.);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import { IEncodeFeature, IParseDataItem } from '@l7/core';
|
||||
// @ts-ignore
|
||||
import Martini from '@mapbox/martini';
|
||||
export function heatMap3DTriangulation(width: number, height: number) {
|
||||
const indices = [];
|
||||
const vertices = [];
|
||||
const uvs = [];
|
||||
const gridX1 = width + 1;
|
||||
const gridY1 = height + 1;
|
||||
const widthHalf = width / 2;
|
||||
const heightHalf = height / 2;
|
||||
for (let iy = 0; iy < gridY1; iy++) {
|
||||
const y = iy - heightHalf;
|
||||
for (let ix = 0; ix < gridX1; ix++) {
|
||||
const x = ix - widthHalf;
|
||||
vertices.push(x / widthHalf, -y / heightHalf, 0);
|
||||
uvs.push(ix / width);
|
||||
uvs.push(1 - iy / height);
|
||||
}
|
||||
}
|
||||
for (let iy = 0; iy < height; iy++) {
|
||||
for (let ix = 0; ix < width; ix++) {
|
||||
const a = ix + gridX1 * iy;
|
||||
const b = ix + gridX1 * (iy + 1);
|
||||
const c = ix + 1 + gridX1 * (iy + 1);
|
||||
const d = ix + 1 + gridX1 * iy;
|
||||
indices.push(a, b, d);
|
||||
indices.push(b, c, d);
|
||||
}
|
||||
}
|
||||
return {
|
||||
vertices,
|
||||
indices,
|
||||
uvs,
|
||||
};
|
||||
}
|
|
@ -1,14 +1,19 @@
|
|||
import { container, ILayerPlugin, TYPES } from '@l7/core';
|
||||
import BaseLayer from './core/BaseLayer';
|
||||
import HeatMapGridLayer from './heatmap/grid';
|
||||
import HeatMapLayer from './heatmap/heatmap';
|
||||
import ArcLineLayer from './line/arc';
|
||||
import Arc2DLineLayer from './line/arc2d';
|
||||
import LineLayer from './line/index';
|
||||
import Point3dLayer from './point/extrude';
|
||||
import PointImageLayer from './point/image';
|
||||
import PointLayer from './point/index';
|
||||
import TextLayer from './point/text';
|
||||
// import Point from './point/point';
|
||||
import PolygonLayer from './polygon';
|
||||
import Polygon3DLayer from './polygon/polygon3D';
|
||||
import ImageLayer from './raster/image';
|
||||
import RasterLayer from './raster/raster';
|
||||
|
||||
import ConfigSchemaValidationPlugin from './plugins/ConfigSchemaValidationPlugin';
|
||||
import DataMappingPlugin from './plugins/DataMappingPlugin';
|
||||
|
@ -77,7 +82,11 @@ export {
|
|||
Polygon3DLayer,
|
||||
ImageLayer,
|
||||
HeatMapGridLayer,
|
||||
// Line,
|
||||
ArcLineLayer,
|
||||
Arc2DLineLayer,
|
||||
RasterLayer,
|
||||
HeatMapLayer,
|
||||
TextLayer,
|
||||
// ImageLayer,
|
||||
// HeatMapLayer,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
import { AttributeType, gl, IEncodeFeature, ILayer } from '@l7/core';
|
||||
import BaseLayer from '../core/BaseLayer';
|
||||
import { LineArcTriangulation } from '../core/triangulation';
|
||||
import line_arc_frag from './shaders/line_arc_frag.glsl';
|
||||
import line_arc_vert from './shaders/line_arc_vert.glsl';
|
||||
interface IArcLayerStyleOptions {
|
||||
opacity: number;
|
||||
segmentNumber: number;
|
||||
}
|
||||
export default class ArcLineLayer extends BaseLayer<IArcLayerStyleOptions> {
|
||||
public name: string = 'LineLayer';
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected renderModels() {
|
||||
const { opacity } = this.getStyleOptions();
|
||||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 1,
|
||||
segmentNumber: 30,
|
||||
},
|
||||
}),
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected buildModels() {
|
||||
this.registerBuiltinAttributes(this);
|
||||
this.models = [
|
||||
this.buildLayerModel({
|
||||
moduleName: 'arcline',
|
||||
vertexShader: line_arc_vert,
|
||||
fragmentShader: line_arc_frag,
|
||||
triangulation: LineArcTriangulation,
|
||||
blend: {
|
||||
enable: true,
|
||||
func: {
|
||||
srcRGB: gl.ONE,
|
||||
srcAlpha: 1,
|
||||
dstRGB: gl.ONE,
|
||||
dstAlpha: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
private registerBuiltinAttributes(layer: ILayer) {
|
||||
// point layer size;
|
||||
layer.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 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
layer.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]];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
import { AttributeType, gl, IEncodeFeature, ILayer } from '@l7/core';
|
||||
import BaseLayer from '../core/BaseLayer';
|
||||
import { LineArcTriangulation } from '../core/triangulation';
|
||||
import line_arc2d_vert from './shaders/line_arc2d_vert.glsl';
|
||||
import line_arc_frag from './shaders/line_arc_frag.glsl';
|
||||
interface IArcLayerStyleOptions {
|
||||
opacity: number;
|
||||
segmentNumber: number;
|
||||
}
|
||||
export default class Arc2DLineLayer extends BaseLayer<IArcLayerStyleOptions> {
|
||||
public name: string = 'LineLayer';
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected renderModels() {
|
||||
const { opacity } = this.getStyleOptions();
|
||||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 1,
|
||||
segmentNumber: 30,
|
||||
},
|
||||
}),
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected buildModels() {
|
||||
this.registerBuiltinAttributes(this);
|
||||
this.models = [
|
||||
this.buildLayerModel({
|
||||
moduleName: 'arc2dline',
|
||||
vertexShader: line_arc2d_vert,
|
||||
fragmentShader: line_arc_frag,
|
||||
triangulation: LineArcTriangulation,
|
||||
depth: { enable: false },
|
||||
blend: {
|
||||
enable: true,
|
||||
func: {
|
||||
srcRGB: gl.ONE,
|
||||
srcAlpha: 1,
|
||||
dstRGB: gl.ONE,
|
||||
dstAlpha: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
private registerBuiltinAttributes(layer: ILayer) {
|
||||
// point layer size;
|
||||
layer.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 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
layer.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]];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ export default class LineLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 0,
|
||||
u_Opacity: opacity || 1.0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
precision mediump float;
|
||||
attribute vec4 a_Color;
|
||||
attribute vec3 a_Position;
|
||||
attribute vec4 a_Instance;
|
||||
attribute float a_Size;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform float segmentNumber;
|
||||
varying vec4 v_color;
|
||||
|
||||
#pragma include "projection"
|
||||
|
||||
float maps (float value, float start1, float stop1, float start2, float stop2) {
|
||||
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
|
||||
}
|
||||
|
||||
float getSegmentRatio(float index) {
|
||||
return smoothstep(0.0, 1.0, index / (segmentNumber - 1.));
|
||||
}
|
||||
|
||||
float paraboloid(vec2 source, vec2 target, float ratio) {
|
||||
vec2 x = mix(source, target, ratio);
|
||||
vec2 center = mix(source, target, 0.5);
|
||||
float dSourceCenter = distance(source, center);
|
||||
float dXCenter = distance(x, center);
|
||||
return (dSourceCenter + dXCenter) * (dSourceCenter - dXCenter);
|
||||
}
|
||||
|
||||
vec3 getPos(vec2 source, vec2 target, float segmentRatio) {
|
||||
float vertex_height = paraboloid(source, target, segmentRatio);
|
||||
|
||||
return vec3(
|
||||
mix(source, target, segmentRatio),
|
||||
sqrt(max(0.0, vertex_height))
|
||||
);
|
||||
}
|
||||
vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
|
||||
// normalized direction of the line
|
||||
vec2 dir_screenspace = normalize(line_clipspace);
|
||||
// rotate by 90 degrees
|
||||
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
|
||||
vec2 offset = dir_screenspace * offset_direction * a_Size / 2.0;
|
||||
return offset;
|
||||
}
|
||||
float getAngularDist (vec2 source, vec2 target) {
|
||||
vec2 delta = source - target;
|
||||
vec2 sin_half_delta = sin(delta / 2.0);
|
||||
float a =
|
||||
sin_half_delta.y * sin_half_delta.y +
|
||||
cos(source.y) * cos(target.y) *
|
||||
sin_half_delta.x * sin_half_delta.x;
|
||||
return 2.0 * atan(sqrt(a), sqrt(1.0 - a));
|
||||
}
|
||||
vec2 interpolate (vec2 source, vec2 target, float angularDist, float t) {
|
||||
// if the angularDist is PI, linear interpolation is applied. otherwise, use spherical interpolation
|
||||
if(abs(angularDist - PI) < 0.001) {
|
||||
return (1.0 - t) * source + t * target;
|
||||
}
|
||||
float a = sin((1.0 - t) * angularDist) / sin(angularDist);
|
||||
float b = sin(t * angularDist) / sin(angularDist);
|
||||
vec2 sin_source = sin(source);
|
||||
vec2 cos_source = cos(source);
|
||||
vec2 sin_target = sin(target);
|
||||
vec2 cos_target = cos(target);
|
||||
float x = a * cos_source.y * cos_source.x + b * cos_target.y * cos_target.x;
|
||||
float y = a * cos_source.y * sin_source.x + b * cos_target.y * sin_target.x;
|
||||
float z = a * sin_source.y + b * sin_target.y;
|
||||
return vec2(atan(y, x), atan(z, sqrt(x * x + y * y)));
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
v_color = a_Color;
|
||||
vec2 source = radians(a_Instance.rg);
|
||||
vec2 target = radians(a_Instance.ba);
|
||||
float angularDist = getAngularDist(source, target);
|
||||
float segmentIndex = a_Position.x;
|
||||
float segmentRatio = getSegmentRatio(segmentIndex);
|
||||
float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0));
|
||||
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir);
|
||||
|
||||
vec4 curr = project_position(vec4(degrees(interpolate(source, target, angularDist, segmentRatio)), 0.0, 1.0));
|
||||
vec4 next = project_position(vec4(degrees(interpolate(source, target, angularDist, nextSegmentRatio)), 0.0, 1.0));
|
||||
|
||||
vec2 offset = getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y);
|
||||
|
||||
// vec4 project_pos = project_position(vec4(curr.xy, 0, 1.0));
|
||||
gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0));
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
precision mediump float;
|
||||
uniform float u_Opacity;
|
||||
varying vec4 v_color;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_FragColor = v_color;
|
||||
gl_FragColor.a = v_color.a * u_Opacity;
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
precision mediump float;
|
||||
attribute vec3 a_Position;
|
||||
attribute vec4 a_Instance;
|
||||
attribute vec4 a_Color;
|
||||
attribute float a_Size;
|
||||
|
||||
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform float segmentNumber;
|
||||
varying vec4 v_color;
|
||||
#pragma include "projection"
|
||||
|
||||
float maps (float value, float start1, float stop1, float start2, float stop2) {
|
||||
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
|
||||
}
|
||||
|
||||
float getSegmentRatio(float index) {
|
||||
return smoothstep(0.0, 1.0, index / (segmentNumber - 1.0));
|
||||
}
|
||||
|
||||
float paraboloid(vec2 source, vec2 target, float ratio) {
|
||||
vec2 x = mix(source, target, ratio);
|
||||
vec2 center = mix(source, target, 0.5);
|
||||
float dSourceCenter = distance(source, center);
|
||||
float dXCenter = distance(x, center);
|
||||
return (dSourceCenter + dXCenter) * (dSourceCenter - dXCenter);
|
||||
}
|
||||
|
||||
vec3 getPos(vec2 source, vec2 target, float segmentRatio) {
|
||||
float vertex_height = paraboloid(source, target, segmentRatio);
|
||||
|
||||
return vec3(
|
||||
mix(source, target, segmentRatio),
|
||||
sqrt(max(0.0, vertex_height))
|
||||
);
|
||||
}
|
||||
vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
|
||||
// normalized direction of the line
|
||||
vec2 dir_screenspace = normalize(line_clipspace);
|
||||
// rotate by 90 degrees
|
||||
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
|
||||
|
||||
vec2 offset = dir_screenspace * offset_direction * a_Size / 2.0;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
v_color = a_Color;
|
||||
vec2 source = project_position(vec4(a_Instance.rg, 0, 0)).xy;
|
||||
vec2 target = project_position(vec4(a_Instance.ba, 0, 0)).xy;
|
||||
float segmentIndex = a_Position.x;
|
||||
float segmentRatio = getSegmentRatio(segmentIndex);
|
||||
float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0));
|
||||
|
||||
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir);
|
||||
vec3 curr = getPos(source, target, segmentRatio);
|
||||
vec3 next = getPos(source, target, nextSegmentRatio);
|
||||
vec2 offset = getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y);
|
||||
|
||||
// vec4 project_pos = project_position(vec4(curr, 1.0));
|
||||
|
||||
gl_Position = project_common_position_to_clipspace(vec4(curr.xy + project_pixel(offset), curr.z, 1.0));
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ uniform mat4 u_ModelMatrix;
|
|||
varying vec4 v_color;
|
||||
varying float v_dash_array;
|
||||
varying vec3 v_normal;
|
||||
|
||||
#pragma include "projection"
|
||||
void main() {
|
||||
v_normal = a_Normal;
|
||||
|
|
|
@ -193,7 +193,7 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
}
|
||||
|
||||
private getDefaultType(firstValue: unknown) {
|
||||
let type = ScaleTypes.QUANTIZE;
|
||||
let type = ScaleTypes.LINEAR;
|
||||
if (typeof firstValue === 'string') {
|
||||
type = dateRegex.test(firstValue) ? ScaleTypes.TIME : ScaleTypes.CAT;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 0,
|
||||
u_Opacity: opacity || 1.0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -46,7 +46,7 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 0,
|
||||
u_Opacity: opacity || 1.0,
|
||||
u_texture: createTexture2D({
|
||||
data: this.iconService.getCanvas(),
|
||||
width: 1024,
|
||||
|
|
|
@ -44,7 +44,7 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 0,
|
||||
u_Opacity: opacity || 1.0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
@ -118,8 +118,8 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const { size = 2 } = feature;
|
||||
return [size as number];
|
||||
const { size } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,7 +13,9 @@ uniform vec4 u_activeColor : [1.0, 0.0, 0.0, 1.0];
|
|||
varying vec2 v_uv;
|
||||
varying float v_gamma_scale;
|
||||
varying vec4 v_color;
|
||||
|
||||
#pragma include "projection"
|
||||
|
||||
void main() {
|
||||
v_color = a_color;
|
||||
v_uv = a_tex / u_sdf_map_size;
|
||||
|
@ -24,10 +26,10 @@ void main() {
|
|||
vec4 project_pos = project_position(vec4(a_Position, 1.0));
|
||||
|
||||
vec4 projected_position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0));
|
||||
|
||||
|
||||
gl_Position = vec4(projected_position.xy / projected_position.w
|
||||
+ a_offset * fontScale / u_viewport_size * 2., 0.0, 1.0);
|
||||
v_gamma_scale = gl_Position.w;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
IFontOptions,
|
||||
ILayer,
|
||||
ILayerPlugin,
|
||||
ILogService,
|
||||
IStyleAttributeService,
|
||||
lazyInject,
|
||||
TYPES,
|
||||
} from '@l7/core';
|
||||
import BaseLayer from '../core/BaseLayer';
|
||||
import { getGlyphQuads, shapeText } from '../utils/symbol-layout';
|
||||
import textFrag from './shaders/text_frag.glsl';
|
||||
import textVert from './shaders/text_vert.glsl';
|
||||
interface IPointTextLayerStyleOptions {
|
||||
opacity: number;
|
||||
textAnchor: string;
|
||||
textOffset: [number, number];
|
||||
spacing: number;
|
||||
padding: [number, number];
|
||||
stroke: string;
|
||||
strokeWidth: number;
|
||||
strokeOpacity: number;
|
||||
fontWeight: string;
|
||||
fontFamily: string;
|
||||
|
||||
textAllowOverlap: boolean;
|
||||
}
|
||||
export function PointTriangulation(feature: IEncodeFeature) {
|
||||
const coordinates = feature.coordinates as number[];
|
||||
return {
|
||||
vertices: [...coordinates, ...coordinates, ...coordinates, ...coordinates],
|
||||
indices: [0, 1, 2, 2, 3, 0],
|
||||
size: coordinates.length,
|
||||
};
|
||||
}
|
||||
export default class TextLayer extends BaseLayer<IPointTextLayerStyleOptions> {
|
||||
public name: string = 'PointLayer';
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected renderModels() {
|
||||
const { opacity } = this.getStyleOptions();
|
||||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 1.0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected buildModels() {
|
||||
this.registerBuiltinAttributes(this);
|
||||
this.models = [
|
||||
this.buildLayerModel({
|
||||
moduleName: 'pointText',
|
||||
vertexShader: textVert,
|
||||
fragmentShader: textFrag,
|
||||
triangulation: PointTriangulation,
|
||||
depth: { enable: false },
|
||||
blend: {
|
||||
enable: true,
|
||||
func: {
|
||||
srcRGB: gl.SRC_ALPHA,
|
||||
srcAlpha: 1,
|
||||
dstRGB: gl.ONE_MINUS_SRC_ALPHA,
|
||||
dstAlpha: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
private registerBuiltinAttributes(layer: ILayer) {
|
||||
layer.styleAttributeService.registerStyleAttribute({
|
||||
name: 'textOffsets',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_textOffsets',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 2,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const extrude = [-1, -1, 1, -1, 1, 1, -1, 1];
|
||||
const extrudeIndex = (attributeIdx % 4) * 2;
|
||||
return [extrude[extrudeIndex], extrude[extrudeIndex + 1]];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// point layer size;
|
||||
layer.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 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// point layer size;
|
||||
layer.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 = layer.configService.getConfig().shape2d as string[];
|
||||
const shapeIndex = shape2d.indexOf(shape as string);
|
||||
return [shapeIndex];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private iniTextFont() {
|
||||
const { fontWeight = 'normal', fontFamily } = this.getStyleOptions();
|
||||
const data = this.getEncodedData();
|
||||
const characterSet: string[] = [];
|
||||
data.forEach((item: IEncodeFeature) => {
|
||||
let { text = '' } = item;
|
||||
text = text.toString();
|
||||
for (const char of text) {
|
||||
// 去重
|
||||
if (characterSet.indexOf(char) === -1) {
|
||||
characterSet.push(char);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.fontService.setFontOptions({
|
||||
characterSet,
|
||||
fontWeight,
|
||||
fontFamily,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
|
|||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 0,
|
||||
u_Opacity: opacity || 1.0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 0,
|
||||
u_Opacity: opacity || 1.0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
// import BaseBuffer, { IEncodeFeature, Position } from '../../core/BaseBuffer';
|
||||
// interface IImageFeature extends IEncodeFeature {
|
||||
// images: any[];
|
||||
// }
|
||||
// export default class ImageBuffer extends BaseBuffer {
|
||||
// protected calculateFeatures() {
|
||||
// this.verticesCount = 6;
|
||||
// this.indexCount = 6;
|
||||
// }
|
||||
// protected buildFeatures() {
|
||||
// this.attributes.uv = new Float32Array(this.verticesCount * 2);
|
||||
// const layerData = this.data as IImageFeature[];
|
||||
// const coordinates = layerData[0].coordinates as Position[];
|
||||
// const positions: number[] = [
|
||||
// ...coordinates[0],
|
||||
// 0,
|
||||
// coordinates[1][0],
|
||||
// coordinates[0][1],
|
||||
// 0,
|
||||
// ...coordinates[1],
|
||||
// 0,
|
||||
// ...coordinates[0],
|
||||
// 0,
|
||||
// ...coordinates[1],
|
||||
// 0,
|
||||
// coordinates[0][0],
|
||||
// coordinates[1][1],
|
||||
// 0,
|
||||
// ];
|
||||
// this.attributes.positions.set(positions, 0);
|
||||
// this.attributes.uv.set([0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0], 0);
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1,22 @@
|
|||
import { IEncodeFeature, IParseDataItem } from '@l7/core';
|
||||
// @ts-ignore
|
||||
import Martini from '@mapbox/martini';
|
||||
export function RasterTriangulation(parserData: IParseDataItem) {
|
||||
const { coordinates, data, min, max, width, height } = parserData;
|
||||
const maxlength = Math.max(width, height);
|
||||
const gridSize = Math.pow(2, Math.ceil(Math.log2(maxlength))) + 1;
|
||||
const terrain = new Float32Array(gridSize * gridSize);
|
||||
for (let i = 0; i < width; i++) {
|
||||
for (let j = 0; j < height; j++) {
|
||||
terrain[i * gridSize + j] = data[i * width + j];
|
||||
}
|
||||
}
|
||||
const martini = new Martini(gridSize);
|
||||
const tile = martini.createTile(terrain);
|
||||
const mesh = tile.getMesh(gridSize / 2);
|
||||
return {
|
||||
vertices: Array.from(mesh.vertices) as number[],
|
||||
indices: Array.from(mesh.triangles) as number[],
|
||||
size: 2,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
ILayer,
|
||||
ILayerPlugin,
|
||||
ILogService,
|
||||
IRasterParserDataItem,
|
||||
IStyleAttributeService,
|
||||
ITexture2D,
|
||||
lazyInject,
|
||||
TYPES,
|
||||
} from '@l7/core';
|
||||
import BaseLayer from '../core/BaseLayer';
|
||||
import { generateColorRamp, IColorRamp } from '../utils/color';
|
||||
import { RasterTriangulation } from './buffers/triangulation';
|
||||
import rasterFrag from './shaders/raster_frag.glsl';
|
||||
import rasterVert from './shaders/raster_vert.glsl';
|
||||
interface IRasterLayerStyleOptions {
|
||||
opacity: number;
|
||||
min: number;
|
||||
max: number;
|
||||
extent: [number, number, number, number];
|
||||
rampColors: IColorRamp;
|
||||
}
|
||||
|
||||
export default class RasterLayer extends BaseLayer<IRasterLayerStyleOptions> {
|
||||
public name: string = 'e';
|
||||
protected texture: ITexture2D;
|
||||
protected colorTexture: ITexture2D;
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected renderModels() {
|
||||
const { opacity } = this.getStyleOptions();
|
||||
const parserDataItem = this.getSource().data.dataArray[0];
|
||||
const { coordinates, width, height, min, max } = parserDataItem;
|
||||
this.models.forEach((model) =>
|
||||
model.draw({
|
||||
uniforms: {
|
||||
u_Opacity: opacity || 1,
|
||||
u_texture: this.texture,
|
||||
u_min: min,
|
||||
u_width: width,
|
||||
u_height: height,
|
||||
u_max: max,
|
||||
u_colorTexture: this.colorTexture,
|
||||
u_extent: [...coordinates[0], ...coordinates[1]],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected buildModels() {
|
||||
const parserDataItem = this.getSource().data.dataArray[0];
|
||||
const { createTexture2D } = this.rendererService;
|
||||
this.texture = createTexture2D({
|
||||
data: parserDataItem.data,
|
||||
width: parserDataItem.width,
|
||||
height: parserDataItem.height,
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
});
|
||||
const { rampColors } = this.getStyleOptions();
|
||||
const imageData = generateColorRamp(rampColors as IColorRamp);
|
||||
this.colorTexture = createTexture2D({
|
||||
data: imageData.data,
|
||||
width: imageData.width,
|
||||
height: imageData.height,
|
||||
flipY: true,
|
||||
});
|
||||
this.models = [this.buildRasterModel()];
|
||||
}
|
||||
private buildRasterModel() {
|
||||
const source = this.getSource();
|
||||
const sourceFeature = source.data.dataArray[0];
|
||||
const triangulation = RasterTriangulation(sourceFeature);
|
||||
this.shaderModuleService.registerModule('raster', {
|
||||
vs: rasterVert,
|
||||
fs: rasterFrag,
|
||||
});
|
||||
|
||||
const { vs, fs, uniforms } = this.shaderModuleService.getModule('raster');
|
||||
const {
|
||||
createAttribute,
|
||||
createElements,
|
||||
createBuffer,
|
||||
createModel,
|
||||
} = this.rendererService;
|
||||
return createModel({
|
||||
vs,
|
||||
fs,
|
||||
attributes: {
|
||||
a_Position: createAttribute({
|
||||
buffer: createBuffer({
|
||||
data: triangulation.vertices,
|
||||
type: gl.FLOAT,
|
||||
}),
|
||||
size: 2,
|
||||
}),
|
||||
},
|
||||
primitive: gl.TRIANGLES,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
},
|
||||
depth: {
|
||||
enable: true,
|
||||
},
|
||||
elements: createElements({
|
||||
data: triangulation.indices,
|
||||
type: gl.UNSIGNED_INT,
|
||||
count: triangulation.indices.length,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
varying vec4 v_color;
|
||||
uniform float u_Opacity: 1.0;
|
||||
#define PI 3.141592653589793
|
||||
|
||||
void main() {
|
||||
gl_FragColor = v_color;
|
||||
gl_FragColor.a *= u_Opacity;
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
precision highp float;
|
||||
|
||||
uniform mat4 u_ModelMatrix;
|
||||
attribute vec3 a_Position;
|
||||
|
||||
uniform vec4 u_extent;
|
||||
uniform sampler2D u_texture;
|
||||
uniform sampler2D u_colorTexture;
|
||||
uniform float u_min;
|
||||
uniform float u_max;
|
||||
uniform float u_width;
|
||||
uniform float u_height;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
varying vec4 v_color;
|
||||
#pragma include "projection"
|
||||
void main() {
|
||||
vec2 uv = a_Position.xy / vec2(u_width, u_height);
|
||||
vec2 minxy = project_position(vec4(u_extent.xy, 0, 1.0)).xy;
|
||||
vec2 maxxy = project_position(vec4(u_extent.zw, 0, 1.0)).xy;
|
||||
float value = texture2D(u_texture, vec2(uv.x,1.0 - uv.y)).x;
|
||||
vec2 step = (maxxy - minxy) / vec2(u_width, u_height);
|
||||
vec2 pos = minxy + vec2(a_Position.x, a_Position.y ) * step;
|
||||
// v_texCoord = a_Uv;
|
||||
value = clamp(value,u_min,u_max);
|
||||
float value1 = (value - u_min) / (u_max -u_min);
|
||||
vec2 ramp_pos = vec2(
|
||||
fract(16.0 * (1.0 - value1)),
|
||||
floor(16.0 * (1.0 - value1)) / 16.0);
|
||||
v_color = texture2D(u_colorTexture,ramp_pos);
|
||||
|
||||
// if(uv.x > 1.0 || uv.y > 1.0) {
|
||||
// v_color = vec4(0.);
|
||||
// }
|
||||
|
||||
// vec2 range = u_extent.zw - u_extent.xy;
|
||||
// vec4 project_pos = project_position(vec4(pos, 0, 1.0));
|
||||
gl_Position = project_common_position_to_clipspace(vec4(pos.xy, project_scale(value) * 10., 1.0));
|
||||
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
import * as d3 from 'd3-color';
|
||||
export interface IColorRamp {
|
||||
positions: number[];
|
||||
colors: string[];
|
||||
}
|
||||
export function rgb2arr(str: string) {
|
||||
const color = d3.color(str) as d3.RGBColor;
|
||||
const arr = [0, 0, 0, 0];
|
||||
|
@ -10,3 +14,23 @@ export function rgb2arr(str: string) {
|
|||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
export function generateColorRamp(colorRamp: IColorRamp): ImageData {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||
canvas.width = 256;
|
||||
canvas.height = 1;
|
||||
const gradient = ctx.createLinearGradient(0, 0, 256, 0);
|
||||
let data = null;
|
||||
const min = colorRamp.positions[0];
|
||||
const max = colorRamp.positions[colorRamp.positions.length - 1];
|
||||
for (let i = 0; i < colorRamp.colors.length; ++i) {
|
||||
const value = (colorRamp.positions[i] - min) / (max - min);
|
||||
gradient.addColorStop(value, colorRamp.colors[i]);
|
||||
}
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(0, 0, 256, 1);
|
||||
data = new Uint8ClampedArray(ctx.getImageData(0, 0, 256, 1).data);
|
||||
|
||||
return new ImageData(data, 16, 16);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
/**
|
||||
* 返回文本相对锚点位置
|
||||
* @param {string} anchor 锚点位置
|
||||
* @return {alignment} alignment
|
||||
*/
|
||||
function getAnchorAlignment(anchor: string) {
|
||||
let horizontalAlign = 0.5;
|
||||
let verticalAlign = 0.5;
|
||||
|
||||
switch (anchor) {
|
||||
case 'right':
|
||||
case 'top-right':
|
||||
case 'bottom-right':
|
||||
horizontalAlign = 1;
|
||||
break;
|
||||
case 'left':
|
||||
case 'top-left':
|
||||
case 'bottom-left':
|
||||
horizontalAlign = 0;
|
||||
break;
|
||||
default:
|
||||
horizontalAlign = 0.5;
|
||||
}
|
||||
|
||||
switch (anchor) {
|
||||
case 'bottom':
|
||||
case 'bottom-right':
|
||||
case 'bottom-left':
|
||||
verticalAlign = 1;
|
||||
break;
|
||||
case 'top':
|
||||
case 'top-right':
|
||||
case 'top-left':
|
||||
verticalAlign = 0;
|
||||
break;
|
||||
default:
|
||||
verticalAlign = 0.5;
|
||||
}
|
||||
|
||||
return { horizontalAlign, verticalAlign };
|
||||
}
|
||||
|
||||
// justify right = 1, left = 0, center = 0.5
|
||||
function justifyLine(
|
||||
positionedGlyphs: any,
|
||||
glyphMap: any,
|
||||
start: number,
|
||||
end: number,
|
||||
justify: number,
|
||||
) {
|
||||
if (!justify) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lastPositionedGlyph = positionedGlyphs[end];
|
||||
const glyph = lastPositionedGlyph.glyph;
|
||||
if (glyph) {
|
||||
const lastAdvance = glyphMap[glyph].advance * lastPositionedGlyph.scale;
|
||||
const lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify;
|
||||
|
||||
for (let j = start; j <= end; j++) {
|
||||
positionedGlyphs[j].x -= lineIndent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// justify right=1 left=0 center=0.5
|
||||
// horizontalAlign right=1 left=0 center=0.5
|
||||
// verticalAlign right=1 left=0 center=0.5
|
||||
function align(
|
||||
positionedGlyphs: any[],
|
||||
justify: number,
|
||||
horizontalAlign: number,
|
||||
verticalAlign: number,
|
||||
maxLineLength: number,
|
||||
lineHeight: number,
|
||||
lineCount: number,
|
||||
) {
|
||||
const shiftX = (justify - horizontalAlign) * maxLineLength;
|
||||
const shiftY = (-verticalAlign * lineCount + 0.5) * lineHeight;
|
||||
|
||||
for (const glyphs of positionedGlyphs) {
|
||||
glyphs.x += shiftX;
|
||||
glyphs.y += shiftY;
|
||||
}
|
||||
}
|
||||
|
||||
function shapeLines(
|
||||
shaping: any,
|
||||
glyphMap: any,
|
||||
lines: any[],
|
||||
lineHeight: number,
|
||||
textAnchor: string,
|
||||
textJustify: string,
|
||||
spacing: number,
|
||||
) {
|
||||
// buffer 为 4
|
||||
const yOffset = -8;
|
||||
|
||||
let x = 0;
|
||||
let y = yOffset;
|
||||
|
||||
let maxLineLength = 0;
|
||||
const positionedGlyphs = shaping.positionedGlyphs;
|
||||
|
||||
const justify =
|
||||
textJustify === 'right' ? 1 : textJustify === 'left' ? 0 : 0.5;
|
||||
|
||||
const lineStartIndex = positionedGlyphs.length;
|
||||
lines.forEach((line) => {
|
||||
line.split('').forEach((char: string) => {
|
||||
const glyph = glyphMap[char];
|
||||
const baselineOffset = 0;
|
||||
|
||||
if (glyph) {
|
||||
positionedGlyphs.push({
|
||||
glyph: char,
|
||||
x,
|
||||
y: y + baselineOffset,
|
||||
vertical: false, // TODO:目前只支持水平方向
|
||||
scale: 1,
|
||||
metrics: glyph,
|
||||
});
|
||||
x += glyph.advance + spacing;
|
||||
}
|
||||
});
|
||||
|
||||
// 左右对齐
|
||||
if (positionedGlyphs.length !== lineStartIndex) {
|
||||
const lineLength = x - spacing;
|
||||
maxLineLength = Math.max(lineLength, maxLineLength);
|
||||
justifyLine(
|
||||
positionedGlyphs,
|
||||
glyphMap,
|
||||
lineStartIndex,
|
||||
positionedGlyphs.length - 1,
|
||||
justify,
|
||||
);
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y += lineHeight;
|
||||
});
|
||||
|
||||
const { horizontalAlign, verticalAlign } = getAnchorAlignment(textAnchor);
|
||||
align(
|
||||
positionedGlyphs,
|
||||
justify,
|
||||
horizontalAlign,
|
||||
verticalAlign,
|
||||
maxLineLength,
|
||||
lineHeight,
|
||||
lines.length,
|
||||
);
|
||||
|
||||
// 计算包围盒
|
||||
const height = y - yOffset;
|
||||
|
||||
shaping.top += -verticalAlign * height;
|
||||
shaping.bottom = shaping.top + height;
|
||||
shaping.left += -horizontalAlign * maxLineLength;
|
||||
shaping.right = shaping.left + maxLineLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算文本中每个独立字符相对锚点的位置
|
||||
*
|
||||
* @param {string} text 原始文本
|
||||
* @param {*} glyphs mapping
|
||||
* @param {number} lineHeight 行高
|
||||
* @param {string} textAnchor 文本相对于锚点的位置
|
||||
* @param {string} textJustify 左右对齐
|
||||
* @param {number} spacing 字符间距
|
||||
* @param {[number, number]} translate 文本水平 & 垂直偏移量
|
||||
* @return {boolean|shaping} 每个字符相对于锚点的位置
|
||||
*/
|
||||
export function shapeText(
|
||||
text: string,
|
||||
glyphs: any,
|
||||
lineHeight: number,
|
||||
textAnchor: string,
|
||||
textJustify: string,
|
||||
spacing: number,
|
||||
translate: [number, number],
|
||||
) {
|
||||
// TODO:处理换行
|
||||
const lines = text.split('\n');
|
||||
|
||||
const positionedGlyphs: any[] = [];
|
||||
const shaping = {
|
||||
positionedGlyphs,
|
||||
top: translate[1],
|
||||
bottom: translate[1],
|
||||
left: translate[0],
|
||||
right: translate[0],
|
||||
lineCount: lines.length,
|
||||
text,
|
||||
};
|
||||
|
||||
shapeLines(
|
||||
shaping,
|
||||
glyphs,
|
||||
lines,
|
||||
lineHeight,
|
||||
textAnchor,
|
||||
textJustify,
|
||||
spacing,
|
||||
);
|
||||
if (!positionedGlyphs.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return shaping;
|
||||
}
|
||||
|
||||
export function getGlyphQuads(
|
||||
shaping: any,
|
||||
textOffset: [number, number],
|
||||
alongLine: boolean,
|
||||
) {
|
||||
const { positionedGlyphs } = shaping;
|
||||
const quads = [];
|
||||
|
||||
for (const positionedGlyph of positionedGlyphs) {
|
||||
const rect = positionedGlyph.metrics;
|
||||
|
||||
// The rects have an addditional buffer that is not included in their size.
|
||||
const rectBuffer = 4;
|
||||
|
||||
const halfAdvance = (rect.advance * positionedGlyph.scale) / 2;
|
||||
|
||||
const glyphOffset = alongLine
|
||||
? [positionedGlyph.x + halfAdvance, positionedGlyph.y]
|
||||
: [0, 0];
|
||||
|
||||
const builtInOffset = alongLine
|
||||
? [0, 0]
|
||||
: [
|
||||
positionedGlyph.x + halfAdvance + textOffset[0],
|
||||
positionedGlyph.y + textOffset[1],
|
||||
];
|
||||
|
||||
const x1 =
|
||||
(0 - rectBuffer) * positionedGlyph.scale - halfAdvance + builtInOffset[0];
|
||||
const y1 = (0 - rectBuffer) * positionedGlyph.scale + builtInOffset[1];
|
||||
const x2 = x1 + rect.width * positionedGlyph.scale;
|
||||
const y2 = y1 + rect.height * positionedGlyph.scale;
|
||||
|
||||
const tl = { x: x1, y: y1 };
|
||||
const tr = { x: x2, y: y1 };
|
||||
const bl = { x: x1, y: y2 };
|
||||
const br = { x: x2, y: y2 };
|
||||
|
||||
// TODO:处理字符旋转的情况
|
||||
|
||||
quads.push({ tl, tr, bl, br, tex: rect, glyphOffset });
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
|
@ -22,6 +22,8 @@
|
|||
"@l7/core": "^0.0.1",
|
||||
"inversify": "^5.0.1",
|
||||
"inversify-logging": "^0.2.1",
|
||||
"regl": "^1.3.11"
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"regl": "^1.3.11",
|
||||
"gl": "^4.4.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ export default class ReglTexture2D implements ITexture2D {
|
|||
type = gl.UNSIGNED_BYTE,
|
||||
width,
|
||||
height,
|
||||
flipY = false,
|
||||
format = gl.RGBA,
|
||||
mipmap = false,
|
||||
wrapS = gl.CLAMP_TO_EDGE,
|
||||
|
@ -46,6 +47,7 @@ export default class ReglTexture2D implements ITexture2D {
|
|||
mag: filterMap[mag],
|
||||
min: filterMap[min],
|
||||
alignment,
|
||||
flipY,
|
||||
colorSpace: colorSpaceMap[colorSpace],
|
||||
premultiplyAlpha,
|
||||
aniso,
|
||||
|
|
|
@ -3,6 +3,7 @@ import csv from './parser/csv';
|
|||
import geojson from './parser/geojson';
|
||||
import image from './parser/image';
|
||||
import json from './parser/json';
|
||||
import raster from './parser/raster';
|
||||
import Source from './source';
|
||||
import { cluster } from './transform/cluster';
|
||||
import { aggregatorToGrid } from './transform/grid';
|
||||
|
@ -12,6 +13,7 @@ registerParser('geojson', geojson);
|
|||
registerParser('image', image);
|
||||
registerParser('csv', csv);
|
||||
registerParser('json', json);
|
||||
registerParser('raster', raster);
|
||||
registerTransform('cluster', cluster);
|
||||
registerTransform('grid', aggregatorToGrid);
|
||||
registerTransform('hexagon', pointToHexbin);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { IParserData } from '@l7/core';
|
||||
import { getImage } from '@l7/utils';
|
||||
import { IParserData } from '../interface';
|
||||
interface IImageCfg {
|
||||
extent: [number, number, number, number];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { IParserData, IRasterCfg } from '@l7/core';
|
||||
export default function raster(data: number[], cfg: IRasterCfg): IParserData {
|
||||
const { extent, width, height, min, max } = cfg;
|
||||
const resultData = {
|
||||
_id: 1,
|
||||
dataArray: [
|
||||
{
|
||||
_id: 1,
|
||||
data: Array.from(data),
|
||||
width,
|
||||
height,
|
||||
min,
|
||||
max,
|
||||
coordinates: [[extent[0], extent[1]], [extent[2], extent[3]]],
|
||||
},
|
||||
],
|
||||
};
|
||||
return resultData;
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import Arc2DLineDemo from './components/Arc2DLine';
|
||||
import ArcLineDemo from './components/Arcline';
|
||||
import HeatMapDemo from './components/heatMap';
|
||||
import GridHeatMap from './components/heatMapgrid';
|
||||
import LineLayer from './components/Line';
|
||||
import PointDemo from './components/Point';
|
||||
|
@ -7,6 +10,7 @@ import Point3D from './components/Point3D';
|
|||
import PointImage from './components/pointImage';
|
||||
import Polygon3D from './components/polygon3D';
|
||||
import ImageLayerDemo from './components/rasterImage';
|
||||
import RasterLayerDemo from './components/RasterLayer';
|
||||
|
||||
// @ts-ignore
|
||||
storiesOf('图层', module)
|
||||
|
@ -15,5 +19,9 @@ storiesOf('图层', module)
|
|||
.add('图片标注', () => <PointImage />)
|
||||
.add('面3d图层', () => <Polygon3D />)
|
||||
.add('线图层', () => <LineLayer />)
|
||||
.add('3D弧线', () => <ArcLineDemo />)
|
||||
.add('2D弧线', () => <Arc2DLineDemo />)
|
||||
.add('网格热力图', () => <GridHeatMap />)
|
||||
.add('热力图', () => <HeatMapDemo />)
|
||||
.add('栅格', () => <RasterLayerDemo />)
|
||||
.add('图片', () => <ImageLayerDemo />);
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
import { Arc2DLineLayer } from '@l7/layers';
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Arc2DLineDemo extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt',
|
||||
);
|
||||
const scene = new Scene({
|
||||
center: [116.2825, 39.9],
|
||||
id: 'map',
|
||||
pitch: 0,
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/dark-v9',
|
||||
zoom: 2,
|
||||
});
|
||||
const lineLayer = new Arc2DLineLayer({})
|
||||
.source(await response.text(), {
|
||||
parser: {
|
||||
type: 'csv',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng2',
|
||||
y1: 'lat2',
|
||||
},
|
||||
})
|
||||
.size(0.5)
|
||||
.shape('arc')
|
||||
.color('rgb(13,64,140)');
|
||||
scene.addLayer(lineLayer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
import { ArcLineLayer } from '@l7/layers';
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class ArcLineDemo extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt',
|
||||
);
|
||||
const scene = new Scene({
|
||||
center: [116.2825, 39.9],
|
||||
id: 'map',
|
||||
pitch: 0,
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/dark-v9',
|
||||
zoom: 2,
|
||||
});
|
||||
const lineLayer = new ArcLineLayer({})
|
||||
.source(await response.text(), {
|
||||
parser: {
|
||||
type: 'csv',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng2',
|
||||
y1: 'lat2',
|
||||
},
|
||||
})
|
||||
.size(0.5)
|
||||
.shape('arc')
|
||||
.color('rgb(13,64,140)');
|
||||
scene.addLayer(lineLayer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import { LineLayer } from '@l7/layers';
|
|||
import { Scene } from '@l7/scene';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Point3D extends React.Component {
|
||||
export default class LineDemo extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
|
|
|
@ -57,6 +57,7 @@ export default class Point3D extends React.Component {
|
|||
scene.addLayer(pointLayer);
|
||||
console.log(pointLayer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -39,6 +39,7 @@ export default class Point3D extends React.Component {
|
|||
.size([15, 10]);
|
||||
scene.addLayer(pointLayer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
import { RasterLayer } from '@l7/layers';
|
||||
import { Scene } from '@l7/scene';
|
||||
// @ts-ignore
|
||||
import * as GeoTIFF from 'geotiff/dist/geotiff.bundle.js';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class ImageLayerDemo extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const scene = new Scene({
|
||||
center: [121.268, 30.3628],
|
||||
id: 'map',
|
||||
pitch: 0,
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/streets-v9',
|
||||
zoom: 2,
|
||||
});
|
||||
const tiffdata = await this.getTiffData();
|
||||
const layer = new RasterLayer({});
|
||||
layer
|
||||
.source(tiffdata.data, {
|
||||
parser: {
|
||||
type: 'raster',
|
||||
width: tiffdata.width,
|
||||
height: tiffdata.height,
|
||||
min: 0,
|
||||
max: 8000,
|
||||
extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963],
|
||||
},
|
||||
})
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
rampColors: {
|
||||
colors: [
|
||||
'#002466',
|
||||
'#0D408C',
|
||||
'#105CB3',
|
||||
'#1A76C7',
|
||||
'#2894E0',
|
||||
'#3CB4F0',
|
||||
'#65CEF7',
|
||||
'#98E3FA',
|
||||
'#CFF6FF',
|
||||
'#E8FCFF',
|
||||
],
|
||||
positions: [0, 0.02, 0.05, 0.1, 0.2, 0.3, 0.5, 0.6, 0.8, 1.0],
|
||||
},
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
console.log(layer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
private async getTiffData() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/rmsportal/XKgkjjGaAzRyKupCBiYW.dat',
|
||||
);
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer);
|
||||
const image = await tiff.getImage();
|
||||
const width = image.getWidth();
|
||||
const height = image.getHeight();
|
||||
const values = await image.readRasters();
|
||||
return {
|
||||
data: values[0],
|
||||
width,
|
||||
height,
|
||||
min: 0,
|
||||
max: 8000,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
import { PointLayer } from '@l7/layers';
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as React from 'react';
|
||||
import data from '../data/data.json';
|
||||
export default class Point3D extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
const scene = new Scene({
|
||||
center: [120.19382669582967, 30.258134],
|
||||
id: 'map',
|
||||
pitch: 0,
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/streets-v9',
|
||||
zoom: 1,
|
||||
});
|
||||
const pointLayer = new PointLayer({});
|
||||
const p1 = {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [83.671875, 44.84029065139799],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
pointLayer
|
||||
.source(data)
|
||||
.color('name', [
|
||||
'#FFF5B8',
|
||||
'#FFDC7D',
|
||||
'#FFAB5C',
|
||||
'#F27049',
|
||||
'#D42F31',
|
||||
'#730D1C',
|
||||
])
|
||||
.shape('subregion',[
|
||||
'circle',
|
||||
'triangle',
|
||||
'square',
|
||||
'pentagon',
|
||||
'hexagon',
|
||||
'octogon',
|
||||
'hexagram',
|
||||
'rhombus',
|
||||
'vesica',
|
||||
])
|
||||
.size('scalerank', [2, 4, 6, 8, 10]);
|
||||
scene.addLayer(pointLayer);
|
||||
console.log(pointLayer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
import { HeatMapLayer } from '@l7/layers';
|
||||
import { Scene } from '@l7/scene';
|
||||
// @ts-ignore
|
||||
import * as React from 'react';
|
||||
|
||||
export default class HeatMapLayerDemo extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json',
|
||||
);
|
||||
const scene = new Scene({
|
||||
center: [121.268, 30.3628],
|
||||
id: 'map',
|
||||
pitch: 0,
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/dark-v10',
|
||||
zoom: 2,
|
||||
});
|
||||
const layer = new HeatMapLayer({
|
||||
enableTAA: true,
|
||||
});
|
||||
layer
|
||||
.source(await response.json())
|
||||
.size('mag', [0, 1]) // weight映射通道
|
||||
.style({
|
||||
intensity: 2,
|
||||
radius: 20,
|
||||
opacity: 0.5,
|
||||
rampColors: {
|
||||
colors: [
|
||||
'rgba(0,0,0,0)',
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
],
|
||||
positions: [0, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0],
|
||||
},
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
console.log(layer);
|
||||
// requestAnimationFrame(run);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
// function run() {
|
||||
// scene.render();
|
||||
// requestAnimationFrame(run);
|
||||
// }
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -58,6 +58,7 @@ export default class GridHeatMap extends React.Component {
|
|||
]);
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -42,6 +42,7 @@ export default class PointImage extends React.Component {
|
|||
.size(30);
|
||||
scene.addLayer(pointLayer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -56,6 +56,7 @@ export default class Polygon3D extends React.Component {
|
|||
});
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -29,8 +29,8 @@ export default class ImageLayerDemo extends React.Component {
|
|||
},
|
||||
);
|
||||
scene.addLayer(layer);
|
||||
console.log(layer);
|
||||
scene.render();
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
20
yarn.lock
20
yarn.lock
|
@ -2129,6 +2129,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.4.1.tgz#c0a03cf75f8b0ad7b57849d6c7e91b0aec4b640f"
|
||||
integrity sha512-yyKza9S6z3ELKuf6w5n6VNUB0Osu6Z93RXPfMHLIlNWohu3KqxewLOq4lMXseYJ92GwkRAxd207Pr/Z98cwmvw==
|
||||
|
||||
"@mapbox/martini@^0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/martini/-/martini-0.1.0.tgz#1801b9234140e1136f37939157ba647d46f1ea30"
|
||||
integrity sha512-sAk7M4l1Zw0vIRIH1QpT+dy548w0Mh5fMP+r2sNPVzM9q8BV2nur76Qiv7cQ1NJzbYdCX182qUxbRnUljT4grg==
|
||||
|
||||
"@mapbox/point-geometry@0.1.0", "@mapbox/point-geometry@^0.1.0", "@mapbox/point-geometry@~0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2"
|
||||
|
@ -7450,6 +7455,14 @@ geojson-vt@^3.2.1:
|
|||
resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-3.2.1.tgz#f8adb614d2c1d3f6ee7c4265cad4bbf3ad60c8b7"
|
||||
integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==
|
||||
|
||||
geotiff@^1.0.0-beta.6:
|
||||
version "1.0.0-beta.6"
|
||||
resolved "https://registry.yarnpkg.com/geotiff/-/geotiff-1.0.0-beta.6.tgz#500f256196a2c23517b73ccb36a45dc82a1f7a70"
|
||||
integrity sha512-xdZ/MLcnrv1+6wQlQZQIs11zNJywylnV1pXqDw7Ao7bmLRpM421a39dXP5e6SG+vio0mnDUZkL2XknKbqppFzw==
|
||||
dependencies:
|
||||
pako "^1.0.3"
|
||||
xmldom "0.1.*"
|
||||
|
||||
get-caller-file@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
|
||||
|
@ -11527,7 +11540,7 @@ p-waterfall@^1.0.0:
|
|||
dependencies:
|
||||
p-reduce "^1.0.0"
|
||||
|
||||
pako@~1.0.5:
|
||||
pako@^1.0.3, pako@~1.0.5:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
|
||||
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
|
||||
|
@ -15995,6 +16008,11 @@ xml-name-validator@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
|
||||
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
|
||||
|
||||
xmldom@0.1.*:
|
||||
version "0.1.27"
|
||||
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
|
||||
integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk=
|
||||
|
||||
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
|
|
Loading…
Reference in New Issue