Merge pull request #145 from antvis/docs

feat: add raster layer
This commit is contained in:
@thinkinggis 2020-01-02 21:10:22 +08:00 committed by GitHub
commit 1fb532d0e7
28 changed files with 594 additions and 133 deletions

View File

@ -43,7 +43,7 @@ order: 5
layer.source(pointsData, {
cluster: true,
});
// 设置配置项
layer.source(pointsData, {
cluster: true,

View File

@ -5,7 +5,7 @@ order: 2
# 简介
L7 专注数据可视化层数据表达,目前 L7 还不支持独立的地图引擎,需要引入第三方引擎,目前支持 高德地图和 MapBox 两种。
L7 专注数据可视化层数据表达,目前 L7 还不支持独立的地图引擎,需要引入第三方引擎,目前支持 高德地图和 MapBox 两种。=
L7 在内部解决了不同底图地图直接的差异,同时 L7 层面统一管理地图的操作方法。
## Map
@ -25,6 +25,15 @@ L7 在内部解决了不同底图地图直接的差异,同时 L7 层面统一
#### 高德地图实例化
高德地图 API 配置参数
- token
注册高德 [API token](https://lbs.amap.com/api/javascript-api/guide/abc/prepare)
- plugin {array} `['AMap.ElasticMarker','AMap.CircleEditor']`
加载[高德地图插件](https://lbs.amap.com/api/javascript-api/guide/abc/plugins)
```javascript
const L7AMap = new GaodeMap({
pitch: 35.210526315789465,
@ -32,6 +41,7 @@ const L7AMap = new GaodeMap({
center: [104.288144, 31.239692],
zoom: 4.4,
token: 'xxxx - token',
plugin: [], // 可以不设置
});
```
@ -59,6 +69,8 @@ const scene = new Scene({
⚠️ 传入地图实例需要自行引入相关地图的 API
⚠️ viewMode 设置为 3D 模式
#### 传入高德地图实例
```javascript
@ -76,6 +88,9 @@ const scene = new Scene({
});
```
[示例地址](/zh/examples/tutorial/map#amapInstance)
[代码地址](https://github.com/antvis/L7/blob/master/examples/tutorial/map/demo/amapInstance.js)
#### 传入 Mapbox 地图实例
```javascript

View File

@ -25,6 +25,15 @@ L7 在内部解决了不同底图地图直接的差异,同时 L7 层面统一
#### 高德地图实例化
高德地图 API 配置参数
- token
注册高德 [API token](https://lbs.amap.com/api/javascript-api/guide/abc/prepare)
- plugin {array} `['AMap.ElasticMarker','AMap.CircleEditor']`
加载[高德地图插件](https://lbs.amap.com/api/javascript-api/guide/abc/plugins)
```javascript
const L7AMap = new GaodeMap({
pitch: 35.210526315789465,
@ -32,6 +41,7 @@ const L7AMap = new GaodeMap({
center: [104.288144, 31.239692],
zoom: 4.4,
token: 'xxxx - token',
plugin: [], // 可以不设置
});
```
@ -59,6 +69,8 @@ const scene = new Scene({
⚠️ 传入地图实例需要自行引入相关地图的 API
⚠️ viewMode 设置为 3D 模式
#### 传入高德地图实例
```javascript

View File

@ -187,7 +187,6 @@ layer.source(
parser:{
type:'json',
coordinates: "coord",
}
}
})

View File

@ -0,0 +1,57 @@
import { RasterLayer, Scene } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
import * as GeoTIFF from 'geotiff';
const scene = new Scene({
id: 'map',
map: new GaodeMap({
pitch: 0,
style: 'dark',
center: [ 115.5268, 34.3628 ],
zoom: 3
})
});
addLayer();
async function 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
};
}
async function addLayer() {
const tiffdata = await getTiffData();
const layer = new RasterLayer({});
layer
.source(tiffdata.data, {
parser: {
type: 'raster',
width: tiffdata.width,
height: tiffdata.height,
extent: [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
}
})
.style({
heightRatio: 100,
opacity: 0.8,
domain: [ 0, 8000 ],
rampColors: {
colors: [ '#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C' ].reverse(),
positions: [ 0, 0.2, 0.4, 0.6, 0.8, 1.0 ]
}
});
scene.addLayer(layer);
}

View File

@ -46,7 +46,7 @@ const defaultLayerConfig: Partial<ILayerConfig> = {
'vesica',
],
shape3d: ['cylinder', 'triangleColumn', 'hexagonColumn', 'squareColumn'],
minZoom: 0,
minZoom: -1,
maxZoom: 24,
visible: true,
autoFit: false,

View File

@ -40,12 +40,12 @@ describe('ConfigService', () => {
const { valid, errorText } = configService.validateMapConfig({
zoom: 100,
minZoom: 100,
maxZoom: -1,
maxZoom: -2,
});
expect(valid).toBeFalsy();
expect(errorText).toMatch('zoom should be <= 20');
expect(errorText).toMatch('minZoom should be <= 20');
expect(errorText).toMatch('maxZoom should be >= 0');
expect(errorText).toMatch('zoom should be <= 24');
expect(errorText).toMatch('minZoom should be <= 24');
expect(errorText).toMatch('maxZoom should be >= -1');
expect(
configService.validateMapConfig({

View File

@ -6,18 +6,18 @@ export default {
// 地图缩放等级
zoom: {
type: 'number',
minimum: 0,
maximum: 20,
minimum: -1,
maximum: 24,
},
minZoom: {
type: 'number',
minimum: 0,
maximum: 20,
minimum: -1,
maximum: 24,
},
maxZoom: {
type: 'number',
minimum: 0,
maximum: 20,
minimum: -1,
maximum: 24,
},
// 地图中心点
center: {

View File

@ -5,7 +5,7 @@ export interface IWarnInfo {
}
const WarnInfo: IWarnInfo = {
MapToken:
'您正在使用 Demo测试地图token如果生环境中使用去对应地图请注册Token',
'您正在使用 Demo测试地图token如果生环境中使用去对应地图请注册Token',
SDK: '请确认引入了mapbox-gl api且在L7之前引入',
};

View File

@ -71,6 +71,10 @@ export interface IMapConfig<RawMap = {}> {
*
*/
mapInstance?: RawMap;
/**
* API插件
*/
plugin?: string[];
/**
* DOM id
*/

View File

@ -424,7 +424,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
this.buildModels();
return this;
}
public style(options: object & Partial<ILayerConfig>): ILayer {
public style(
options: Partial<ChildLayerStyleOptions> & Partial<ILayerConfig>,
): ILayer {
const { passes, ...rest } = options;
// passes 特殊处理
@ -582,7 +584,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
}
public isVisible(): boolean {
const zoom = this.mapService.getZoom();
const {
visible,
minZoom = -Infinity,

View File

@ -11,6 +11,7 @@ import {
ILayer,
ILayerConfig,
ILayerModel,
ILayerService,
IMapService,
IModel,
IModelUniform,
@ -44,6 +45,7 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
protected styleAttributeService: IStyleAttributeService;
protected mapService: IMapService;
protected cameraService: ICameraService;
protected layerService: ILayerService;
constructor(layer: ILayer) {
this.layer = layer;
@ -57,6 +59,10 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
this.cameraService = layer
.getContainer()
.get<ICameraService>(TYPES.ICameraService);
this.layerService = layer
.getContainer()
.get<ILayerService>(TYPES.ILayerService);
// 注册 Attribute
this.registerBuiltinAttributes();
// 开启动画

View File

@ -0,0 +1,35 @@
import BaseLayer from '../core/BaseLayer';
import ImageModels, { ImageModelType } from './models/index';
interface IImageLayerStyleOptions {
opacity: number;
}
export default class ImageLayer extends BaseLayer<IImageLayerStyleOptions> {
public type: string = 'ImageLayer';
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {
image: {},
};
return defaultConfig[type];
}
protected buildModels() {
const modelType = this.getModelType();
this.layerModel = new ImageModels[modelType](this);
this.models = this.layerModel.buildModels();
}
protected getModelType(): ImageModelType {
return 'image';
}
}

View File

@ -0,0 +1,99 @@
import {
AttributeType,
gl,
IEncodeFeature,
ILayer,
ILayerPlugin,
ILogService,
IModel,
IModelUniform,
IRasterParserDataItem,
IStyleAttributeService,
ITexture2D,
lazyInject,
TYPES,
} from '@antv/l7-core';
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
import BaseModel from '../../core/BaseModel';
import { RasterImageTriangulation } from '../../core/triangulation';
import ImageFrag from '../shaders/image_frag.glsl';
import ImageVert from '../shaders/image_vert.glsl';
interface IImageLayerStyleOptions {
opacity: number;
}
export default class ImageModel extends BaseModel {
protected texture: ITexture2D;
public getUninforms(): IModelUniform {
const { opacity } = this.layer.getLayerConfig() as IImageLayerStyleOptions;
return {
u_opacity: opacity || 1,
u_texture: this.texture,
};
}
public buildModels() {
const source = this.layer.getSource();
const { createTexture2D } = this.rendererService;
this.texture = createTexture2D({
height: 0,
width: 0,
});
source.data.images.then((imageData: HTMLImageElement[]) => {
this.texture = createTexture2D({
data: imageData[0],
width: imageData[0].width,
height: imageData[0].height,
});
this.layerService.renderLayers();
});
return [
this.layer.buildLayerModel({
moduleName: 'RasterImage',
vertexShader: ImageVert,
fragmentShader: ImageFrag,
triangulation: RasterImageTriangulation,
primitive: gl.TRIANGLES,
depth: { enable: false },
blend: this.getBlend(),
}),
];
}
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'uv',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Uv',
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]];
},
},
});
}
}

View File

@ -0,0 +1,8 @@
import ImageModel from './image';
export type ImageModelType = 'image';
const ImageModels: { [key in ImageModelType]: any } = {
image: ImageModel,
};
export default ImageModels;

View File

@ -3,11 +3,11 @@ import CityBuildingLayer from './citybuliding/building';
import BaseLayer from './core/BaseLayer';
import './glsl.d';
import HeatmapLayer from './heatmap';
import ImageLayer from './image';
import LineLayer from './line/index';
import PointLayer from './point';
import PolygonLayer from './polygon';
import ImageLayer from './raster/image';
import RasterLayer from './raster/raster';
import RasterLayer from './raster';
import ConfigSchemaValidationPlugin from './plugins/ConfigSchemaValidationPlugin';
import DataMappingPlugin from './plugins/DataMappingPlugin';

View File

@ -1,106 +1,106 @@
import {
AttributeType,
gl,
IEncodeFeature,
ILayer,
ITexture2D,
} from '@antv/l7-core';
import BaseLayer from '../core/BaseLayer';
import { RasterImageTriangulation } from '../core/triangulation';
import rasterImageFrag from './shaders/image_frag.glsl';
import rasterImageVert from './shaders/image_vert.glsl';
interface IRaterLayerStyleOptions {
opacity: number;
}
// import {
// AttributeType,
// gl,
// IEncodeFeature,
// ILayer,
// ITexture2D,
// } from '@antv/l7-core';
// import BaseLayer from '../core/BaseLayer';
// import { RasterImageTriangulation } from '../core/triangulation';
// import rasterImageFrag from './shaders/image_frag.glsl';
// import rasterImageVert from './shaders/image_vert.glsl';
// interface IRaterLayerStyleOptions {
// opacity: number;
// }
export default class ImageLayer extends BaseLayer<IRaterLayerStyleOptions> {
public type: string = 'ImageLayer';
protected texture: ITexture2D;
// export default class ImageLayer extends BaseLayer<IRaterLayerStyleOptions> {
// public type: string = 'ImageLayer';
// protected texture: ITexture2D;
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
// protected getConfigSchema() {
// return {
// properties: {
// opacity: {
// type: 'number',
// minimum: 0,
// maximum: 1,
// },
// },
// };
// }
protected renderModels() {
const { opacity } = this.getLayerConfig();
if (this.texture) {
this.models.forEach((model) =>
model.draw({
uniforms: {
u_opacity: opacity || 1,
u_texture: this.texture,
},
}),
);
}
// protected renderModels() {
// const { opacity } = this.getLayerConfig();
// if (this.texture) {
// this.models.forEach((model) =>
// model.draw({
// uniforms: {
// u_opacity: opacity || 1,
// u_texture: this.texture,
// },
// }),
// );
// }
return this;
}
// return this;
// }
protected buildModels() {
this.registerBuiltinAttributes();
const source = this.getSource();
const { createTexture2D } = this.rendererService;
source.data.images.then((imageData: HTMLImageElement[]) => {
this.texture = createTexture2D({
data: imageData[0],
width: imageData[0].width,
height: imageData[0].height,
});
this.renderModels();
});
this.models = [
this.buildLayerModel({
moduleName: 'RasterImage',
vertexShader: rasterImageVert,
fragmentShader: rasterImageFrag,
triangulation: RasterImageTriangulation,
primitive: gl.TRIANGLES,
depth: { enable: false },
blend: {
enable: true,
func: {
srcRGB: gl.SRC_ALPHA,
srcAlpha: 1,
dstRGB: gl.ONE_MINUS_SRC_ALPHA,
dstAlpha: 1,
},
},
}),
];
}
// protected buildModels() {
// this.registerBuiltinAttributes();
// const source = this.getSource();
// const { createTexture2D } = this.rendererService;
// source.data.images.then((imageData: HTMLImageElement[]) => {
// this.texture = createTexture2D({
// data: imageData[0],
// width: imageData[0].width,
// height: imageData[0].height,
// });
// this.renderModels();
// });
// this.models = [
// this.buildLayerModel({
// moduleName: 'RasterImage',
// vertexShader: rasterImageVert,
// fragmentShader: rasterImageFrag,
// triangulation: RasterImageTriangulation,
// primitive: gl.TRIANGLES,
// depth: { enable: false },
// blend: {
// enable: true,
// func: {
// srcRGB: gl.SRC_ALPHA,
// srcAlpha: 1,
// dstRGB: gl.ONE_MINUS_SRC_ALPHA,
// dstAlpha: 1,
// },
// },
// }),
// ];
// }
private registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'uv',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Uv',
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]];
},
},
});
}
}
// private registerBuiltinAttributes() {
// // point layer size;
// this.styleAttributeService.registerStyleAttribute({
// name: 'uv',
// type: AttributeType.Attribute,
// descriptor: {
// name: 'a_Uv',
// 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]];
// },
// },
// });
// }
// }

View File

@ -0,0 +1,42 @@
import { IColorRamp } from '@antv/l7-utils';
import BaseLayer from '../core/BaseLayer';
import RasterModels, { RasterModelType } from './models/index';
interface IRasterLayerStyleOptions {
opacity: number;
domain: [number, number];
noDataValue: number;
clampLow: boolean;
clampHigh: boolean;
rampColors: IColorRamp;
}
export default class RaterLayer extends BaseLayer<IRasterLayerStyleOptions> {
public type: string = 'RasterLayer';
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
protected getDefaultConfig() {
const type = this.getModelType();
const defaultConfig = {
raster: {},
raster3d: {},
};
return defaultConfig[type];
}
protected buildModels() {
const modelType = this.getModelType();
this.layerModel = new RasterModels[modelType](this);
this.models = this.layerModel.buildModels();
}
protected getModelType(): RasterModelType {
return 'raster';
}
}

View File

@ -0,0 +1,9 @@
import RasterModel from './raster';
export type RasterModelType = 'raster' | 'raster3d';
const RasterModels: { [key in RasterModelType]: any } = {
raster: RasterModel,
raster3d: RasterModel,
};
export default RasterModels;

View File

@ -0,0 +1,113 @@
import {
AttributeType,
gl,
IEncodeFeature,
ILayer,
ILayerPlugin,
ILogService,
IModel,
IModelUniform,
IRasterParserDataItem,
IStyleAttributeService,
ITexture2D,
lazyInject,
TYPES,
} from '@antv/l7-core';
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
import BaseModel from '../../core/BaseModel';
import { RasterImageTriangulation } from '../../core/triangulation';
import rasterFrag from '../shaders/raster_2d_frag.glsl';
import rasterVert from '../shaders/raster_2d_vert.glsl';
interface IRasterLayerStyleOptions {
opacity: number;
domain: [number, number];
noDataValue: number;
clampLow: boolean;
clampHigh: boolean;
rampColors: IColorRamp;
}
export default class RasterModel extends BaseModel {
protected texture: ITexture2D;
protected colorTexture: ITexture2D;
public getUninforms() {
const {
opacity = 1,
clampLow = true,
clampHigh = true,
noDataValue = -9999999,
domain = [0, 1],
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
return {
u_opacity: opacity || 1,
u_texture: this.texture,
u_domain: domain,
u_clampLow: clampLow,
u_clampHigh: typeof clampHigh !== 'undefined' ? clampHigh : clampLow,
u_noDataValue: noDataValue,
u_colorTexture: this.colorTexture,
};
}
public buildModels() {
const source = this.layer.getSource();
const { createTexture2D } = this.rendererService;
const parserDataItem = source.data.dataArray[0];
this.texture = createTexture2D({
data: parserDataItem.data,
width: parserDataItem.width,
height: parserDataItem.height,
format: gl.LUMINANCE,
type: gl.FLOAT,
// aniso: 4,
});
const {
rampColors,
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
const imageData = generateColorRamp(rampColors as IColorRamp);
this.colorTexture = createTexture2D({
data: imageData.data,
width: imageData.width,
height: imageData.height,
flipY: true,
});
return [
this.layer.buildLayerModel({
moduleName: 'RasterImageData',
vertexShader: rasterVert,
fragmentShader: rasterFrag,
triangulation: RasterImageTriangulation,
primitive: gl.TRIANGLES,
depth: { enable: false },
blend: this.getBlend(),
}),
];
}
protected registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({
name: 'uv',
type: AttributeType.Attribute,
descriptor: {
name: 'a_Uv',
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]];
},
},
});
}
}

View File

@ -5,12 +5,14 @@ import {
ILayer,
ILayerPlugin,
ILogService,
IModelUniform,
IRasterParserDataItem,
IStyleAttributeService,
ITexture2D,
lazyInject,
TYPES,
} from '@antv/l7-core';
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
import BaseLayer from '../core/BaseLayer';
import { RasterTriangulation } from './buffers/triangulation';
@ -30,6 +32,9 @@ export default class RasterLayer extends BaseLayer<IRasterLayerStyleOptions> {
protected texture: ITexture2D;
protected colorTexture: ITexture2D;
public getAnimateUniforms(): IModelUniform {
return {};
}
protected getConfigSchema() {
return {
properties: {

View File

@ -4,15 +4,26 @@ uniform sampler2D u_texture;
uniform sampler2D u_colorTexture;
uniform float u_min;
uniform float u_max;
uniform vec2 u_domain;
uniform float u_noDataValue;
uniform bool u_clampLow: true;
uniform bool u_clampHigh: true;
varying vec2 v_texCoord;
void main() {
float value = texture2D(u_texture,vec2(v_texCoord.x,v_texCoord.y)).a;
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);
gl_FragColor = texture2D(u_colorTexture,ramp_pos);;
float value = texture2D(u_texture,vec2(v_texCoord.x,v_texCoord.y)).r;
if (value == u_noDataValue)
gl_FragColor = vec4(0.0, 0, 0, 0.0);
else if ((!u_clampLow && value < u_domain[0]) || (!u_clampHigh && value > u_domain[1]))
gl_FragColor = vec4(0, 0, 0, 0);
else {
float normalisedValue =(value - u_domain[0]) / (u_domain[1] -u_domain[0]);
vec2 ramp_pos = vec2(
fract(16.0 * (1.0 - normalisedValue)),
floor(16.0 * (1.0 - normalisedValue)) / 16.0);
gl_FragColor = texture2D(u_colorTexture, ramp_pos);
}
}

View File

@ -229,6 +229,7 @@ export default class AMapService
maxZoom = 18,
token = AMAP_API_KEY,
mapInstance,
plugin = [],
...rest
} = this.config;
// 高德地图创建独立的container
@ -273,7 +274,9 @@ export default class AMapService
if (token === AMAP_API_KEY) {
this.logger.warn(this.configService.getSceneWarninfo('MapToken'));
}
const url: string = `https://webapi.amap.com/maps?v=${AMAP_VERSION}&key=${token}&plugin=Map3D&callback=initAMap`;
const url: string = `https://webapi.amap.com/maps?v=${AMAP_VERSION}&key=${token}&plugin=Map3D${plugin.join(
',',
)}&callback=initAMap`;
const $jsapi = document.createElement('script');
$jsapi.id = AMAP_SCRIPT_ID;
$jsapi.charset = 'utf-8';

View File

@ -52,7 +52,6 @@ export default class ReglRendererService implements IRendererService {
// TODO: use extensions
extensions: [
'OES_element_index_uint',
// 'EXT_shader_texture_lod', // IBL 兼容性问题
'EXT_blend_minmax',
'OES_standard_derivatives', // wireframe
// 'OES_texture_float', // shadow map 兼容性问题
@ -60,7 +59,7 @@ export default class ReglRendererService implements IRendererService {
'angle_instanced_arrays',
'EXT_texture_filter_anisotropic', // VSM shadow map
],
// optionalExtensions: ['oes_texture_float_linear'],
optionalExtensions: ['oes_texture_float_linear', 'OES_texture_float'],
profile: true,
onDone: (err: Error | null, r?: regl.Regl | undefined): void => {
if (err || !r) {

View File

@ -15,7 +15,7 @@ export default class ImageLayerDemo extends React.Component {
map: new Mapbox({
center: [121.268, 30.3628],
pitch: 0,
style: 'mapbox://styles/mapbox/streets-v9',
style: 'dark',
zoom: 10,
}),
});
@ -30,7 +30,6 @@ export default class ImageLayerDemo extends React.Component {
},
);
scene.addLayer(layer);
scene.render();
this.scene = scene;
}

View File

@ -1,14 +1,19 @@
import { RasterLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import * as dat from 'dat.gui';
// @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;
private gui: dat.GUI;
public componentWillUnmount() {
this.scene.destroy();
if (this.gui) {
this.gui.destroy();
}
}
public async componentDidMount() {
@ -17,7 +22,7 @@ export default class ImageLayerDemo extends React.Component {
map: new Mapbox({
center: [121.268, 30.3628],
pitch: 0,
style: 'mapbox://styles/mapbox/streets-v9',
style: 'dark',
zoom: 2,
}),
});
@ -36,6 +41,8 @@ export default class ImageLayerDemo extends React.Component {
})
.style({
opacity: 0.8,
domain: [100, 4000],
clampLow: true,
rampColors: {
colors: [
'#002466',
@ -53,8 +60,45 @@ export default class ImageLayerDemo extends React.Component {
},
});
scene.addLayer(layer);
scene.render();
this.scene = scene;
/*** 运行时修改样式属性 ***/
const gui = new dat.GUI();
this.gui = gui;
const styleOptions = {
clampLow: true,
clampHigh: true,
noDataValue: -9999999,
min: 100,
max: 4000,
};
const rasterFolder = gui.addFolder('栅格可视化');
rasterFolder.add(styleOptions, 'clampLow').onChange((clampLow: boolean) => {
layer.style({
clampLow,
});
scene.render();
});
rasterFolder
.add(styleOptions, 'clampHigh')
.onChange((clampHigh: boolean) => {
layer.style({
clampHigh,
});
scene.render();
});
rasterFolder.add(styleOptions, 'min', 0, 9000).onChange((min: number) => {
layer.style({
domain: [min, styleOptions.max],
});
scene.render();
});
rasterFolder.add(styleOptions, 'max', 0, 9000).onChange((max: number) => {
layer.style({
domain: [styleOptions.min, max],
});
scene.render();
});
}
public render() {