mirror of https://gitee.com/antv-l7/antv-l7
feat(layers): add heatmap layer
This commit is contained in:
commit
e04b3b268b
|
@ -22,6 +22,8 @@ module.exports = (api) => {
|
|||
'@babel/preset-typescript',
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
'@babel/plugin-proposal-nullish-coalescing-operator',
|
||||
[
|
||||
'@babel/plugin-proposal-decorators',
|
||||
{
|
||||
|
@ -35,7 +37,6 @@ module.exports = (api) => {
|
|||
loose: true,
|
||||
}
|
||||
],
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-transform-modules-commonjs',
|
||||
[
|
||||
|
|
|
@ -50,13 +50,13 @@ ClearPass -> RenderPass -> [ ...其他后处理 Pass ] -> CopyPass
|
|||
| -------- | --- | ------------- | --------- |
|
||||
| ClearPass | normal | 无 | 清除 framebuffer,clearColor 为 [0, 0, 0, 0] |
|
||||
| RenderPass | normal | 无 | 渲染到 framebuffer,作为后续后处理的输入 |
|
||||
| PickingPass | normal | 无 | 负责拾取,[详见](./PixelPickingEngine.md) |
|
||||
| TAAPass | normal | 无 | [详见](./TAA.md) |
|
||||
| CopyPass | post-processing | 无 | 作为后处理最后一个 Pass,负责拷贝 framebuffer 到屏幕输出 |
|
||||
| BlurHPass | post-processing | `blurRadius` 水平方向模糊半径,默认值为 `8.0` | [高斯模糊 blur9](https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/9.glsl) |
|
||||
| BlurVPass | post-processing | `blurRadius` 垂直方向模糊半径,默认值为 `8.0` | 同上 |
|
||||
|
||||
剩余后处理效果见最后一节。
|
||||
后续待实现 Pass 如下:
|
||||
|
||||
- [ ] PickingPass 负责拾取
|
||||
- [ ] ShadowPass 负责生成 shadowMap,供 PCF、CSM 等实时阴影技术使用
|
||||
|
||||
## 使用方法
|
||||
|
@ -76,3 +76,92 @@ const layer = new PolygonLayer({
|
|||
],
|
||||
});
|
||||
```
|
||||
|
||||
## 内置后处理效果
|
||||
|
||||
参考了 [glfx](https://github.com/evanw/glfx.js) 中的一些常用图像处理效果。可以按照名称引用,顺序决定了各个效果的应用次序。例如我们想依次应用噪声和模糊效果:
|
||||
|
||||
```typescript
|
||||
const layer = new PolygonLayer({
|
||||
passes: [
|
||||
[
|
||||
'noise', // 使用 NoisePass
|
||||
{
|
||||
amount: 0.5,
|
||||
},
|
||||
]
|
||||
'blurH', // 使用 BlurHPass
|
||||
'blurV', // 使用 BlurVPass
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
下面详细介绍各个后处理效果及其参数,在 DEMO 中也可以通过 GUI 任意调节参数。
|
||||
|
||||
### 高斯模糊
|
||||
|
||||
采用 [高斯模糊 blur9](https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/9.glsl)。
|
||||
|
||||
名称:`blurH/blurV`
|
||||
|
||||
参数:
|
||||
* `blurRadius` 水平/垂直方向模糊半径,默认值为 `8.0`
|
||||
|
||||
效果如下:
|
||||
|
||||
![](./screenshots/blurpass.png)
|
||||
|
||||
### ColorHalftone
|
||||
|
||||
CMYK halftone 效果
|
||||
|
||||
名称:`colorHalftone`
|
||||
|
||||
参数:
|
||||
* `angle` pattern 旋转角度,默认值为 0
|
||||
* `size` pattern 大小,默认值为 8
|
||||
* `center` `[x, y]` pattern 的中心,默认值为 `[0, 0]`
|
||||
|
||||
效果如下:
|
||||
|
||||
![](./screenshots/halftone.png)
|
||||
|
||||
### 噪声
|
||||
|
||||
噪声效果。
|
||||
|
||||
名称:`noise`
|
||||
|
||||
参数:
|
||||
* `amount` 噪声程度,范围 `[0, 1]`,默认值为 `0.5`
|
||||
|
||||
效果如下:
|
||||
|
||||
![](./screenshots/noise.png)
|
||||
|
||||
### 六边形像素化处理
|
||||
|
||||
六边形像素化处理。
|
||||
|
||||
名称:`hexagonalPixelate`
|
||||
|
||||
参数:
|
||||
* `scale` 六边形大小,默认值为 `10`
|
||||
* `center` `[x, y]` pattern 的中心,默认值为 `[0.5, 0.5]`
|
||||
|
||||
效果如下:
|
||||
|
||||
![](./screenshots/hexagonalPixelate.png)
|
||||
|
||||
### Sepia
|
||||
|
||||
Sepia 颜色映射。
|
||||
|
||||
名称:`sepia`
|
||||
|
||||
参数:
|
||||
* `amount` 程度,范围 `[0, 1]`,默认值为 `0.5`
|
||||
|
||||
效果如下:
|
||||
|
||||
![](./screenshots/sepia.png)
|
|
@ -65,7 +65,7 @@ this.cameraService.jitterProjectionMatrix(
|
|||
|
||||
![](./screenshots/taa-step3.png)
|
||||
|
||||
这里我们选择当前帧权重为 0.9,历史帧为 0.1,最终的混合结果供后续后处理模块继续处理:
|
||||
这里我们选择当前帧权重为 0.9,历史帧为 0.1:
|
||||
|
||||
```typescript
|
||||
useFramebuffer(this.outputRenderTarget, () => {
|
||||
|
@ -83,6 +83,23 @@ useFramebuffer(this.outputRenderTarget, () => {
|
|||
});
|
||||
```
|
||||
|
||||
最后我们将最终的混合结果“拷贝”给后处理模块,实现渐进增强的效果:
|
||||
|
||||
```typescript
|
||||
useFramebuffer(
|
||||
layer.multiPassRenderer.getPostProcessor().getReadFBO(),
|
||||
() => {
|
||||
this.copyModel.draw({
|
||||
uniforms: {
|
||||
u_Texture: this.copyRenderTarget,
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
// 调用后处理模块应用后续效果
|
||||
layer.multiPassRenderer.getPostProcessor().render(layer);
|
||||
```
|
||||
|
||||
## 最终效果
|
||||
|
||||
为了更直观地看到效果,在 DEMO 中我们可以调节相机抖动范围:
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
After Width: | Height: | Size: 895 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.3 MiB |
Binary file not shown.
After Width: | Height: | Size: 847 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,8 @@
|
|||
"devDependencies": {
|
||||
"@babel/cli": "^7.6.4",
|
||||
"@babel/core": "^7.6.4",
|
||||
"@babel/plugin-proposal-decorators": "^7.6.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.6.0",
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
|
@ -111,6 +113,6 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-decorators": "^7.6.0"
|
||||
"geotiff": "^1.0.0-beta.6"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,6 @@ import container, { lazyInject, lazyMultiInject } from './inversify.config';
|
|||
import ClearPass from './services/renderer/passes/ClearPass';
|
||||
import MultiPassRenderer from './services/renderer/passes/MultiPassRenderer';
|
||||
import PixelPickingPass from './services/renderer/passes/PixelPickingPass';
|
||||
import BlurHPass from './services/renderer/passes/post-processing/BlurHPass';
|
||||
import BlurVPass from './services/renderer/passes/post-processing/BlurVPass';
|
||||
import CopyPass from './services/renderer/passes/post-processing/CopyPass';
|
||||
import RenderPass from './services/renderer/passes/RenderPass';
|
||||
import TAAPass from './services/renderer/passes/TAAPass';
|
||||
import { TYPES } from './types';
|
||||
|
@ -30,9 +27,6 @@ export {
|
|||
ClearPass,
|
||||
RenderPass,
|
||||
PixelPickingPass,
|
||||
BlurHPass,
|
||||
BlurVPass,
|
||||
CopyPass,
|
||||
TAAPass,
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,18 @@ import StyleAttributeService from './services/layer/StyleAttributeService';
|
|||
import LogService from './services/log/LogService';
|
||||
import SceneService from './services/scene/SceneService';
|
||||
import ShaderModuleService from './services/shader/ShaderModuleService';
|
||||
|
||||
/** PostProcessing passes */
|
||||
import { IPostProcessingPass } from './services/renderer/IMultiPassRenderer';
|
||||
import BlurHPass from './services/renderer/passes/post-processing/BlurHPass';
|
||||
import BlurVPass from './services/renderer/passes/post-processing/BlurVPass';
|
||||
import ColorHalfTonePass from './services/renderer/passes/post-processing/ColorHalfTonePass';
|
||||
import CopyPass from './services/renderer/passes/post-processing/CopyPass';
|
||||
import HexagonalPixelatePass from './services/renderer/passes/post-processing/HexagonalPixelatePass';
|
||||
import InkPass from './services/renderer/passes/post-processing/InkPass';
|
||||
import NoisePass from './services/renderer/passes/post-processing/NoisePass';
|
||||
import SepiaPass from './services/renderer/passes/post-processing/SepiaPass';
|
||||
|
||||
// @see https://github.com/inversify/InversifyJS/blob/master/wiki/container_api.md#defaultscope
|
||||
const container = new Container();
|
||||
|
||||
|
@ -140,4 +152,51 @@ export const lazyMultiInject = (
|
|||
};
|
||||
};
|
||||
|
||||
// 绑定 post processing passes
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(CopyPass)
|
||||
.whenTargetNamed('copy');
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(BlurHPass)
|
||||
.whenTargetNamed('blurH');
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(BlurVPass)
|
||||
.whenTargetNamed('blurV');
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(NoisePass)
|
||||
.whenTargetNamed('noise');
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(SepiaPass)
|
||||
.whenTargetNamed('sepia');
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(ColorHalfTonePass)
|
||||
.whenTargetNamed('colorHalftone');
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(HexagonalPixelatePass)
|
||||
.whenTargetNamed('hexagonalPixelate');
|
||||
container
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.INewablePostProcessingPass)
|
||||
.to(InkPass)
|
||||
.whenTargetNamed('ink');
|
||||
|
||||
container
|
||||
.bind<interfaces.Factory<IPostProcessingPass<unknown>>>(
|
||||
TYPES.IFactoryPostProcessingPass,
|
||||
)
|
||||
.toFactory<IPostProcessingPass<unknown>>((context) => {
|
||||
return (named: string) => {
|
||||
return context.container.getNamed<IPostProcessingPass<unknown>>(
|
||||
TYPES.INewablePostProcessingPass,
|
||||
named,
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default container;
|
||||
|
|
|
@ -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
|
||||
|
@ -129,6 +131,7 @@ export interface IStyleAttribute extends IStyleAttributeInitializationOptions {
|
|||
|
||||
export type Triangulation = (
|
||||
feature: IEncodeFeature,
|
||||
parserData: IParseDataItem,
|
||||
) => {
|
||||
vertices: number[];
|
||||
indices: number[];
|
||||
|
@ -158,6 +161,7 @@ export interface IStyleAttributeService {
|
|||
createAttributesAndIndices(
|
||||
encodedFeatures: IEncodeFeature[],
|
||||
triangulation: Triangulation,
|
||||
parserData: IParseDataItem[],
|
||||
): {
|
||||
attributes: {
|
||||
[attributeName: string]: IAttribute;
|
||||
|
|
|
@ -4,7 +4,6 @@ import {
|
|||
StyleScaleType,
|
||||
} from '../layer/IStyleAttributeService';
|
||||
import { IAttribute } from '../renderer/IAttribute';
|
||||
import { IBuffer } from '../renderer/IBuffer';
|
||||
import {
|
||||
AttributeType,
|
||||
IEncodeFeature,
|
||||
|
@ -45,8 +44,6 @@ export default class StyleAttribute implements IStyleAttribute {
|
|||
};
|
||||
public vertexAttribute: IAttribute;
|
||||
|
||||
private buffer: IBuffer;
|
||||
|
||||
constructor(options: Partial<IStyleAttributeInitializationOptions>) {
|
||||
this.setProps(options);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
@ -48,8 +49,7 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
public registerStyleAttribute(
|
||||
options: Partial<IStyleAttributeInitializationOptions>,
|
||||
) {
|
||||
let attributeToUpdate =
|
||||
options.name && this.getLayerStyleAttribute(options.name);
|
||||
let attributeToUpdate = this.getLayerStyleAttribute(options.name || '');
|
||||
if (attributeToUpdate) {
|
||||
attributeToUpdate.setProps(options);
|
||||
} else {
|
||||
|
@ -72,7 +72,7 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
});
|
||||
}
|
||||
const { scale } = options;
|
||||
if (scale) {
|
||||
if (scale && attributeToUpdate) {
|
||||
// TODO: 需要比较新旧值确定是否需要 rescale
|
||||
// 需要重新 scale,肯定也需要重新进行数据映射
|
||||
attributeToUpdate.scale = scale;
|
||||
|
@ -167,6 +167,7 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
public createAttributesAndIndices(
|
||||
features: IEncodeFeature[],
|
||||
triangulation: Triangulation,
|
||||
parserData: IParseDataItem[],
|
||||
): {
|
||||
attributes: {
|
||||
[attributeName: string]: IAttribute;
|
||||
|
@ -187,7 +188,7 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
vertices: verticesForCurrentFeature,
|
||||
normals: normalsForCurrentFeature,
|
||||
size: vertexSize,
|
||||
} = triangulation(feature);
|
||||
} = triangulation(feature, parserData[featureIdx]);
|
||||
indices.push(...indicesForCurrentFeature.map((i) => i + verticesNum));
|
||||
vertices.push(...verticesForCurrentFeature);
|
||||
if (normalsForCurrentFeature) {
|
||||
|
@ -278,7 +279,9 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
public clearAllAttributes() {
|
||||
// 销毁关联的 vertex attribute buffer objects
|
||||
this.attributes.forEach((attribute) => {
|
||||
attribute.vertexAttribute.destroy();
|
||||
if (attribute.vertexAttribute) {
|
||||
attribute.vertexAttribute.destroy();
|
||||
}
|
||||
});
|
||||
this.attributes = [];
|
||||
}
|
||||
|
|
|
@ -12,9 +12,10 @@ export enum PassType {
|
|||
* 2. PostProcessing eg. CopyPass、BlurPass
|
||||
* 另外考虑到 Pass 之间严格的执行顺序,render 方法必须是异步的
|
||||
*/
|
||||
export interface IPass {
|
||||
export interface IPass<InitializationOptions> {
|
||||
getName(): string;
|
||||
getType(): PassType;
|
||||
init(layer: ILayer): void;
|
||||
init(layer: ILayer, config?: Partial<InitializationOptions>): void;
|
||||
render(layer: ILayer): void;
|
||||
}
|
||||
|
||||
|
@ -22,24 +23,33 @@ export interface IPass {
|
|||
* PostProcessing,自动切换 renderTarget
|
||||
* 例如最后一个 PostProcessingPass 自动切换 renderTarget 为屏幕
|
||||
*/
|
||||
export interface IPostProcessingPass extends IPass {
|
||||
export interface IPostProcessingPass<InitializationOptions>
|
||||
extends IPass<InitializationOptions> {
|
||||
setRenderToScreen(renderToScreen: boolean): void;
|
||||
isEnabled(): boolean;
|
||||
setEnabled(enabled: boolean): void;
|
||||
updateOptions(config: Partial<InitializationOptions>): void;
|
||||
}
|
||||
|
||||
export interface IPostProcessor {
|
||||
getReadFBO(): IFramebuffer;
|
||||
getWriteFBO(): IFramebuffer;
|
||||
resize(viewportWidth: number, viewportHeight: number): void;
|
||||
add(pass: IPostProcessingPass, layer: ILayer): void;
|
||||
add<InitializationOptions>(
|
||||
pass: IPostProcessingPass<InitializationOptions>,
|
||||
layer: ILayer,
|
||||
config?: Partial<InitializationOptions>,
|
||||
): void;
|
||||
render(layer: ILayer): Promise<unknown>;
|
||||
getPostProcessingPassByName(
|
||||
name: string,
|
||||
): IPostProcessingPass<unknown> | undefined;
|
||||
}
|
||||
|
||||
export interface IMultiPassRenderer {
|
||||
getPostProcessor(): IPostProcessor;
|
||||
resize(viewportWidth: number, viewportHeight: number): void;
|
||||
add(pass: IPass): void;
|
||||
add<InitializationOptions>(pass: IPass<InitializationOptions>): void;
|
||||
render(): void;
|
||||
getRenderFlag(): boolean;
|
||||
setRenderFlag(enabled: boolean): void;
|
||||
|
|
|
@ -15,7 +15,7 @@ export interface IRenderConfig {
|
|||
* 是否开启 multi pass
|
||||
*/
|
||||
enableMultiPassRenderer?: boolean;
|
||||
passes?: IPass[];
|
||||
passes?: Array<IPass<unknown>>;
|
||||
}
|
||||
|
||||
export interface IClearOptions {
|
||||
|
|
|
@ -39,7 +39,8 @@ export interface ITexture2DInitializationOptions {
|
|||
| number[][]
|
||||
| Uint8Array
|
||||
| Uint16Array
|
||||
| Uint32Array;
|
||||
| Uint32Array
|
||||
| Uint8ClampedArray;
|
||||
|
||||
/**
|
||||
* 纹理参数
|
||||
|
|
|
@ -4,7 +4,6 @@ import {
|
|||
IModel,
|
||||
IRendererService,
|
||||
IShaderModuleService,
|
||||
lazyInject,
|
||||
} from '../../../index';
|
||||
import { TYPES } from '../../../types';
|
||||
import { ILayer } from '../../layer/ILayerService';
|
||||
|
@ -18,11 +17,11 @@ import { IUniform } from '../IUniform';
|
|||
*/
|
||||
@injectable()
|
||||
export default class BasePostProcessingPass<InitializationOptions = {}>
|
||||
implements IPostProcessingPass {
|
||||
@lazyInject(TYPES.IShaderModuleService)
|
||||
implements IPostProcessingPass<InitializationOptions> {
|
||||
@inject(TYPES.IShaderModuleService)
|
||||
protected readonly shaderModule: IShaderModuleService;
|
||||
|
||||
@lazyInject(TYPES.IRendererService)
|
||||
@inject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
protected config: Partial<InitializationOptions> | undefined;
|
||||
|
@ -42,15 +41,19 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
|||
*/
|
||||
private model: IModel;
|
||||
|
||||
constructor(config?: Partial<InitializationOptions>) {
|
||||
this.config = config;
|
||||
private optionsToUpdate: Partial<InitializationOptions> = {};
|
||||
|
||||
public getName() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public getType() {
|
||||
return PassType.PostProcessing;
|
||||
}
|
||||
|
||||
public init() {
|
||||
public init(layer: ILayer, config?: Partial<InitializationOptions>) {
|
||||
this.config = config;
|
||||
|
||||
const { createAttribute, createBuffer, createModel } = this.rendererService;
|
||||
const { vs, fs, uniforms } = this.setupShaders();
|
||||
|
||||
|
@ -71,6 +74,7 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
|||
uniforms: {
|
||||
u_Texture: null,
|
||||
...uniforms,
|
||||
...(this.config && this.convertOptionsToUniforms(this.config)),
|
||||
},
|
||||
depth: {
|
||||
enable: false,
|
||||
|
@ -81,7 +85,8 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
|||
|
||||
public render(layer: ILayer) {
|
||||
const postProcessor = layer.multiPassRenderer.getPostProcessor();
|
||||
const { useFramebuffer } = this.rendererService;
|
||||
const { useFramebuffer, getViewportSize } = this.rendererService;
|
||||
const { width, height } = getViewportSize();
|
||||
|
||||
useFramebuffer(
|
||||
this.renderToScreen ? null : postProcessor.getWriteFBO(),
|
||||
|
@ -89,6 +94,8 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
|||
this.model.draw({
|
||||
uniforms: {
|
||||
u_Texture: postProcessor.getReadFBO(),
|
||||
u_ViewportSize: [width, height],
|
||||
...this.convertOptionsToUniforms(this.optionsToUpdate),
|
||||
},
|
||||
});
|
||||
},
|
||||
|
@ -107,6 +114,13 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
|||
this.renderToScreen = renderToScreen;
|
||||
}
|
||||
|
||||
public updateOptions(config: Partial<InitializationOptions>) {
|
||||
this.optionsToUpdate = {
|
||||
...this.optionsToUpdate,
|
||||
...config,
|
||||
};
|
||||
}
|
||||
|
||||
protected setupShaders(): {
|
||||
vs: string;
|
||||
fs: string;
|
||||
|
@ -114,4 +128,12 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
|||
} {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<InitializationOptions>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ import { IRendererService } from '../IRendererService';
|
|||
* ClearPass
|
||||
*/
|
||||
@injectable()
|
||||
export default class ClearPass implements IPass {
|
||||
export default class ClearPass<InitializationOptions = {}>
|
||||
implements IPass<InitializationOptions> {
|
||||
@lazyInject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
|
@ -16,6 +17,10 @@ export default class ClearPass implements IPass {
|
|||
return PassType.Normal;
|
||||
}
|
||||
|
||||
public getName() {
|
||||
return 'clear';
|
||||
}
|
||||
|
||||
public init() {
|
||||
//
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import PostProcessor from './PostProcessor';
|
|||
*/
|
||||
@injectable()
|
||||
export default class MultiPassRenderer implements IMultiPassRenderer {
|
||||
private passes: IPass[] = [];
|
||||
private passes: Array<IPass<unknown>> = [];
|
||||
private postProcessor: IPostProcessor;
|
||||
|
||||
private layer: ILayer;
|
||||
|
@ -64,17 +64,21 @@ export default class MultiPassRenderer implements IMultiPassRenderer {
|
|||
this.postProcessor.resize(width, height);
|
||||
}
|
||||
|
||||
public add(pass: IPass) {
|
||||
public add<T>(pass: IPass<T>, config?: Partial<T>) {
|
||||
if (pass.getType() === PassType.PostProcessing) {
|
||||
this.postProcessor.add(pass as IPostProcessingPass, this.layer);
|
||||
this.postProcessor.add<T>(
|
||||
pass as IPostProcessingPass<T>,
|
||||
this.layer,
|
||||
config,
|
||||
);
|
||||
} else {
|
||||
pass.init(this.layer);
|
||||
pass.init(this.layer, config);
|
||||
this.passes.push(pass);
|
||||
}
|
||||
}
|
||||
|
||||
public insert(pass: IPass, index: number) {
|
||||
pass.init(this.layer);
|
||||
public insert<T>(pass: IPass<T>, config: Partial<T>, index: number) {
|
||||
pass.init(this.layer, config);
|
||||
this.passes.splice(index, 0, pass);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ function decodePickingColor(color: Uint8Array): number {
|
|||
* @see https://github.com/antvis/L7/blob/next/dev-docs/PixelPickingEngine.md
|
||||
*/
|
||||
@injectable()
|
||||
export default class PixelPickingPass implements IPass {
|
||||
export default class PixelPickingPass<InitializationOptions = {}> implements IPass<InitializationOptions> {
|
||||
@lazyInject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
|
@ -53,6 +53,10 @@ export default class PixelPickingPass implements IPass {
|
|||
return PassType.Normal;
|
||||
}
|
||||
|
||||
public getName() {
|
||||
return 'pixelPicking';
|
||||
}
|
||||
|
||||
public init(layer: ILayer) {
|
||||
this.layer = layer;
|
||||
const { createTexture2D, createFramebuffer } = this.rendererService;
|
||||
|
|
|
@ -16,7 +16,7 @@ export default class PostProcessor implements IPostProcessor {
|
|||
@lazyInject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
private passes: IPostProcessingPass[] = [];
|
||||
private passes: Array<IPostProcessingPass<unknown>> = [];
|
||||
private readFBO: IFramebuffer;
|
||||
private writeFBO: IFramebuffer;
|
||||
|
||||
|
@ -75,16 +75,31 @@ export default class PostProcessor implements IPostProcessor {
|
|||
});
|
||||
}
|
||||
|
||||
public add(pass: IPostProcessingPass, layer: ILayer) {
|
||||
pass.init(layer);
|
||||
public add<T>(
|
||||
pass: IPostProcessingPass<T>,
|
||||
layer: ILayer,
|
||||
config?: Partial<T>,
|
||||
) {
|
||||
pass.init(layer, config);
|
||||
this.passes.push(pass);
|
||||
}
|
||||
|
||||
public insert(pass: IPostProcessingPass, index: number, layer: ILayer) {
|
||||
pass.init(layer);
|
||||
public insert<T>(
|
||||
pass: IPostProcessingPass<T>,
|
||||
index: number,
|
||||
layer: ILayer,
|
||||
config?: Partial<T>,
|
||||
) {
|
||||
pass.init(layer, config);
|
||||
this.passes.splice(index, 0, pass);
|
||||
}
|
||||
|
||||
public getPostProcessingPassByName(
|
||||
name: string,
|
||||
): IPostProcessingPass<unknown> | undefined {
|
||||
return this.passes.find((p) => p.getName() === name);
|
||||
}
|
||||
|
||||
private isLastEnabledPass(index: number): boolean {
|
||||
for (let i = index + 1; i < this.passes.length; i++) {
|
||||
if (this.passes[i].isEnabled()) {
|
||||
|
|
|
@ -9,7 +9,8 @@ import { IRendererService } from '../IRendererService';
|
|||
* RenderPass,负责输出到后续 PostProcessor 的 readFBO 中
|
||||
*/
|
||||
@injectable()
|
||||
export default class RenderPass implements IPass {
|
||||
export default class RenderPass<InitializationOptions = {}>
|
||||
implements IPass<InitializationOptions> {
|
||||
@lazyInject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
|
@ -17,6 +18,10 @@ export default class RenderPass implements IPass {
|
|||
return PassType.Normal;
|
||||
}
|
||||
|
||||
public getName() {
|
||||
return 'render';
|
||||
}
|
||||
|
||||
public init(layer: ILayer) {
|
||||
//
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ let accumulatingId = 1;
|
|||
* @see https://yuque.antfin-inc.com/yuqi.pyq/fgetpa/ri52hv
|
||||
*/
|
||||
@injectable()
|
||||
export default class TAAPass implements IPass {
|
||||
export default class TAAPass<InitializationOptions = {}>
|
||||
implements IPass<InitializationOptions> {
|
||||
@lazyInject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
|
@ -84,6 +85,10 @@ export default class TAAPass implements IPass {
|
|||
return PassType.Normal;
|
||||
}
|
||||
|
||||
public getName() {
|
||||
return 'taa';
|
||||
}
|
||||
|
||||
public init(layer: ILayer) {
|
||||
const { createFramebuffer, createTexture2D } = this.rendererService;
|
||||
this.sampleRenderTarget = createFramebuffer({
|
||||
|
@ -258,13 +263,17 @@ export default class TAAPass implements IPass {
|
|||
});
|
||||
});
|
||||
|
||||
useFramebuffer(null, () => {
|
||||
this.copyModel.draw({
|
||||
uniforms: {
|
||||
u_Texture: this.copyRenderTarget,
|
||||
},
|
||||
});
|
||||
});
|
||||
useFramebuffer(
|
||||
layer.multiPassRenderer.getPostProcessor().getReadFBO(),
|
||||
() => {
|
||||
this.copyModel.draw({
|
||||
uniforms: {
|
||||
u_Texture: this.copyRenderTarget,
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
layer.multiPassRenderer.getPostProcessor().render(layer);
|
||||
}
|
||||
|
||||
// 保存前序帧结果
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { lazyInject } from '../../../../index';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import blur from '../../../../shaders/post-processing/blur.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { TYPES } from '../../../../types';
|
||||
import { IRendererService } from '../../IRendererService';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface IBlurHPassConfig {
|
||||
blurRadius: number;
|
||||
}
|
||||
|
||||
const defaultConfig: IBlurHPassConfig = {
|
||||
blurRadius: 8.0,
|
||||
};
|
||||
|
||||
@injectable()
|
||||
export default class BlurHPass extends BasePostProcessingPass<
|
||||
IBlurHPassConfig
|
||||
> {
|
||||
@lazyInject(TYPES.IRendererService)
|
||||
@inject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
public setupShaders() {
|
||||
public getName() {
|
||||
return 'blurH';
|
||||
}
|
||||
|
||||
protected setupShaders() {
|
||||
this.shaderModule.registerModule('blur-pass', {
|
||||
vs: quad,
|
||||
fs: blur,
|
||||
|
@ -30,19 +31,29 @@ export default class BlurHPass extends BasePostProcessingPass<
|
|||
const { vs, fs, uniforms } = this.shaderModule.getModule('blur-pass');
|
||||
const { width, height } = this.rendererService.getViewportSize();
|
||||
|
||||
const { blurRadius } = {
|
||||
...defaultConfig,
|
||||
...this.config,
|
||||
};
|
||||
|
||||
return {
|
||||
vs,
|
||||
fs,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
u_BlurDir: [blurRadius, 0],
|
||||
u_ViewportSize: [width, height],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<IBlurHPassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.blurRadius)) {
|
||||
uniforms.u_BlurDir = [options.blurRadius, 0];
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,27 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { lazyInject } from '../../../../index';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import blur from '../../../../shaders/post-processing/blur.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { TYPES } from '../../../../types';
|
||||
import { IRendererService } from '../../IRendererService';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface IBlurVPassConfig {
|
||||
blurRadius: number;
|
||||
}
|
||||
|
||||
const defaultConfig: IBlurVPassConfig = {
|
||||
blurRadius: 8.0,
|
||||
};
|
||||
|
||||
@injectable()
|
||||
export default class BlurVPass extends BasePostProcessingPass<
|
||||
IBlurVPassConfig
|
||||
> {
|
||||
@lazyInject(TYPES.IRendererService)
|
||||
@inject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
public getName() {
|
||||
return 'blurV';
|
||||
}
|
||||
|
||||
public setupShaders() {
|
||||
this.shaderModule.registerModule('blur-pass', {
|
||||
vs: quad,
|
||||
|
@ -30,19 +31,29 @@ export default class BlurVPass extends BasePostProcessingPass<
|
|||
const { vs, fs, uniforms } = this.shaderModule.getModule('blur-pass');
|
||||
const { width, height } = this.rendererService.getViewportSize();
|
||||
|
||||
const { blurRadius } = {
|
||||
...defaultConfig,
|
||||
...this.config,
|
||||
};
|
||||
|
||||
return {
|
||||
vs,
|
||||
fs,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
u_BlurDir: [0, blurRadius],
|
||||
u_ViewportSize: [width, height],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<IBlurVPassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.blurRadius)) {
|
||||
uniforms.u_BlurDir = [0, options.blurRadius];
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import { inject, injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import colorHalftone from '../../../../shaders/post-processing/colorhalftone.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { TYPES } from '../../../../types';
|
||||
import { IRendererService } from '../../IRendererService';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface IColorHalftonePassConfig {
|
||||
center: [number, number];
|
||||
angle: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export default class ColorHalftonePass extends BasePostProcessingPass<
|
||||
IColorHalftonePassConfig
|
||||
> {
|
||||
@inject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
public getName() {
|
||||
return 'colorHalftone';
|
||||
}
|
||||
|
||||
protected setupShaders() {
|
||||
this.shaderModule.registerModule('colorhalftone-pass', {
|
||||
vs: quad,
|
||||
fs: colorHalftone,
|
||||
});
|
||||
|
||||
const { vs, fs, uniforms } = this.shaderModule.getModule(
|
||||
'colorhalftone-pass',
|
||||
);
|
||||
const { width, height } = this.rendererService.getViewportSize();
|
||||
|
||||
return {
|
||||
vs,
|
||||
fs,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
u_ViewportSize: [width, height],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<IColorHalftonePassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.center)) {
|
||||
uniforms.u_Center = options.center;
|
||||
}
|
||||
|
||||
if (!isNil(options.angle)) {
|
||||
uniforms.u_Angle = options.angle;
|
||||
}
|
||||
|
||||
if (!isNil(options.size)) {
|
||||
uniforms.u_Size = options.size;
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,15 @@
|
|||
import { injectable } from 'inversify';
|
||||
import copy from '../../../../shaders/post-processing/copy.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
@injectable()
|
||||
export default class CopyPass extends BasePostProcessingPass {
|
||||
public getName() {
|
||||
return 'copy';
|
||||
}
|
||||
|
||||
public setupShaders() {
|
||||
this.shaderModule.registerModule('copy-pass', {
|
||||
vs: quad,
|
||||
|
@ -13,4 +18,12 @@ export default class CopyPass extends BasePostProcessingPass {
|
|||
|
||||
return this.shaderModule.getModule('copy-pass');
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<{}>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
import { inject, injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import hexagonalPixelate from '../../../../shaders/post-processing/hexagonalpixelate.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { TYPES } from '../../../../types';
|
||||
import { IRendererService } from '../../IRendererService';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface IHexagonalPixelatePassConfig {
|
||||
center: [number, number];
|
||||
scale: number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export default class HexagonalPixelatePass extends BasePostProcessingPass<
|
||||
IHexagonalPixelatePassConfig
|
||||
> {
|
||||
@inject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
public getName() {
|
||||
return 'hexagonalPixelate';
|
||||
}
|
||||
|
||||
protected setupShaders() {
|
||||
this.shaderModule.registerModule('hexagonalpixelate-pass', {
|
||||
vs: quad,
|
||||
fs: hexagonalPixelate,
|
||||
});
|
||||
|
||||
const { vs, fs, uniforms } = this.shaderModule.getModule(
|
||||
'hexagonalpixelate-pass',
|
||||
);
|
||||
const { width, height } = this.rendererService.getViewportSize();
|
||||
|
||||
return {
|
||||
vs,
|
||||
fs,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
u_ViewportSize: [width, height],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<IHexagonalPixelatePassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.center)) {
|
||||
uniforms.u_Center = options.center;
|
||||
}
|
||||
|
||||
if (!isNil(options.scale)) {
|
||||
uniforms.u_Scale = options.scale;
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
import { inject, injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import ink from '../../../../shaders/post-processing/ink.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { TYPES } from '../../../../types';
|
||||
import { IRendererService } from '../../IRendererService';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface IInkPassConfig {
|
||||
strength: number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export default class InkPass extends BasePostProcessingPass<IInkPassConfig> {
|
||||
@inject(TYPES.IRendererService)
|
||||
protected readonly rendererService: IRendererService;
|
||||
|
||||
public getName() {
|
||||
return 'ink';
|
||||
}
|
||||
|
||||
protected setupShaders() {
|
||||
this.shaderModule.registerModule('ink-pass', {
|
||||
vs: quad,
|
||||
fs: ink,
|
||||
});
|
||||
|
||||
const { vs, fs, uniforms } = this.shaderModule.getModule('ink-pass');
|
||||
const { width, height } = this.rendererService.getViewportSize();
|
||||
|
||||
return {
|
||||
vs,
|
||||
fs,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
u_ViewportSize: [width, height],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<IInkPassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.strength)) {
|
||||
uniforms.u_Strength = options.strength;
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import noise from '../../../../shaders/post-processing/noise.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface INoisePassConfig {
|
||||
amount: number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export default class NoisePass extends BasePostProcessingPass<
|
||||
INoisePassConfig
|
||||
> {
|
||||
public getName() {
|
||||
return 'noise';
|
||||
}
|
||||
|
||||
public setupShaders() {
|
||||
this.shaderModule.registerModule('noise-pass', {
|
||||
vs: quad,
|
||||
fs: noise,
|
||||
});
|
||||
|
||||
return this.shaderModule.getModule('noise-pass');
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<INoisePassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.amount)) {
|
||||
uniforms.u_Amount = options.amount;
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import sepia from '../../../../shaders/post-processing/sepia.glsl';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface ISepiaPassConfig {
|
||||
amount: number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export default class SepiaPass extends BasePostProcessingPass<
|
||||
ISepiaPassConfig
|
||||
> {
|
||||
public getName() {
|
||||
return 'sepia';
|
||||
}
|
||||
|
||||
public setupShaders() {
|
||||
this.shaderModule.registerModule('sepia-pass', {
|
||||
vs: quad,
|
||||
fs: sepia,
|
||||
});
|
||||
|
||||
return this.shaderModule.getModule('sepia-pass');
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<ISepiaPassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.amount)) {
|
||||
uniforms.u_Amount = options.amount;
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ import { uniq } from 'lodash';
|
|||
import { extractUniforms } from '../../utils/shader-module';
|
||||
import { IModuleParams, IShaderModuleService } from './IShaderModuleService';
|
||||
|
||||
import common from '../../shaders/common.glsl';
|
||||
import decode from '../../shaders/decode.glsl';
|
||||
import lighting from '../../shaders/lighting.glsl';
|
||||
import pickingFrag from '../../shaders/picking.frag.glsl';
|
||||
|
@ -21,6 +22,7 @@ export default class ShaderModuleService implements IShaderModuleService {
|
|||
private rawContentCache: { [key: string]: IModuleParams } = {};
|
||||
|
||||
public registerBuiltinModules() {
|
||||
this.registerModule('common', { vs: common, fs: common });
|
||||
this.registerModule('decode', { vs: decode, fs: '' });
|
||||
this.registerModule('projection', { vs: projection, fs: '' });
|
||||
this.registerModule('sdf_2d', { vs: '', fs: sdf2d });
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#define PI 3.14159265359
|
|
@ -0,0 +1,44 @@
|
|||
varying vec2 v_UV;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
uniform vec2 u_ViewportSize: [1.0, 1.0];
|
||||
uniform vec2 u_Center : [0.5, 0.5];
|
||||
uniform float u_Angle : 0;
|
||||
uniform float u_Size : 8;
|
||||
|
||||
#pragma include "common"
|
||||
|
||||
float scale = PI / u_Size;
|
||||
|
||||
float pattern(float u_Angle, vec2 texSize, vec2 texCoord) {
|
||||
float s = sin(u_Angle), c = cos(u_Angle);
|
||||
vec2 tex = texCoord * texSize - u_Center * texSize;
|
||||
vec2 point = vec2(
|
||||
c * tex.x - s * tex.y,
|
||||
s * tex.x + c * tex.y
|
||||
) * scale;
|
||||
return (sin(point.x) * sin(point.y)) * 4.0;
|
||||
}
|
||||
|
||||
// https://github.com/evanw/glfx.js/blob/master/src/filters/fun/colorhalftone.js
|
||||
vec4 colorHalftone_filterColor(vec4 color, vec2 texSize, vec2 texCoord) {
|
||||
vec3 cmy = 1.0 - color.rgb;
|
||||
float k = min(cmy.x, min(cmy.y, cmy.z));
|
||||
cmy = (cmy - k) / (1.0 - k);
|
||||
cmy = clamp(
|
||||
cmy * 10.0 - 3.0 + vec3(
|
||||
pattern(u_Angle + 0.26179, texSize, texCoord),
|
||||
pattern(u_Angle + 1.30899, texSize, texCoord),
|
||||
pattern(u_Angle, texSize, texCoord)
|
||||
),
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
k = clamp(k * 10.0 - 5.0 + pattern(u_Angle + 0.78539, texSize, texCoord), 0.0, 1.0);
|
||||
return vec4(1.0 - cmy - k, color.a);
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(texture2D(u_Texture, v_UV));
|
||||
gl_FragColor = colorHalftone_filterColor(gl_FragColor, u_ViewportSize, v_UV);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
varying vec2 v_UV;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
uniform vec2 u_ViewportSize: [1.0, 1.0];
|
||||
uniform vec2 u_Center : [0.5, 0.5];
|
||||
uniform float u_Scale : 10;
|
||||
|
||||
// https://github.com/evanw/glfx.js/blob/master/src/filters/fun/hexagonalpixelate.js
|
||||
vec4 hexagonalPixelate_sampleColor(sampler2D texture, vec2 texSize, vec2 texCoord) {
|
||||
vec2 tex = (texCoord * texSize - u_Center * texSize) / u_Scale;
|
||||
tex.y /= 0.866025404;
|
||||
tex.x -= tex.y * 0.5;
|
||||
vec2 a;
|
||||
if (tex.x + tex.y - floor(tex.x) - floor(tex.y) < 1.0) {
|
||||
a = vec2(floor(tex.x), floor(tex.y));
|
||||
}
|
||||
else a = vec2(ceil(tex.x), ceil(tex.y));
|
||||
vec2 b = vec2(ceil(tex.x), floor(tex.y));
|
||||
vec2 c = vec2(floor(tex.x), ceil(tex.y));
|
||||
vec3 TEX = vec3(tex.x, tex.y, 1.0 - tex.x - tex.y);
|
||||
vec3 A = vec3(a.x, a.y, 1.0 - a.x - a.y);
|
||||
vec3 B = vec3(b.x, b.y, 1.0 - b.x - b.y);
|
||||
vec3 C = vec3(c.x, c.y, 1.0 - c.x - c.y);
|
||||
float alen = length(TEX - A);
|
||||
float blen = length(TEX - B);
|
||||
float clen = length(TEX - C);
|
||||
vec2 choice;
|
||||
if (alen < blen) {
|
||||
if (alen < clen) choice = a;
|
||||
else choice = c;
|
||||
} else {
|
||||
if (blen < clen) choice = b;
|
||||
else choice = c;
|
||||
}
|
||||
choice.x += choice.y * 0.5;
|
||||
choice.y *= 0.866025404;
|
||||
choice *= u_Scale / texSize;
|
||||
return texture2D(texture, choice + u_Center);
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(texture2D(u_Texture, v_UV));
|
||||
gl_FragColor = hexagonalPixelate_sampleColor(u_Texture, u_ViewportSize, v_UV);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
varying vec2 v_UV;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
uniform vec2 u_ViewportSize: [1.0, 1.0];
|
||||
uniform float u_Strength : 0.6;
|
||||
|
||||
vec4 ink_sampleColor(sampler2D texture, vec2 texSize, vec2 texCoord) {
|
||||
vec2 dx = vec2(1.0 / texSize.x, 0.0);
|
||||
vec2 dy = vec2(0.0, 1.0 / texSize.y);
|
||||
vec4 color = texture2D(texture, texCoord);
|
||||
float bigTotal = 0.0;
|
||||
float smallTotal = 0.0;
|
||||
vec3 bigAverage = vec3(0.0);
|
||||
vec3 smallAverage = vec3(0.0);
|
||||
for (float x = -2.0; x <= 2.0; x += 1.0) {
|
||||
for (float y = -2.0; y <= 2.0; y += 1.0) {
|
||||
vec3 sample = texture2D(texture, texCoord + dx * x + dy * y).rgb;
|
||||
bigAverage += sample;
|
||||
bigTotal += 1.0;
|
||||
if (abs(x) + abs(y) < 2.0) {
|
||||
smallAverage += sample;
|
||||
smallTotal += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
vec3 edge = max(vec3(0.0), bigAverage / bigTotal - smallAverage / smallTotal);
|
||||
float power = u_Strength * u_Strength * u_Strength * u_Strength * u_Strength;
|
||||
return vec4(color.rgb - dot(edge, edge) * power * 100000.0, color.a);
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(texture2D(u_Texture, v_UV));
|
||||
gl_FragColor = ink_sampleColor(u_Texture, u_ViewportSize, v_UV);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
varying vec2 v_UV;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
uniform float u_Amount : 0.5;
|
||||
|
||||
float rand(vec2 co) {
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
// https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/noise.js
|
||||
vec4 noise_filterColor(vec4 color, vec2 texCoord) {
|
||||
float diff = (rand(texCoord) - 0.5) * u_Amount;
|
||||
color.r += diff;
|
||||
color.g += diff;
|
||||
color.b += diff;
|
||||
return color;
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(texture2D(u_Texture, v_UV));
|
||||
gl_FragColor = noise_filterColor(gl_FragColor, v_UV);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
varying vec2 v_UV;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
|
||||
uniform float u_Amount : 0.5;
|
||||
|
||||
// https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/sepia.js
|
||||
vec4 sepia_filterColor(vec4 color) {
|
||||
float r = color.r;
|
||||
float g = color.g;
|
||||
float b = color.b;
|
||||
color.r =
|
||||
min(1.0, (r * (1.0 - (0.607 * u_Amount))) + (g * (0.769 * u_Amount)) + (b * (0.189 * u_Amount)));
|
||||
color.g = min(1.0, (r * 0.349 * u_Amount) + (g * (1.0 - (0.314 * u_Amount))) + (b * 0.168 * u_Amount));
|
||||
color.b = min(1.0, (r * 0.272 * u_Amount) + (g * 0.534 * u_Amount) + (b * (1.0 - (0.869 * u_Amount))));
|
||||
return color;
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(texture2D(u_Texture, v_UV));
|
||||
gl_FragColor = sepia_filterColor(gl_FragColor);
|
||||
}
|
|
@ -8,6 +8,7 @@ const TYPES = {
|
|||
ILayerStyleService: Symbol.for('ILayerStyleService'),
|
||||
ILogService: Symbol.for('ILogService'),
|
||||
IMapService: Symbol.for('IMapService'),
|
||||
IFactoryMapService: Symbol.for('Factory<IMapService>'),
|
||||
IRendererService: Symbol.for('IRendererService'),
|
||||
IShaderModuleService: Symbol.for('IShaderModuleService'),
|
||||
IIconService: Symbol.for('IIconService'),
|
||||
|
@ -16,13 +17,8 @@ const TYPES = {
|
|||
IControlService: Symbol.for('IControlService'),
|
||||
IStyleAttributeService: Symbol.for('IStyleAttributeService'),
|
||||
ILayerPlugin: Symbol.for('ILayerPlugin'),
|
||||
|
||||
/** multi-pass */
|
||||
ClearPass: Symbol.for('ClearPass'),
|
||||
RenderPass: Symbol.for('RenderPass'),
|
||||
CopyPass: Symbol.for('CopyPass'),
|
||||
BlurHPass: Symbol.for('BlurHPass'),
|
||||
BlurVPass: Symbol.for('BlurVPass'),
|
||||
INewablePostProcessingPass: Symbol.for('Newable<IPostProcessingPass>'),
|
||||
IFactoryPostProcessingPass: Symbol.for('Factory<IPostProcessingPass>'),
|
||||
};
|
||||
|
||||
export { TYPES };
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
"@l7/core": "^0.0.1",
|
||||
"@l7/source": "^0.0.1",
|
||||
"@l7/utils": "^0.0.1",
|
||||
"@mapbox/martini": "^0.1.0",
|
||||
"@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 +32,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",
|
||||
|
|
|
@ -28,7 +28,7 @@ import { isFunction } from 'lodash';
|
|||
// @ts-ignore
|
||||
import mergeJsonSchemas from 'merge-json-schemas';
|
||||
import { SyncBailHook, SyncHook } from 'tapable';
|
||||
|
||||
import { normalizePasses } from '../plugins/MultiPassRendererPlugin';
|
||||
import baseLayerSchema from './schema';
|
||||
|
||||
export interface ILayerModelInitializationOptions {
|
||||
|
@ -106,6 +106,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 +123,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;
|
||||
|
||||
|
@ -230,11 +230,26 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {
|
|||
};
|
||||
return this;
|
||||
}
|
||||
public style(options: object): ILayer {
|
||||
// @ts-ignore
|
||||
public style(options: object & Partial<ILayerInitializationOptions>): ILayer {
|
||||
const { passes, ...rest } = options;
|
||||
|
||||
// passes 特殊处理
|
||||
if (passes) {
|
||||
normalizePasses(passes).forEach(
|
||||
(pass: [string, { [key: string]: unknown }]) => {
|
||||
const postProcessingPass = this.multiPassRenderer
|
||||
.getPostProcessor()
|
||||
.getPostProcessingPassByName(pass[0]);
|
||||
if (postProcessingPass) {
|
||||
postProcessingPass.updateOptions(pass[1]);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
this.styleOptions = {
|
||||
...this.styleOptions,
|
||||
...(options as object),
|
||||
...rest,
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
@ -328,13 +343,14 @@ 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,
|
||||
} = this.styleAttributeService.createAttributesAndIndices(
|
||||
this.encodedData,
|
||||
triangulation,
|
||||
parserData,
|
||||
);
|
||||
return createModel({
|
||||
attributes,
|
||||
|
|
|
@ -141,7 +141,8 @@ export function RasterImageTriangulation(feature: IEncodeFeature) {
|
|||
* @param feature 映射数据
|
||||
* @param segNum 弧线线段数
|
||||
*/
|
||||
export function LineArcTriangulation(feature: IEncodeFeature, segNum = 30) {
|
||||
export function LineArcTriangulation(feature: IEncodeFeature) {
|
||||
const segNum = 30;
|
||||
const coordinates = feature.coordinates as IPosition[];
|
||||
const positions = [];
|
||||
const indexArray = [];
|
||||
|
@ -179,6 +180,35 @@ export function LineArcTriangulation(feature: IEncodeFeature, segNum = 30) {
|
|||
};
|
||||
}
|
||||
|
||||
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
|
||||
* @param shape 3D形状
|
||||
|
@ -259,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,314 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
IFramebuffer,
|
||||
ILayer,
|
||||
ILayerPlugin,
|
||||
ILogService,
|
||||
IModel,
|
||||
IStyleAttributeService,
|
||||
ITexture2D,
|
||||
lazyInject,
|
||||
TYPES,
|
||||
} from '@l7/core';
|
||||
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;
|
||||
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.buildHeatmapColor();
|
||||
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();
|
||||
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],
|
||||
},
|
||||
});
|
||||
}
|
||||
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.1,0.5,intensity) * u_Opacity;
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
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;
|
||||
#pragma include "projection"
|
||||
void main() {
|
||||
v_texCoord = a_Uv;
|
||||
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(pos.xy, 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,16 +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';
|
||||
|
@ -76,7 +79,9 @@ export {
|
|||
HeatMapGridLayer,
|
||||
ArcLineLayer,
|
||||
Arc2DLineLayer,
|
||||
// Line,
|
||||
RasterLayer,
|
||||
HeatMapLayer,
|
||||
TextLayer,
|
||||
// ImageLayer,
|
||||
// HeatMapLayer,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,33 +1,22 @@
|
|||
import {
|
||||
BlurHPass,
|
||||
BlurVPass,
|
||||
ClearPass,
|
||||
CopyPass,
|
||||
IGlobalConfigService,
|
||||
ILayer,
|
||||
ILayerPlugin,
|
||||
IPostProcessingPass,
|
||||
IRendererService,
|
||||
lazyInject,
|
||||
MultiPassRenderer,
|
||||
PixelPickingPass,
|
||||
RenderPass,
|
||||
TAAPass,
|
||||
TYPES,
|
||||
} from '@l7/core';
|
||||
import { inject, injectable } from 'inversify';
|
||||
|
||||
const builtinPostProcessingPassMap: {
|
||||
[key: string]: new (config?: { [key: string]: any }) => IPostProcessingPass;
|
||||
} = {
|
||||
blurH: BlurHPass,
|
||||
blurV: BlurVPass,
|
||||
};
|
||||
import { inject, injectable, interfaces, multiInject } from 'inversify';
|
||||
|
||||
/**
|
||||
* 'blurH' -> ['blurH', {}]
|
||||
*/
|
||||
function normalizePasses(
|
||||
export function normalizePasses(
|
||||
passes: Array<string | [string, { [key: string]: unknown }]>,
|
||||
) {
|
||||
return passes.map((pass: string | [string, { [key: string]: unknown }]) => {
|
||||
|
@ -57,6 +46,11 @@ export default class MultiPassRendererPlugin implements ILayerPlugin {
|
|||
@inject(TYPES.IRendererService)
|
||||
private readonly rendererService: IRendererService;
|
||||
|
||||
@inject(TYPES.IFactoryPostProcessingPass)
|
||||
private readonly postProcessingPassFactory: (
|
||||
name: string,
|
||||
) => IPostProcessingPass<unknown>;
|
||||
|
||||
private enabled: boolean;
|
||||
|
||||
public apply(layer: ILayer) {
|
||||
|
@ -110,7 +104,7 @@ export default class MultiPassRendererPlugin implements ILayerPlugin {
|
|||
multiPassRenderer.add(new PixelPickingPass());
|
||||
}
|
||||
|
||||
// TAA pass if enabled
|
||||
// use TAA pass if enabled instead of render pass
|
||||
if (enableTAA) {
|
||||
multiPassRenderer.add(new TAAPass());
|
||||
} else {
|
||||
|
@ -121,13 +115,16 @@ export default class MultiPassRendererPlugin implements ILayerPlugin {
|
|||
// post processing
|
||||
normalizePasses(passes).forEach(
|
||||
(pass: [string, { [key: string]: unknown }]) => {
|
||||
const PostProcessingPassClazz = builtinPostProcessingPassMap[pass[0]];
|
||||
multiPassRenderer.add(new PostProcessingPassClazz(pass[1]));
|
||||
const [passName, initializationOptions] = pass;
|
||||
multiPassRenderer.add(
|
||||
this.postProcessingPassFactory(passName),
|
||||
initializationOptions,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// 末尾为固定的 CopyPass
|
||||
multiPassRenderer.add(new CopyPass());
|
||||
multiPassRenderer.add(this.postProcessingPassFactory('copy'));
|
||||
|
||||
return multiPassRenderer;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -10,8 +10,8 @@ varying vec4 v_Color;
|
|||
#pragma include "picking"
|
||||
|
||||
void main() {
|
||||
v_Color =a_Color;
|
||||
vec4 project_pos = project_position(vec4(a_Position,1.0));
|
||||
v_Color = a_Color;
|
||||
vec4 project_pos = project_position(vec4(a_Position, 1.0));
|
||||
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0));
|
||||
|
||||
setPickingColor(a_PickingColor);
|
||||
|
|
|
@ -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,25 @@
|
|||
import { IEncodeFeature, IParseDataItem } from '@l7/core';
|
||||
// @ts-ignore
|
||||
import Martini from '@mapbox/martini';
|
||||
export function RasterTriangulation(
|
||||
feature: IEncodeFeature,
|
||||
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(1024);
|
||||
return {
|
||||
vertices: Array.from(mesh.vertices) as number[],
|
||||
indices: Array.from(mesh.triangles) as number[],
|
||||
size: 2,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
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 ImageLayer extends BaseLayer<IRasterLayerStyleOptions> {
|
||||
public name: string = 'RasterLayer';
|
||||
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.buildLayerModel({
|
||||
moduleName: 'Raster',
|
||||
vertexShader: rasterVert,
|
||||
fragmentShader: rasterFrag,
|
||||
triangulation: RasterTriangulation,
|
||||
primitive: gl.TRIANGLES,
|
||||
depth: { enable: false },
|
||||
blend: {
|
||||
enable: true,
|
||||
func: {
|
||||
srcRGB: gl.SRC_ALPHA,
|
||||
srcAlpha: 1,
|
||||
dstRGB: gl.ONE_MINUS_SRC_ALPHA,
|
||||
dstAlpha: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -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) * 50., 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,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,
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
} from '@l7/core';
|
||||
import { AMapService, MapboxService } from '@l7/maps';
|
||||
import { ReglRendererService } from '@l7/renderer';
|
||||
import { interfaces } from 'inversify';
|
||||
import { Map } from 'mapbox-gl';
|
||||
|
||||
// 绑定渲染引擎服务
|
||||
|
@ -28,6 +29,24 @@ container
|
|||
.bind<IRendererService>(TYPES.IRendererService)
|
||||
.to(ReglRendererService)
|
||||
.inSingletonScope();
|
||||
// // 绑定地图服务 AMap & Mapbox
|
||||
// container
|
||||
// .bind<IMapService>(TYPES.IMapService)
|
||||
// .to(AMapService)
|
||||
// .whenTargetNamed(MapType.amap)
|
||||
// .inSingletonScope();
|
||||
// container
|
||||
// .bind<IMapService>(TYPES.IMapService)
|
||||
// .to(MapboxService)
|
||||
// .inSingletonScope();
|
||||
// // 地图服务工厂,根据 name 返回指定服务
|
||||
// container
|
||||
// .bind<interfaces.Factory<IMapService>>(TYPES.IFactoryMapService)
|
||||
// .toFactory<IMapService>((context) => {
|
||||
// return (named: string) => {
|
||||
// return context.container.getNamed<IMapService>(TYPES.IMapService, named);
|
||||
// };
|
||||
// });
|
||||
|
||||
// 缓存当前地图类型,便于 DEMO 中切换底图时动态绑定
|
||||
let mapType: MapType;
|
||||
|
@ -52,7 +71,6 @@ class Scene {
|
|||
|
||||
private iconService: IIconService;
|
||||
|
||||
// private mapType: MapType;
|
||||
public constructor(config: IMapConfig & IRenderConfig) {
|
||||
const { type = MapType.amap } = config;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -2,6 +2,7 @@ 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';
|
||||
|
@ -9,15 +10,18 @@ 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)
|
||||
.add('点图层', () => <PointDemo />)
|
||||
.add('3D点', () => <Point3D />)
|
||||
.add('图片标注', () => <PointImage />)
|
||||
.add('面3d图层', () => <Polygon3D />)
|
||||
.add('线图层', () => <LineLayer />)
|
||||
.add('3D弧线', () => <ArcLineDemo />)
|
||||
.add('2D弧线', () => <Arc2DLineDemo />)
|
||||
.add('网格热力图', () => <GridHeatMap />)
|
||||
// .add('点图层', () => <PointDemo />)
|
||||
// .add('3D点', () => <Point3D />)
|
||||
// .add('图片标注', () => <PointImage />)
|
||||
// .add('面3d图层', () => <Polygon3D />)
|
||||
// .add('线图层', () => <LineLayer />)
|
||||
// .add('3D弧线', () => <ArcLineDemo />)
|
||||
// .add('2D弧线', () => <Arc2DLineDemo />)
|
||||
// .add('网格热力图', () => <GridHeatMap />)
|
||||
.add('热力图', () => <HeatMapDemo />)
|
||||
// .add('栅格', () => <RasterLayerDemo />)
|
||||
.add('图片', () => <ImageLayerDemo />);
|
||||
|
|
|
@ -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,70 @@
|
|||
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({});
|
||||
layer
|
||||
.source(await response.json())
|
||||
.size('mag', [0, 1]) // weight映射通道
|
||||
.style({
|
||||
intensity: 2,
|
||||
radius: 20,
|
||||
opacity: 1,
|
||||
rampColors: {
|
||||
colors: [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
],
|
||||
positions: [0, 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() {
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import Blur from './components/Blur';
|
||||
import ColorHalftone from './components/ColorHalftone';
|
||||
import HexagonalPixelate from './components/HexagonalPixelate';
|
||||
import Ink from './components/Ink';
|
||||
import Noise from './components/Noise';
|
||||
import Sepia from './components/Sepia';
|
||||
import TAA from './components/TAA';
|
||||
// @ts-ignore
|
||||
storiesOf('MultiPassRenderer', module)
|
||||
.add('ColorHalftone', () => <ColorHalftone />)
|
||||
.add('HexagonalPixelate', () => <HexagonalPixelate />)
|
||||
.add('Ink', () => <Ink />)
|
||||
.add('Blur', () => <Blur />)
|
||||
.add('Noise', () => <Noise />)
|
||||
.add('Sepia', () => <Sepia />)
|
||||
.add('TAA(Temporal Anti-Aliasing)', () => <TAA />);
|
||||
|
|
|
@ -37,7 +37,12 @@ export default class Mapbox extends React.Component {
|
|||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
passes: [
|
||||
'blurH',
|
||||
[
|
||||
'blurH',
|
||||
{
|
||||
blurRadius: 8,
|
||||
},
|
||||
],
|
||||
[
|
||||
'blurV',
|
||||
{
|
||||
|
@ -67,6 +72,46 @@ export default class Mapbox extends React.Component {
|
|||
scene.render();
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
/*** 运行时修改样式属性 ***/
|
||||
const gui = new dat.GUI();
|
||||
this.gui = gui;
|
||||
const styleOptions = {
|
||||
blurVRadius: 8,
|
||||
blurHRadius: 8,
|
||||
};
|
||||
const pointFolder = gui.addFolder('Blur 配置');
|
||||
pointFolder
|
||||
.add(styleOptions, 'blurVRadius', 0, 100)
|
||||
.onChange((blurRadius: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'blurV',
|
||||
{
|
||||
blurRadius,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder
|
||||
.add(styleOptions, 'blurHRadius', 0, 100)
|
||||
.onChange((blurRadius: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'blurH',
|
||||
{
|
||||
blurRadius,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.open();
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
// @ts-ignore
|
||||
import { PolygonLayer } from '@l7/layers';
|
||||
// @ts-ignore
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as dat from 'dat.gui';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class ColorHalftone extends React.Component {
|
||||
private gui: dat.GUI;
|
||||
private $stats: Node;
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.gui) {
|
||||
this.gui.destroy();
|
||||
}
|
||||
if (this.$stats) {
|
||||
document.body.removeChild(this.$stats);
|
||||
}
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/streets-v9',
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
zoom: 3,
|
||||
});
|
||||
const layer = new PolygonLayer({
|
||||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
passes: [
|
||||
[
|
||||
'colorHalftone',
|
||||
{
|
||||
size: 8,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
layer
|
||||
.source(data)
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
/*** 运行时修改样式属性 ***/
|
||||
const gui = new dat.GUI();
|
||||
this.gui = gui;
|
||||
const styleOptions = {
|
||||
angle: 0,
|
||||
size: 8,
|
||||
centerX: 0.5,
|
||||
centerY: 0.5,
|
||||
};
|
||||
const pointFolder = gui.addFolder('ColorHalftone 配置');
|
||||
pointFolder
|
||||
.add(styleOptions, 'centerX', 0, 1)
|
||||
.onChange((centerX: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'colorHalftone',
|
||||
{
|
||||
center: [centerX, styleOptions.centerY],
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder
|
||||
.add(styleOptions, 'centerY', 0, 1)
|
||||
.onChange((centerY: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'colorHalftone',
|
||||
{
|
||||
center: [styleOptions.centerX, centerY],
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.add(styleOptions, 'angle', 0, 10).onChange((angle: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'colorHalftone',
|
||||
{
|
||||
angle,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.add(styleOptions, 'size', 0, 20).onChange((size: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'colorHalftone',
|
||||
{
|
||||
size,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.open();
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
// @ts-ignore
|
||||
import { PolygonLayer } from '@l7/layers';
|
||||
// @ts-ignore
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as dat from 'dat.gui';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class HexagonalPixelate extends React.Component {
|
||||
private gui: dat.GUI;
|
||||
private $stats: Node;
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.gui) {
|
||||
this.gui.destroy();
|
||||
}
|
||||
if (this.$stats) {
|
||||
document.body.removeChild(this.$stats);
|
||||
}
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/streets-v9',
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
zoom: 3,
|
||||
});
|
||||
const layer = new PolygonLayer({
|
||||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
passes: [
|
||||
[
|
||||
'hexagonalPixelate',
|
||||
{
|
||||
scale: 10,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
layer
|
||||
.source(data)
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
/*** 运行时修改样式属性 ***/
|
||||
const gui = new dat.GUI();
|
||||
this.gui = gui;
|
||||
const styleOptions = {
|
||||
scale: 10,
|
||||
centerX: 0.5,
|
||||
centerY: 0.5,
|
||||
};
|
||||
const pointFolder = gui.addFolder('HexagonalPixelate 配置');
|
||||
pointFolder
|
||||
.add(styleOptions, 'centerX', 0, 1)
|
||||
.onChange((centerX: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'hexagonalPixelate',
|
||||
{
|
||||
center: [centerX, styleOptions.centerY],
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder
|
||||
.add(styleOptions, 'centerY', 0, 1)
|
||||
.onChange((centerY: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'hexagonalPixelate',
|
||||
{
|
||||
center: [styleOptions.centerX, centerY],
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.add(styleOptions, 'scale', 0, 50).onChange((scale: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'hexagonalPixelate',
|
||||
{
|
||||
scale,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.open();
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
// @ts-ignore
|
||||
import { PolygonLayer } from '@l7/layers';
|
||||
// @ts-ignore
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as dat from 'dat.gui';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Ink extends React.Component {
|
||||
private gui: dat.GUI;
|
||||
private $stats: Node;
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.gui) {
|
||||
this.gui.destroy();
|
||||
}
|
||||
if (this.$stats) {
|
||||
document.body.removeChild(this.$stats);
|
||||
}
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/streets-v9',
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
zoom: 3,
|
||||
});
|
||||
const layer = new PolygonLayer({
|
||||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
passes: [
|
||||
[
|
||||
'ink',
|
||||
{
|
||||
strength: 0.6,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
layer
|
||||
.source(data)
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
/*** 运行时修改样式属性 ***/
|
||||
const gui = new dat.GUI();
|
||||
this.gui = gui;
|
||||
const styleOptions = {
|
||||
strength: 0.6,
|
||||
};
|
||||
const pointFolder = gui.addFolder('Ink 配置');
|
||||
pointFolder
|
||||
.add(styleOptions, 'strength', 0, 1)
|
||||
.onChange((strength: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'ink',
|
||||
{
|
||||
strength,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.open();
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// @ts-ignore
|
||||
import { PolygonLayer } from '@l7/layers';
|
||||
// @ts-ignore
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as dat from 'dat.gui';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Noise extends React.Component {
|
||||
private gui: dat.GUI;
|
||||
private $stats: Node;
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.gui) {
|
||||
this.gui.destroy();
|
||||
}
|
||||
if (this.$stats) {
|
||||
document.body.removeChild(this.$stats);
|
||||
}
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/streets-v9',
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
zoom: 3,
|
||||
});
|
||||
const layer = new PolygonLayer({
|
||||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
passes: ['noise'],
|
||||
});
|
||||
|
||||
layer
|
||||
.source(data)
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
/*** 运行时修改样式属性 ***/
|
||||
const gui = new dat.GUI();
|
||||
this.gui = gui;
|
||||
const styleOptions = {
|
||||
amount: 1,
|
||||
};
|
||||
const pointFolder = gui.addFolder('Noise 配置');
|
||||
pointFolder.add(styleOptions, 'amount', 0, 1).onChange((amount: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'noise',
|
||||
{
|
||||
amount,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.open();
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// @ts-ignore
|
||||
import { PolygonLayer } from '@l7/layers';
|
||||
// @ts-ignore
|
||||
import { Scene } from '@l7/scene';
|
||||
import * as dat from 'dat.gui';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Sepia extends React.Component {
|
||||
private gui: dat.GUI;
|
||||
private $stats: Node;
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.gui) {
|
||||
this.gui.destroy();
|
||||
}
|
||||
if (this.$stats) {
|
||||
document.body.removeChild(this.$stats);
|
||||
}
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
type: 'mapbox',
|
||||
style: 'mapbox://styles/mapbox/streets-v9',
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
zoom: 3,
|
||||
});
|
||||
const layer = new PolygonLayer({
|
||||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
passes: ['sepia'],
|
||||
});
|
||||
|
||||
layer
|
||||
.source(data)
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
/*** 运行时修改样式属性 ***/
|
||||
const gui = new dat.GUI();
|
||||
this.gui = gui;
|
||||
const styleOptions = {
|
||||
amount: 0.5,
|
||||
};
|
||||
const pointFolder = gui.addFolder('Sepia 配置');
|
||||
pointFolder.add(styleOptions, 'amount', 0, 1).onChange((amount: number) => {
|
||||
layer.style({
|
||||
passes: [
|
||||
[
|
||||
'sepia',
|
||||
{
|
||||
amount,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder.open();
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -79,7 +79,7 @@ export default class TAA extends React.Component {
|
|||
const pointFolder = gui.addFolder('TAA 配置');
|
||||
pointFolder
|
||||
.add(styleOptions, 'jitterScale', 0, 100)
|
||||
.onChange((jitterScale: boolean) => {
|
||||
.onChange((jitterScale: number) => {
|
||||
layer.style({
|
||||
jitterScale,
|
||||
});
|
||||
|
|
249
yarn.lock
249
yarn.lock
|
@ -316,6 +316,14 @@
|
|||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/plugin-syntax-json-strings" "^7.2.0"
|
||||
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4":
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.4.4.tgz#41c360d59481d88e0ce3a3f837df10121a769b39"
|
||||
integrity sha512-Amph7Epui1Dh/xxUxS2+K22/MUi6+6JVTvy3P58tja3B6yKTSjwwx0/d83rF7551D6PVSSoplQb8GCwqec7HRw==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.2.0"
|
||||
|
||||
"@babel/plugin-proposal-object-rest-spread@7.5.5":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58"
|
||||
|
@ -399,6 +407,13 @@
|
|||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-syntax-nullish-coalescing-operator@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.2.0.tgz#f75083dfd5ade73e783db729bbd87e7b9efb7624"
|
||||
integrity sha512-lRCEaKE+LTxDQtgbYajI04ddt6WW0WJq57xqkAZ+s11h4YgfRHhVA/Y2VhfPzzFD4qeLHWg32DMp9HooY4Kqlg==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
|
||||
|
@ -905,7 +920,7 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3":
|
||||
version "7.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.3.tgz#935122c74c73d2240cafd32ddb5fc2a6cd35cf1f"
|
||||
integrity sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==
|
||||
|
@ -1124,10 +1139,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.3.tgz#a166882c81c0c6040975dd30df24fae8549bd96f"
|
||||
integrity sha512-14ZVlsB9akwvydAdaEnVnvqu6J2P6ySv39hYyl/aoB6w/V+bXX0tay8cF6paqbgZsN2n5Xh15uF4pE+GvE+itw==
|
||||
|
||||
"@emotion/is-prop-valid@0.8.3":
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.3.tgz#cbe62ddbea08aa022cdf72da3971570a33190d29"
|
||||
integrity sha512-We7VBiltAJ70KQA0dWkdPMXnYoizlxOXpvtjmu5/MBnExd+u0PGgV27WCYanmLAbCwAU30Le/xA0CQs/F/Otig==
|
||||
"@emotion/is-prop-valid@0.8.4":
|
||||
version "0.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.4.tgz#cf1dcfc1812c226f05e1ba53592eb6b51e734990"
|
||||
integrity sha512-QBW8h6wVQgeQ55F52rNaprEJxtVR+/ScOP8/V1ScSpPzKqHdFB9QVqby0Z50sqS8mcaeIl5vR1vQpKwJbIS6NQ==
|
||||
dependencies:
|
||||
"@emotion/memoize" "0.7.3"
|
||||
|
||||
|
@ -1136,10 +1151,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.3.tgz#5b6b1c11d6a6dddf1f2fc996f74cf3b219644d78"
|
||||
integrity sha512-2Md9mH6mvo+ygq1trTeVp2uzAKwE2P7In0cRpD/M9Q70aH8L+rxMLbb3JCN2JoSWsV2O+DdFjfbbXoMoLBczow==
|
||||
|
||||
"@emotion/serialize@^0.11.12":
|
||||
version "0.11.13"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.13.tgz#49b93e8e6f7dba70bbf0ecd697bb4e03f45d8cde"
|
||||
integrity sha512-Tw+z6oIFCXeznoH25TozFoOUJ9BIyKBgZ9Gif3ej9aqPeP/Dzct8WIXSsz08xxyt1RPlKokvJ3fzMDq0UjL3RQ==
|
||||
"@emotion/serialize@^0.11.12", "@emotion/serialize@^0.11.14":
|
||||
version "0.11.14"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.14.tgz#56a6d8d04d837cc5b0126788b2134c51353c6488"
|
||||
integrity sha512-6hTsySIuQTbDbv00AnUO6O6Xafdwo5GswRlMZ5hHqiFx+4pZ7uGWXUQFW46Kc2taGhP89uXMXn/lWQkdyTosPA==
|
||||
dependencies:
|
||||
"@emotion/hash" "0.7.3"
|
||||
"@emotion/memoize" "0.7.3"
|
||||
|
@ -1152,23 +1167,23 @@
|
|||
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a"
|
||||
integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A==
|
||||
|
||||
"@emotion/styled-base@^10.0.22":
|
||||
version "10.0.22"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.22.tgz#2b6e86e477ed81bd74aa6cef5f403d500503df5b"
|
||||
integrity sha512-ikSuAcz86BcmlZM5EysqCH0EUssYm5ardrWNVM3Ri5ODpOlKPrT//jVozJU2uK3q5GRcqZHLqagP/nd9beNUfQ==
|
||||
"@emotion/styled-base@^10.0.23":
|
||||
version "10.0.23"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.23.tgz#21244fa25f4c867033e670cf9d7bd0262b4f74ce"
|
||||
integrity sha512-94QowN2S09nCXRz9dXBiMaEcUcXn9kHM8uFExpsspwswHWnkpFn6jTewotQEgI7RROnAXDZ8fvSTkCdqtn3sfw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
"@emotion/is-prop-valid" "0.8.3"
|
||||
"@emotion/serialize" "^0.11.12"
|
||||
"@emotion/is-prop-valid" "0.8.4"
|
||||
"@emotion/serialize" "^0.11.14"
|
||||
"@emotion/utils" "0.11.2"
|
||||
|
||||
"@emotion/styled@^10.0.14":
|
||||
version "10.0.22"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.22.tgz#ee398710876ebda5a418f84359516c6a1c5c41b1"
|
||||
integrity sha512-3+dnBk8NjXnddI8Gi2VJLMmup0bCG8HQkZLaeNky+GSLl8VyxQfuaK5I5aDVvgQ3UzkxrcZrFB3vHYU/iUakBA==
|
||||
version "10.0.23"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.23.tgz#2f8279bd59b99d82deade76d1046249ddfab7c1b"
|
||||
integrity sha512-gNr04eqBQ2iYUx8wFLZDfm3N8/QUOODu/ReDXa693uyQGy2OqA+IhPJk+kA7id8aOfwAsMuvZ0pJImEXXKtaVQ==
|
||||
dependencies:
|
||||
"@emotion/styled-base" "^10.0.22"
|
||||
babel-plugin-emotion "^10.0.22"
|
||||
"@emotion/styled-base" "^10.0.23"
|
||||
babel-plugin-emotion "^10.0.23"
|
||||
|
||||
"@emotion/stylis@0.8.4":
|
||||
version "0.8.4"
|
||||
|
@ -2114,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"
|
||||
|
@ -2983,9 +3003,9 @@
|
|||
integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==
|
||||
|
||||
"@types/jest@^24.0.18":
|
||||
version "24.0.20"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.20.tgz#729d5fe8684e7fb06368d3bd557ac6d91289d861"
|
||||
integrity sha512-M8ebEkOpykGdLoRrmew7UowTZ1DANeeP0HiSIChl/4DGgmnSC1ntitNtkyNSXjMTsZvXuaxJrxjImEnRWNPsPw==
|
||||
version "24.0.21"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.21.tgz#2c0a25440e025bb265f4a17d8b79b11b231426bf"
|
||||
integrity sha512-uyqFvx78Tuy0h5iLCPWRCvi5HhWwEqhIj30doitp191oYLqlCxUyAJHdWVm5+Nr271/vPnkyt6rWeEIjGowBTg==
|
||||
dependencies:
|
||||
"@types/jest-diff" "*"
|
||||
|
||||
|
@ -3007,9 +3027,9 @@
|
|||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/node@*", "@types/node@^12.0.2", "@types/node@^12.11.1", "@types/node@^12.7.3":
|
||||
version "12.11.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
|
||||
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
|
||||
version "12.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.0.tgz#ff3201972d6dc851a9275308a17b9b5094e68057"
|
||||
integrity sha512-6N8Sa5AaENRtJnpKXZgvc119PKxT1Lk9VPy4kfT8JF23tIe1qDfaGkBR2DRKJFIA7NptMz+fps//C6aLi1Uoug==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.0"
|
||||
|
@ -3906,15 +3926,15 @@ babel-plugin-dynamic-import-node@2.3.0, babel-plugin-dynamic-import-node@^2.3.0:
|
|||
dependencies:
|
||||
object.assign "^4.1.0"
|
||||
|
||||
babel-plugin-emotion@^10.0.14, babel-plugin-emotion@^10.0.22:
|
||||
version "10.0.22"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.22.tgz#7860b39f96dcc1b79e326987ce29d4fcfff96f52"
|
||||
integrity sha512-e3Yo9+GD6ovrcZlt2Unjgfyy0gfdz0+8httltToWL+biFMhLPPT1PJlc0GHy9i+vtPSrTBNY2hawfPJnuG2L3g==
|
||||
babel-plugin-emotion@^10.0.14, babel-plugin-emotion@^10.0.22, babel-plugin-emotion@^10.0.23:
|
||||
version "10.0.23"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.23.tgz#040d40bf61dcab6d31dd6043d10e180240b8515b"
|
||||
integrity sha512-1JiCyXU0t5S2xCbItejCduLGGcKmF3POT0Ujbexog2MI4IlRcIn/kWjkYwCUZlxpON0O5FC635yPl/3slr7cKQ==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
"@emotion/hash" "0.7.3"
|
||||
"@emotion/memoize" "0.7.3"
|
||||
"@emotion/serialize" "^0.11.12"
|
||||
"@emotion/serialize" "^0.11.14"
|
||||
babel-plugin-macros "^2.0.0"
|
||||
babel-plugin-syntax-jsx "^6.18.0"
|
||||
convert-source-map "^1.5.0"
|
||||
|
@ -4693,9 +4713,9 @@ can-use-dom@^0.1.0:
|
|||
integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=
|
||||
|
||||
caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001004:
|
||||
version "1.0.30001005"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001005.tgz#823054210be638c725521edcb869435dae46728d"
|
||||
integrity sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg==
|
||||
version "1.0.30001006"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001006.tgz#5b6e8288792cfa275f007b2819a00ccad7112655"
|
||||
integrity sha512-MXnUVX27aGs/QINz+QG1sWSLDr3P1A3Hq5EUWoIt0T7K24DuvMxZEnh3Y5aHlJW6Bz2aApJdSewdYLd8zQnUuw==
|
||||
|
||||
capture-exit@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
@ -5168,11 +5188,9 @@ connect-history-api-fallback@^1.6.0:
|
|||
integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
|
||||
|
||||
console-browserify@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
|
||||
integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=
|
||||
dependencies:
|
||||
date-now "^0.1.4"
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
|
||||
integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
|
||||
|
||||
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
|
||||
version "1.1.0"
|
||||
|
@ -5361,17 +5379,17 @@ copy-webpack-plugin@^4.5.2:
|
|||
serialize-javascript "^1.4.0"
|
||||
|
||||
core-js-compat@^3.1.1:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.3.4.tgz#a151c6cd754edbfe6a4a2a66b9382df2ae74fbcd"
|
||||
integrity sha512-7OK3/LPP8R3Ovasf3GilEOp+o1w0ZKJ75FMou2RDfTwIV69G5RkKCGFnqgBv/ZhR6xo9GCzlfVALyHmydbE7DA==
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.3.5.tgz#7abf70778b73dc74aa99d4075aefcd99b76f2c3a"
|
||||
integrity sha512-44ZORuapx0MUht0MUk0p9lcQPh7n/LDXehimTmjCs0CYblpKZcqVd5w0OQDUDq5OQjEbazWObHDQJWvvHYPNTg==
|
||||
dependencies:
|
||||
browserslist "^4.7.2"
|
||||
semver "^6.3.0"
|
||||
|
||||
core-js-pure@^3.0.1:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.3.4.tgz#01d2842f552a866265dc77ededb2ccd668ff2879"
|
||||
integrity sha512-hqxt6XpR4zIMNUY920oNyAtwaq4yg8IScmXumnfyRWF9+ur7wtjr/4eCdfTJzY64jmi8WRCwIqNBKzYeOKdvnw==
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.3.5.tgz#23dc7e44bb946bf1752b377709e8591faffb0bac"
|
||||
integrity sha512-njLfaPe3tS+8Swgx/itYgJ1jiizCWtNXrK1VzMoXbT6LhiYbIAQioukPmZlB2wTieJY2g4fLRUh96WfXpN61oA==
|
||||
|
||||
core-js@^1.0.0:
|
||||
version "1.2.7"
|
||||
|
@ -5384,9 +5402,9 @@ core-js@^2.4.0, core-js@^2.5.0:
|
|||
integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==
|
||||
|
||||
core-js@^3.0.1, core-js@^3.0.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.3.4.tgz#6b0a23392958317bfb46e40b090529a923add669"
|
||||
integrity sha512-BtibooaAmSOptGLRccsuX/dqgPtXwNgqcvYA6kOTTMzonRxZ+pJS4e+6mvVutESfXMeTnK8m3M+aBu3bkJbR+w==
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.3.5.tgz#58d20f48a95a07304b62ff752742b82b56431ed8"
|
||||
integrity sha512-0J3K+Par/ZydhKg8pEiTcK/9d65/nqJOzY62uMkjeBmt05fDOt/khUVjDdh8TpeIuGQDy1yLDDCjiWN/8pFIuw==
|
||||
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
|
@ -5609,21 +5627,13 @@ css-to-react-native@^2.0.3:
|
|||
css-color-keywords "^1.0.0"
|
||||
postcss-value-parser "^3.3.0"
|
||||
|
||||
css-tree@1.0.0-alpha.29:
|
||||
version "1.0.0-alpha.29"
|
||||
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39"
|
||||
integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==
|
||||
dependencies:
|
||||
mdn-data "~1.1.0"
|
||||
source-map "^0.5.3"
|
||||
|
||||
css-tree@1.0.0-alpha.33:
|
||||
version "1.0.0-alpha.33"
|
||||
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e"
|
||||
integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w==
|
||||
css-tree@1.0.0-alpha.37:
|
||||
version "1.0.0-alpha.37"
|
||||
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22"
|
||||
integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==
|
||||
dependencies:
|
||||
mdn-data "2.0.4"
|
||||
source-map "^0.5.3"
|
||||
source-map "^0.6.1"
|
||||
|
||||
css-what@2.1, css-what@^2.1.2:
|
||||
version "2.1.3"
|
||||
|
@ -5655,12 +5665,12 @@ cssesc@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
||||
|
||||
csso@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b"
|
||||
integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==
|
||||
csso@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d"
|
||||
integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==
|
||||
dependencies:
|
||||
css-tree "1.0.0-alpha.29"
|
||||
css-tree "1.0.0-alpha.37"
|
||||
|
||||
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
|
||||
version "0.3.8"
|
||||
|
@ -5820,11 +5830,6 @@ date-fns@^1.27.2:
|
|||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
|
||||
integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
|
||||
|
||||
date-now@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
|
||||
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=
|
||||
|
||||
dateformat@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
|
||||
|
@ -6545,14 +6550,14 @@ es-to-primitive@^1.2.0:
|
|||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@^0.10.51:
|
||||
version "0.10.51"
|
||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.51.tgz#ed2d7d9d48a12df86e0299287e93a09ff478842f"
|
||||
integrity sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==
|
||||
es5-ext@^0.10.35, es5-ext@^0.10.50:
|
||||
version "0.10.52"
|
||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.52.tgz#bb21777e919a04263736ded120a9d665f10ea63f"
|
||||
integrity sha512-bWCbE9fbpYQY4CU6hJbJ1vSz70EClMlDgJ7BmwI+zEJhxrwjesZRPglGJlsZhu0334U3hI+gaspwksH9IGD6ag==
|
||||
dependencies:
|
||||
es6-iterator "~2.0.3"
|
||||
es6-symbol "~3.1.1"
|
||||
next-tick "^1.0.0"
|
||||
es6-symbol "~3.1.2"
|
||||
next-tick "~1.0.0"
|
||||
|
||||
es5-shim@^4.5.13:
|
||||
version "4.5.13"
|
||||
|
@ -6585,13 +6590,13 @@ es6-shim@^0.35.5:
|
|||
resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.5.tgz#46f59dc0a84a1c5029e8ff1166ca0a902077a9ab"
|
||||
integrity sha512-E9kK/bjtCQRpN1K28Xh4BlmP8egvZBGJJ+9GtnzOwt7mdqtrjHFuVGr7QJfdjBIKqrlU5duPf3pCBoDrkjVYFg==
|
||||
|
||||
es6-symbol@^3.1.1, es6-symbol@~3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.2.tgz#859fdd34f32e905ff06d752e7171ddd4444a7ed1"
|
||||
integrity sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==
|
||||
es6-symbol@^3.1.1, es6-symbol@~3.1.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
|
||||
integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
|
||||
dependencies:
|
||||
d "^1.0.1"
|
||||
es5-ext "^0.10.51"
|
||||
ext "^1.1.2"
|
||||
|
||||
escape-html@^1.0.3, escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
|
@ -6829,6 +6834,13 @@ express@^4.17.0, express@^4.17.1:
|
|||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
ext@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ext/-/ext-1.1.2.tgz#d1d216c83641bb4cb7684622b063cff44a19ce35"
|
||||
integrity sha512-/KLjJdTNyDepCihrk4HQt57nAE1IRCEo5jUt+WgWGCr1oARhibDvmI2DMcSNWood1T9AUWwq+jaV1wvRqaXfnA==
|
||||
dependencies:
|
||||
type "^2.0.0"
|
||||
|
||||
extend-shallow@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
|
||||
|
@ -7385,6 +7397,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"
|
||||
|
@ -7783,9 +7803,9 @@ handle-thing@^2.0.0:
|
|||
integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
|
||||
|
||||
handlebars@^4.1.2, handlebars@^4.4.0:
|
||||
version "4.4.5"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.4.5.tgz#1b1f94f9bfe7379adda86a8b73fb570265a0dddd"
|
||||
integrity sha512-0Ce31oWVB7YidkaTq33ZxEbN+UDxMMgThvCe8ptgQViymL5DPis9uLdTA13MiRPhgvqyxIegugrP97iK3JeBHg==
|
||||
version "4.5.1"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.1.tgz#8a01c382c180272260d07f2d1aa3ae745715c7ba"
|
||||
integrity sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==
|
||||
dependencies:
|
||||
neo-async "^2.6.0"
|
||||
optimist "^0.6.1"
|
||||
|
@ -10155,11 +10175,6 @@ mdn-data@2.0.4:
|
|||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
||||
integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
|
||||
|
||||
mdn-data@~1.1.0:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01"
|
||||
integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
|
@ -10267,7 +10282,7 @@ merge-descriptors@1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
|
||||
|
||||
merge-json-schemas@^1.0.0:
|
||||
merge-json-schemas@1.0.0, merge-json-schemas@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-json-schemas/-/merge-json-schemas-1.0.0.tgz#2d635eaa8401c5fa3d03f30f89349fc7cafee62f"
|
||||
integrity sha1-LWNeqoQBxfo9A/MPiTSfx8r+5i8=
|
||||
|
@ -10665,7 +10680,7 @@ nested-object-assign@^1.0.3:
|
|||
resolved "https://registry.yarnpkg.com/nested-object-assign/-/nested-object-assign-1.0.3.tgz#5aca69390d9affe5a612152b5f0843ae399ac597"
|
||||
integrity sha512-kgq1CuvLyUcbcIuTiCA93cQ2IJFSlRwXcN+hLcb2qLJwC2qrePHGZZa7IipyWqaWF6tQjdax2pQnVxdq19Zzwg==
|
||||
|
||||
next-tick@^1.0.0:
|
||||
next-tick@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
|
||||
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
|
||||
|
@ -11384,7 +11399,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==
|
||||
|
@ -11710,11 +11725,11 @@ pnp-webpack-plugin@1.4.3:
|
|||
ts-pnp "^1.1.2"
|
||||
|
||||
polished@^3.3.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-3.4.1.tgz#1eb5597ec1792206365635811d465751f5cbf71c"
|
||||
integrity sha512-GflTnlP5rrpDoigjczEkS6Ye7NDA4sFvAnlr5hSDrEvjiVj97Xzev3hZlLi3UB27fpxyTS9rWU64VzVLWkG+mg==
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-3.4.2.tgz#b4780dad81d64df55615fbfc77acb52fd17d88cd"
|
||||
integrity sha512-9Rch6iMZckABr6EFCLPZsxodeBpXMo9H4fRlfR/9VjMEyy5xpo1/WgXlJGgSjPyVhEZNycbW7UmYMNyWS5MI0g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.4.5"
|
||||
"@babel/runtime" "^7.6.3"
|
||||
|
||||
polyline-miter-util@^1.0.1:
|
||||
version "1.0.1"
|
||||
|
@ -12618,9 +12633,9 @@ react-test-renderer@^16.0.0-0:
|
|||
scheduler "^0.17.0"
|
||||
|
||||
react-textarea-autosize@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.0.tgz#3132cb77e65d94417558d37c0bfe415a5afd3445"
|
||||
integrity sha512-c2FlR/fP0qbxmlrW96SdrbgP/v0XZMTupqB90zybvmDVDutytUgPl7beU35klwcTeMepUIQEpQUn3P3bdshGPg==
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.1.tgz#66ff1b7d6e1ab759fdf35f09e60bdd0e15d8e143"
|
||||
integrity sha512-dVDVXlUm5uUgWyZAL4gaxJiDb2xCWM/qk6Rl2ixXPSKNsngKhvAj3KbDS9mnQn/qIZSYVD+/iuZT/eQWmNjBLw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.1.2"
|
||||
prop-types "^15.6.0"
|
||||
|
@ -13839,9 +13854,9 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
|
|||
urix "^0.1.0"
|
||||
|
||||
source-map-support@^0.5.3, source-map-support@^0.5.6, source-map-support@~0.5.12:
|
||||
version "0.5.13"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
||||
integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==
|
||||
version "0.5.16"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
|
||||
integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
@ -13858,7 +13873,7 @@ source-map@^0.4.2:
|
|||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0:
|
||||
source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||
|
@ -14453,16 +14468,16 @@ svg-tags@^1.0.0:
|
|||
integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
|
||||
|
||||
svgo@^1.2.2:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313"
|
||||
integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ==
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.1.tgz#115c1f9d7e3294dfc66288c8499e65c2a1479729"
|
||||
integrity sha512-2iv3AHKL+x2/nAvkg+vTv01aK94OFU6wTRbnv/K43mf1OdKEEA8xaQl7Wjs5Vrh9AlyXvyPd8fg6s6YzYdQTnQ==
|
||||
dependencies:
|
||||
chalk "^2.4.1"
|
||||
coa "^2.0.2"
|
||||
css-select "^2.0.0"
|
||||
css-select-base-adapter "^0.1.1"
|
||||
css-tree "1.0.0-alpha.33"
|
||||
csso "^3.5.1"
|
||||
css-tree "1.0.0-alpha.37"
|
||||
csso "^4.0.2"
|
||||
js-yaml "^3.13.1"
|
||||
mkdirp "~0.5.1"
|
||||
object.values "^1.1.0"
|
||||
|
@ -14937,6 +14952,11 @@ type@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
|
||||
integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
|
||||
|
||||
type@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3"
|
||||
integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==
|
||||
|
||||
typed-styles@^0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9"
|
||||
|
@ -14966,9 +14986,9 @@ uglify-js@3.4.x:
|
|||
source-map "~0.6.1"
|
||||
|
||||
uglify-js@^3.1.4, uglify-js@^3.5.1:
|
||||
version "3.6.4"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.4.tgz#88cc880c6ed5cf9868fdfa0760654e7bed463f1d"
|
||||
integrity sha512-9Yc2i881pF4BPGhjteCXQNaXx1DCwm3dtOyBaG2hitHjLWOczw/ki8vD1bqyT3u6K0Ms/FpCShkmfg+FtlOfYA==
|
||||
version "3.6.5"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.5.tgz#b0ee796d2ae7e25672e04f65629b997cd4b30bd6"
|
||||
integrity sha512-7L3W+Npia1OCr5Blp4/Vw83tK1mu5gnoIURtT1fUVfQ3Kf8WStWV6NJz0fdoBJZls0KlweruRTLVe6XLafmy5g==
|
||||
dependencies:
|
||||
commander "~2.20.3"
|
||||
source-map "~0.6.1"
|
||||
|
@ -15763,6 +15783,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, 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