fix(scene): contianer resize

This commit is contained in:
thinkinggis 2019-12-07 01:43:18 +08:00
parent c69561a249
commit 1c3be82711
38 changed files with 433 additions and 155 deletions

View File

@ -1,3 +1,3 @@
import '@storybook/addon-actions/register'; // import '@storybook/addon-actions/register';
import '@storybook/addon-notes/register'; import '@storybook/addon-notes/register';
import '@storybook/addon-storysource/register'; import '@storybook/addon-storysource/register';

View File

@ -1,6 +1,6 @@
// tslint:disable-next-line:no-submodule-imports // tslint:disable-next-line:no-submodule-imports
import '!style-loader!css-loader!sass-loader!./iframe.scss'; import '!style-loader!css-loader!sass-loader!./iframe.scss';
import '@storybook/addon-console'; // import '@storybook/addon-console';
import { addParameters, configure } from '@storybook/react'; import { addParameters, configure } from '@storybook/react';
import { create } from '@storybook/theming'; import { create } from '@storybook/theming';
@ -15,7 +15,7 @@ addParameters({
enableShortcuts: true, enableShortcuts: true,
theme: create({ theme: create({
base: 'light', base: 'light',
brandTitle: 'L7 POC for new architecture', brandTitle: 'L7 for new architecture',
brandUrl: 'https://github.com/xiaoiver/L7-POC', brandUrl: 'https://github.com/xiaoiver/L7-POC',
gridCellSize: 12, gridCellSize: 12,
}), }),

View File

@ -1,9 +1,9 @@
module.exports = ({ config }) => { module.exports = ({ config }) => {
config.module.rules.push({ // config.module.rules.push({
test: /\.glsl$/, // test: /\.glsl$/,
loader: 'raw-loader' // loader: 'raw-loader'
}); // });
// config.module.rules.push({ // config.module.rules.push({
// test: /\.worker\.(js|ts)$/, // test: /\.worker\.(js|ts)$/,

View File

@ -24,4 +24,7 @@ const scene = new Scene({
``` ```
如果你只是需要做个中国地图,世界地图这样填充图,建议你采用这样的模式 如果你只是需要做个中国地图,世界地图这样填充图,建议你采用这样的模式
离线无token使用 ![mapbox demo](https://codesandbox.io/embed/frosty-architecture-tv6uv?fontsize=14&hidenavigation=1&theme=dark)
离线无token使用
<iframe width="100%" height="400" src="//jsfiddle.net/lzxue/a76og89k/embedded/html,result/light/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>

View File

@ -24,4 +24,6 @@ const scene = new Scene({
``` ```
如果你只是需要做个中国地图,世界地图这样填充图,建议你采用这样的模式 如果你只是需要做个中国地图,世界地图这样填充图,建议你采用这样的模式
离线无token使用 ![mapbox demo](https://codesandbox.io/embed/frosty-architecture-tv6uv?fontsize=14&hidenavigation=1&theme=dark) 离线无token使用
<iframe width="100%" height="400" src="//jsfiddle.net/lzxue/a76og89k/embedded/html,result/light/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>

View File

@ -25,6 +25,7 @@
"@antv/l7-utils": "^2.0.0-beta.16", "@antv/l7-utils": "^2.0.0-beta.16",
"@mapbox/tiny-sdf": "^1.1.1", "@mapbox/tiny-sdf": "^1.1.1",
"ajv": "^6.10.2", "ajv": "^6.10.2",
"element-resize-event": "^3.0.3",
"eventemitter3": "^4.0.0", "eventemitter3": "^4.0.0",
"gl-matrix": "^3.1.0", "gl-matrix": "^3.1.0",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",

View File

@ -48,7 +48,7 @@ const defaultLayerConfig: Partial<ILayerConfig> = {
maxZoom: 20, maxZoom: 20,
visible: true, visible: true,
zIndex: 0, zIndex: 0,
enableMultiPassRenderer: true, enableMultiPassRenderer: false,
enablePicking: false, enablePicking: false,
enableHighlight: false, enableHighlight: false,
highlightColor: 'red', highlightColor: 'red',

View File

@ -1,5 +1,5 @@
import { Container } from 'inversify'; import { Container } from 'inversify';
import { SyncBailHook, SyncHook } from 'tapable'; import { SyncBailHook, SyncHook, SyncWaterfallHook } from 'tapable';
import Clock from '../../utils/clock'; import Clock from '../../utils/clock';
import { ISceneConfig } from '../config/IConfigService'; import { ISceneConfig } from '../config/IConfigService';
import { IMapService } from '../map/IMapService'; import { IMapService } from '../map/IMapService';
@ -51,8 +51,11 @@ export interface ILayer {
inited: boolean; // 是否初始化完成 inited: boolean; // 是否初始化完成
zIndex: number; zIndex: number;
plugins: ILayerPlugin[]; plugins: ILayerPlugin[];
layerModelNeedUpdate: boolean;
dataPluginsState: { [key: string]: boolean };
hooks: { hooks: {
init: SyncBailHook<void, boolean | void>; init: SyncBailHook<void, boolean | void>;
beforeRenderData: SyncWaterfallHook<boolean | void>;
beforeRender: SyncBailHook<void, boolean | void>; beforeRender: SyncBailHook<void, boolean | void>;
afterRender: SyncHook<void>; afterRender: SyncHook<void>;
beforePickingEncode: SyncHook<void>; beforePickingEncode: SyncHook<void>;
@ -76,13 +79,14 @@ export interface ILayer {
Partial<IModelInitializationOptions>, Partial<IModelInitializationOptions>,
): IModel; ): IModel;
init(): ILayer; init(): ILayer;
scale(field: string | IScaleOptions, cfg: IScale): ILayer;
size(field: StyleAttrField, value?: StyleAttributeOption): ILayer; size(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
color(field: StyleAttrField, value?: StyleAttributeOption): ILayer; color(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
shape(field: StyleAttrField, value?: StyleAttributeOption): ILayer; shape(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
label(field: StyleAttrField, value?: StyleAttributeOption): ILayer; label(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
animate(option: IAnimateOption): ILayer; animate(option: IAnimateOption): ILayer;
// pattern(field: string, value: StyleAttributeOption): ILayer; // pattern(field: string, value: StyleAttributeOption): ILayer;
// filter(field: string, value: StyleAttributeOption): ILayer; filter(field: string, value: StyleAttributeOption): ILayer;
// active(option: ActiveOption): ILayer; // active(option: ActiveOption): ILayer;
style(options: unknown): ILayer; style(options: unknown): ILayer;
hide(): ILayer; hide(): ILayer;
@ -102,6 +106,7 @@ export interface ILayer {
*/ */
addPlugin(plugin: ILayerPlugin): ILayer; addPlugin(plugin: ILayerPlugin): ILayer;
getSource(): ISource; getSource(): ISource;
isSourceNeedUpdate(): boolean;
setSource(source: ISource): void; setSource(source: ISource): void;
setEncodedData(encodedData: IEncodeFeature[]): void; setEncodedData(encodedData: IEncodeFeature[]): void;
getEncodedData(): IEncodeFeature[]; getEncodedData(): IEncodeFeature[];

View File

@ -25,9 +25,18 @@ export enum ScaleTypes {
THRESHOLD = 'threshold', THRESHOLD = 'threshold',
CAT = 'cat', CAT = 'cat',
} }
export type ScaleTypeName =
| 'linear'
| 'power'
| 'log'
| 'identity'
| 'time'
| 'quantile'
| 'quantize'
| 'threshold'
| 'cat';
export interface IScale { export interface IScale {
type: ScaleTypes; type: ScaleTypeName;
ticks?: any[]; ticks?: any[];
nice?: boolean; nice?: boolean;
format?: () => any; format?: () => any;
@ -40,7 +49,7 @@ export enum StyleScaleType {
} }
export interface IScaleOption { export interface IScaleOption {
field?: string; field?: string;
type: ScaleTypes; type: ScaleTypeName;
ticks?: any[]; ticks?: any[];
nice?: boolean; nice?: boolean;
format?: () => any; format?: () => any;
@ -137,6 +146,7 @@ export interface IStyleAttribute extends IStyleAttributeInitializationOptions {
vertexAttribute: IAttribute; vertexAttribute: IAttribute;
mapping?(...params: unknown[]): unknown[]; mapping?(...params: unknown[]): unknown[];
setProps(props: Partial<IStyleAttributeInitializationOptions>): void; setProps(props: Partial<IStyleAttributeInitializationOptions>): void;
resetDescriptor(): void;
} }
export type Triangulation = ( export type Triangulation = (
@ -157,6 +167,12 @@ export interface IStyleAttributeService {
// layerName: string, // layerName: string,
// options: ILayerStyleOptions, // options: ILayerStyleOptions,
// ): void; // ): void;
attributesAndIndices: {
attributes: {
[attributeName: string]: IAttribute;
};
elements: IElements;
};
registerStyleAttribute( registerStyleAttribute(
options: Partial<IStyleAttributeInitializationOptions>, options: Partial<IStyleAttributeInitializationOptions>,
): IStyleAttribute; ): IStyleAttribute;
@ -169,7 +185,7 @@ export interface IStyleAttributeService {
getLayerStyleAttribute(attributeName: string): IStyleAttribute | undefined; getLayerStyleAttribute(attributeName: string): IStyleAttribute | undefined;
createAttributesAndIndices( createAttributesAndIndices(
encodedFeatures: IEncodeFeature[], encodedFeatures: IEncodeFeature[],
triangulation: Triangulation, triangulation?: Triangulation,
): { ): {
attributes: { attributes: {
[attributeName: string]: IAttribute; [attributeName: string]: IAttribute;

View File

@ -59,6 +59,7 @@ export default class LayerService implements ILayerService {
.filter((layer) => layer.isVisible()) .filter((layer) => layer.isVisible())
.forEach((layer) => { .forEach((layer) => {
// trigger hooks // trigger hooks
layer.hooks.beforeRenderData.call(true);
layer.hooks.beforeRender.call(); layer.hooks.beforeRender.call();
layer.render(); layer.render();
layer.hooks.afterRender.call(); layer.hooks.afterRender.call();

View File

@ -68,6 +68,12 @@ export default class StyleAttribute implements IStyleAttribute {
return this.defaultCallback(params); return this.defaultCallback(params);
} }
public resetDescriptor() {
if (this.descriptor) {
this.descriptor.buffer.data = [];
}
}
private defaultCallback = (params: unknown[]): unknown[] => { private defaultCallback = (params: unknown[]): unknown[] => {
// 没有 params 的情况,是指没有指定 fields直接返回配置的 values 常量 // 没有 params 的情况,是指没有指定 fields直接返回配置的 values 常量
if (params.length === 0) { if (params.length === 0) {

View File

@ -30,11 +30,19 @@ let counter = 0;
*/ */
@injectable() @injectable()
export default class StyleAttributeService implements IStyleAttributeService { export default class StyleAttributeService implements IStyleAttributeService {
public attributesAndIndices: {
attributes: {
[attributeName: string]: IAttribute;
};
elements: IElements;
};
@inject(TYPES.IRendererService) @inject(TYPES.IRendererService)
private readonly rendererService: IRendererService; private readonly rendererService: IRendererService;
private attributes: IStyleAttribute[] = []; private attributes: IStyleAttribute[] = [];
private triangulation: Triangulation;
private c = counter++; private c = counter++;
private featureLayout: { private featureLayout: {
@ -49,7 +57,6 @@ export default class StyleAttributeService implements IStyleAttributeService {
sizePerElement: 0, sizePerElement: 0,
elements: [], elements: [],
}; };
public registerStyleAttribute( public registerStyleAttribute(
options: Partial<IStyleAttributeInitializationOptions>, options: Partial<IStyleAttributeInitializationOptions>,
) { ) {
@ -170,14 +177,20 @@ export default class StyleAttributeService implements IStyleAttributeService {
public createAttributesAndIndices( public createAttributesAndIndices(
features: IEncodeFeature[], features: IEncodeFeature[],
triangulation: Triangulation, triangulation?: Triangulation,
): { ): {
attributes: { attributes: {
[attributeName: string]: IAttribute; [attributeName: string]: IAttribute;
}; };
elements: IElements; elements: IElements;
} { } {
const descriptors = this.attributes.map((attr) => attr.descriptor); if (triangulation) {
this.triangulation = triangulation;
}
const descriptors = this.attributes.map((attr) => {
attr.resetDescriptor();
return attr.descriptor;
});
let verticesNum = 0; let verticesNum = 0;
const vertices: number[] = []; const vertices: number[] = [];
const indices: number[] = []; const indices: number[] = [];
@ -191,7 +204,7 @@ export default class StyleAttributeService implements IStyleAttributeService {
vertices: verticesForCurrentFeature, vertices: verticesForCurrentFeature,
normals: normalsForCurrentFeature, normals: normalsForCurrentFeature,
size: vertexSize, size: vertexSize,
} = triangulation(feature); } = this.triangulation(feature);
indices.push(...indicesForCurrentFeature.map((i) => i + verticesNum)); indices.push(...indicesForCurrentFeature.map((i) => i + verticesNum));
vertices.push(...verticesForCurrentFeature); vertices.push(...verticesForCurrentFeature);
if (normalsForCurrentFeature) { if (normalsForCurrentFeature) {
@ -211,7 +224,6 @@ export default class StyleAttributeService implements IStyleAttributeService {
}); });
verticesNum += verticesNumForCurrentFeature; verticesNum += verticesNumForCurrentFeature;
// 根据 position 顶点生成其他顶点数据 // 根据 position 顶点生成其他顶点数据
for ( for (
let vertexIdx = 0; let vertexIdx = 0;
@ -273,13 +285,12 @@ export default class StyleAttributeService implements IStyleAttributeService {
type: gl.UNSIGNED_INT, type: gl.UNSIGNED_INT,
count: indices.length, count: indices.length,
}); });
this.attributesAndIndices = {
return {
attributes, attributes,
elements, elements,
}; };
return this.attributesAndIndices;
} }
public clearAllAttributes() { public clearAllAttributes() {
// 销毁关联的 vertex attribute buffer objects // 销毁关联的 vertex attribute buffer objects
this.attributes.forEach((attribute) => { this.attributes.forEach((attribute) => {

View File

@ -2,8 +2,8 @@ import { injectable } from 'inversify';
import { Log } from 'probe.gl'; import { Log } from 'probe.gl';
import { ILogService } from './ILogService'; import { ILogService } from './ILogService';
const Logger = new Log({ id: 'L7' }).enable(); const Logger = new Log({ id: 'L7' }).enable(true);
// 只输出 debug 级别以上的日志信息 // // 只输出 debug 级别以上的日志信息
Logger.priority = 4; Logger.priority = 4;
@injectable() @injectable()

View File

@ -34,7 +34,6 @@ export interface IElements {
// 原 Buffer 替换位置,单位为 byte // 原 Buffer 替换位置,单位为 byte
offset: number; offset: number;
}): void; }): void;
/** /**
* gl.deleteBuffer * gl.deleteBuffer
*/ */

View File

@ -220,6 +220,7 @@ export interface IModelDrawOptions {
attributes?: { attributes?: {
[key: string]: IAttribute; [key: string]: IAttribute;
}; };
elements?: IElements;
} }
/** /**

View File

@ -1,3 +1,6 @@
// @ts-ignore
import { DOM } from '@antv/l7-utils';
import elementResizeEvent, { unbind } from 'element-resize-event';
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import { inject, injectable } from 'inversify'; import { inject, injectable } from 'inversify';
import { AsyncParallelHook } from 'tapable'; import { AsyncParallelHook } from 'tapable';
@ -149,7 +152,8 @@ export default class Scene extends EventEmitter implements ISceneService {
this.$container = $container; this.$container = $container;
if ($container) { if ($container) {
await this.rendererService.init($container); await this.rendererService.init($container);
window.addEventListener('resize', this.handleWindowResized, false); elementResizeEvent(this.$container, this.handleWindowResized);
// window.addEventListener('resize', this.handleWindowResized, false);
} else { } else {
this.logger.error('容器 id 不存在'); this.logger.error('容器 id 不存在');
} }
@ -211,11 +215,13 @@ export default class Scene extends EventEmitter implements ISceneService {
this.removeAllListeners(); this.removeAllListeners();
this.rendererService.destroy(); this.rendererService.destroy();
this.map.destroy(); this.map.destroy();
window.removeEventListener('resize', this.handleWindowResized, false); unbind(this.$container);
// window.removeEventListener('resize', this.handleWindowResized, false);
} }
private handleWindowResized = () => { private handleWindowResized = () => {
this.emit('resize'); this.emit('resize');
// @ts-check
if (this.$container) { if (this.$container) {
// recalculate the viewport's size and call gl.viewport // recalculate the viewport's size and call gl.viewport
// @see https://github.com/regl-project/regl/blob/master/lib/webgl.js#L24-L38 // @see https://github.com/regl-project/regl/blob/master/lib/webgl.js#L24-L38
@ -227,12 +233,15 @@ export default class Scene extends EventEmitter implements ISceneService {
w = bounds.right - bounds.left; w = bounds.right - bounds.left;
h = bounds.bottom - bounds.top; h = bounds.bottom - bounds.top;
} }
this.rendererService.viewport({ this.rendererService.viewport({
x: 0, x: 0,
y: 0, y: 0,
width: pixelRatio * w, width: pixelRatio * w,
height: pixelRatio * h, height: pixelRatio * h,
}); });
// 触发 Map canvas
DOM.triggerResize();
// repaint layers // repaint layers
this.render(); this.render();
} }

View File

@ -26,6 +26,8 @@ export interface IClusterOptions {
radius: number; radius: number;
maxZoom: number; maxZoom: number;
minZoom: number; minZoom: number;
zoom: number;
bbox: [number, number, number, number];
field: string; field: string;
method: 'max' | 'sum' | 'min' | 'mean' | 'count' | CallBack; method: 'max' | 'sum' | 'min' | 'mean' | 'count' | CallBack;
} }
@ -57,6 +59,8 @@ export type IJsonData = IJsonItem[];
export interface ISource { export interface ISource {
data: IParserData; data: IParserData;
cluster: boolean;
clusterOptions: Partial<IClusterOptions>;
} }
export interface IRasterCfg { export interface IRasterCfg {
extent: [number, number, number, number]; extent: [number, number, number, number];

View File

@ -28,17 +28,20 @@ import {
IStyleAttributeService, IStyleAttributeService,
IStyleAttributeUpdateOptions, IStyleAttributeUpdateOptions,
lazyInject, lazyInject,
ScaleTypeName,
ScaleTypes,
StyleAttributeField, StyleAttributeField,
StyleAttributeOption, StyleAttributeOption,
TYPES, TYPES,
} from '@antv/l7-core'; } from '@antv/l7-core';
import Source from '@antv/l7-source'; import Source from '@antv/l7-source';
import { bindAll } from '@antv/l7-utils';
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import { Container } from 'inversify'; import { Container } from 'inversify';
import { isFunction, isObject } from 'lodash'; import { isFunction, isObject } from 'lodash';
// @ts-ignore // @ts-ignore
import mergeJsonSchemas from 'merge-json-schemas'; import mergeJsonSchemas from 'merge-json-schemas';
import { SyncBailHook, SyncHook } from 'tapable'; import { SyncBailHook, SyncHook, SyncWaterfallHook } from 'tapable';
import { normalizePasses } from '../plugins/MultiPassRendererPlugin'; import { normalizePasses } from '../plugins/MultiPassRendererPlugin';
import baseLayerSchema from './schema'; import baseLayerSchema from './schema';
@ -46,6 +49,7 @@ import baseLayerSchema from './schema';
* layer id * layer id
*/ */
let layerIdCounter = 0; let layerIdCounter = 0;
const MapEventTypes = ['zoomchange', 'dragend', 'camerachange', 'resize'];
export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
implements ILayer { implements ILayer {
@ -56,11 +60,18 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
public minZoom: number; public minZoom: number;
public maxZoom: number; public maxZoom: number;
public inited: boolean = false; public inited: boolean = false;
public layerModelNeedUpdate: boolean = false;
public dataPluginsState: { [key: string]: boolean } = {
DataSource: false,
DataMapping: false,
FeatureScale: false,
StyleAttr: false,
};
// 生命周期钩子 // 生命周期钩子
public hooks = { public hooks = {
init: new SyncBailHook<void, boolean | void>(), init: new SyncBailHook<void, boolean | void>(),
beforeRender: new SyncBailHook<void, boolean | void>(), beforeRender: new SyncBailHook<void, boolean | void>(),
beforeRenderData: new SyncWaterfallHook<void | boolean>(['data']),
afterRender: new SyncHook<void>(), afterRender: new SyncHook<void>(),
beforePickingEncode: new SyncHook<void>(), beforePickingEncode: new SyncHook<void>(),
afterPickingEncode: new SyncHook<void>(), afterPickingEncode: new SyncHook<void>(),
@ -249,7 +260,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
// 获取插件集 // 获取插件集
this.plugins = this.container.getAll<ILayerPlugin>(TYPES.ILayerPlugin); this.plugins = this.container.getAll<ILayerPlugin>(TYPES.ILayerPlugin);
console.log(this.plugins)
// 完成插件注册,传入场景和图层容器内的服务 // 完成插件注册,传入场景和图层容器内的服务
for (const plugin of this.plugins) { for (const plugin of this.plugins) {
plugin.apply(this, { plugin.apply(this, {
@ -263,6 +273,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
// 触发 init 生命周期插件 // 触发 init 生命周期插件
this.hooks.init.call(); this.hooks.init.call();
this.buildModels(); this.buildModels();
this.inited = true; this.inited = true;
@ -300,6 +311,19 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
}); });
return this; return this;
} }
public filter(
field: StyleAttributeField,
values?: StyleAttributeOption,
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
) {
this.pendingStyleAttributes.push({
attributeName: 'filter',
attributeField: field,
attributeValues: values,
updateOptions,
});
return this;
}
public shape( public shape(
field: StyleAttributeField, field: StyleAttributeField,
@ -343,12 +367,34 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
public setData(data: any, options?: ISourceCFG) { public setData(data: any, options?: ISourceCFG) {
this.sourceOption.data = data; this.sourceOption.data = data;
this.sourceOption.options = options; this.sourceOption.options = options;
console.time('init')
this.hooks.init.call(); this.hooks.init.call();
console.timeEnd('init')
this.buildModels(); this.buildModels();
return this; return this;
} }
public isSourceNeedUpdate() {
const cluster = this.layerSource.cluster;
if (cluster) {
const { zoom = 0, bbox = [0, 0, 0, 0] } = this.layerSource.clusterOptions;
const newZoom = this.mapService.getZoom();
const bounds = this.mapService.getBounds();
const newBbox: [number, number, number, number] = [
bounds[0][0],
bounds[0][1],
bounds[1][0],
bounds[1][1],
];
// ||
// bbox[0] !== newBbox[0] ||
// bbox[2] !== newBbox[2]
if (Math.abs(zoom - newZoom) > 1) {
this.layerSource.updateClusterData(Math.floor(newZoom), newBbox);
return true;
}
}
return false;
}
public style(options: object & Partial<ILayerConfig>): ILayer { public style(options: object & Partial<ILayerConfig>): ILayer {
const { passes, ...rest } = options; const { passes, ...rest } = options;
@ -376,7 +422,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
} }
return this; return this;
} }
public scale(field: string | IScaleOptions, cfg: IScale) { public scale(field: ScaleTypeName | IScaleOptions, cfg: IScale) {
if (isObject(field)) { if (isObject(field)) {
this.scaleOptions = { this.scaleOptions = {
...this.scaleOptions, ...this.scaleOptions,
@ -464,11 +510,12 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
this.hooks.afterDestroy.call(); this.hooks.afterDestroy.call();
this.removeAllListeners();
// 解绑图层容器中的服务 // 解绑图层容器中的服务
// this.container.unbind(TYPES.IStyleAttributeService); // this.container.unbind(TYPES.IStyleAttributeService);
} }
public clear() { public clear() {
this.styleAttributeService.clearAllAttributes(); this.styleAttributeService.clearAllAttributes();
// 销毁所有 model // 销毁所有 model
this.models.forEach((model) => model.destroy()); this.models.forEach((model) => model.destroy());
@ -487,6 +534,16 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
public setSource(source: Source) { public setSource(source: Source) {
this.layerSource = source; this.layerSource = source;
const bounds = this.mapService.getBounds();
const zoom = this.mapService.getZoom();
if (this.layerSource.cluster) {
this.layerSource.updateClusterData(zoom, [
bounds[0][0],
bounds[0][1],
bounds[1][0],
bounds[1][1],
]);
}
} }
public getSource() { public getSource() {
return this.layerSource; return this.layerSource;
@ -536,7 +593,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
}); });
const { vs, fs, uniforms } = this.shaderModuleService.getModule(moduleName); const { vs, fs, uniforms } = this.shaderModuleService.getModule(moduleName);
const { createModel } = this.rendererService; const { createModel } = this.rendererService;
const { const {
attributes, attributes,
elements, elements,
@ -586,4 +642,13 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
callback: isFunction(valuesOrCallback) ? valuesOrCallback : undefined, callback: isFunction(valuesOrCallback) ? valuesOrCallback : undefined,
}; };
} }
private registerMapEvent() {
MapEventTypes.forEach((type) => {
this.mapService.on(type, this.layerMapHander.bind(this, type));
});
}
private layerMapHander(type: string, data: any) {
this.emit(type, data);
}
} }

View File

@ -1,5 +1,7 @@
import { import {
IAttribute,
ICameraService, ICameraService,
IElements,
IFontService, IFontService,
IGlobalConfigService, IGlobalConfigService,
IIconService, IIconService,
@ -12,10 +14,13 @@ import {
IShaderModuleService, IShaderModuleService,
IStyleAttributeService, IStyleAttributeService,
lazyInject, lazyInject,
Triangulation,
TYPES, TYPES,
} from '@antv/l7-core'; } from '@antv/l7-core';
export default class BaseModel implements ILayerModel { export default class BaseModel implements ILayerModel {
public triangulation: Triangulation;
protected layer: ILayer; protected layer: ILayer;
@lazyInject(TYPES.IGlobalConfigService) @lazyInject(TYPES.IGlobalConfigService)
@ -57,7 +62,14 @@ export default class BaseModel implements ILayerModel {
public buildModels(): IModel[] { public buildModels(): IModel[] {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
public getAttribute(): {
attributes: {
[attributeName: string]: IAttribute;
};
elements: IElements;
} {
throw new Error('Method not implemented.');
}
public render() { public render() {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }

View File

@ -27,18 +27,16 @@ export default class DataMappingPlugin implements ILayerPlugin {
}: { styleAttributeService: IStyleAttributeService }, }: { styleAttributeService: IStyleAttributeService },
) { ) {
layer.hooks.init.tap('DataMappingPlugin', () => { layer.hooks.init.tap('DataMappingPlugin', () => {
console.time('DataMappingPlugin') this.doMaping(layer, { styleAttributeService });
const attributes = styleAttributeService.getLayerStyleAttributes() || []; });
const { dataArray } = layer.getSource().data;
// TODO: FIXME layer.hooks.beforeRenderData.tap('DataMappingPlugin', (flag) => {
if (!dataArray) { if (flag) {
return; layer.dataPluginsState.DataMapping = false;
this.doMaping(layer, { styleAttributeService });
return true;
} }
return false;
// mapping with source data
layer.setEncodedData(this.mapping(attributes, dataArray));
console.timeEnd('DataMappingPlugin')
}); });
// remapping before render // remapping before render
@ -54,6 +52,29 @@ export default class DataMappingPlugin implements ILayerPlugin {
} }
}); });
} }
private doMaping(
layer: ILayer,
{
styleAttributeService,
}: { styleAttributeService: IStyleAttributeService },
) {
const attributes = styleAttributeService.getLayerStyleAttributes() || [];
const filter = styleAttributeService.getLayerStyleAttribute('filter');
const { dataArray } = layer.getSource().data;
let filterData = dataArray;
if (filter?.scale) {
filterData = dataArray.filter((record: IParseDataItem) => {
return this.applyAttributeMapping(filter, record)[0];
});
}
// TODO: FIXME
if (!filterData) {
return;
}
// mapping with source data
layer.setEncodedData(this.mapping(attributes, filterData));
}
private mapping( private mapping(
attributes: IStyleAttribute[], attributes: IStyleAttribute[],
@ -64,21 +85,22 @@ export default class DataMappingPlugin implements ILayerPlugin {
id: record._id, id: record._id,
coordinates: record.coordinates, coordinates: record.coordinates,
}; };
// TODO 数据过滤 attributes
attributes.forEach((attribute: IStyleAttribute) => { // .filter((attribute) => attribute.name !== 'filter')
let values = this.applyAttributeMapping(attribute, record); .forEach((attribute: IStyleAttribute) => {
attribute.needRemapping = false; let values = this.applyAttributeMapping(attribute, record);
attribute.needRemapping = false;
// TODO: 支持每个属性配置 postprocess // TODO: 支持每个属性配置 postprocess
if (attribute.name === 'color') { if (attribute.name === 'color') {
values = values.map((c: unknown) => { values = values.map((c: unknown) => {
return rgb2arr(c as string); return rgb2arr(c as string);
}); });
} }
// @ts-ignore // @ts-ignore
encodeRecord[attribute.name] = encodeRecord[attribute.name] =
Array.isArray(values) && values.length === 1 ? values[0] : values; Array.isArray(values) && values.length === 1 ? values[0] : values;
}); });
return encodeRecord; return encodeRecord;
}) as IEncodeFeature[]; }) as IEncodeFeature[];
} }

View File

@ -6,10 +6,16 @@ import { injectable } from 'inversify';
export default class DataSourcePlugin implements ILayerPlugin { export default class DataSourcePlugin implements ILayerPlugin {
public apply(layer: ILayer) { public apply(layer: ILayer) {
layer.hooks.init.tap('DataSourcePlugin', () => { layer.hooks.init.tap('DataSourcePlugin', () => {
console.time('DataSourcePlugin')
const { data, options } = layer.sourceOption; const { data, options } = layer.sourceOption;
layer.setSource(new Source(data, options)); layer.setSource(new Source(data, options));
console.timeEnd('DataSourcePlugin') });
// 检测数据是不否需要更新
layer.hooks.beforeRenderData.tap('DataSourcePlugin', (flag) => {
if (layer.isSourceNeedUpdate()) {
return true;
}
return false;
}); });
} }
} }

View File

@ -8,6 +8,7 @@ import {
IStyleAttribute, IStyleAttribute,
IStyleAttributeService, IStyleAttributeService,
IStyleScale, IStyleScale,
ScaleTypeName,
ScaleTypes, ScaleTypes,
StyleScaleType, StyleScaleType,
TYPES, TYPES,
@ -57,12 +58,22 @@ export default class FeatureScalePlugin implements ILayerPlugin {
}: { styleAttributeService: IStyleAttributeService }, }: { styleAttributeService: IStyleAttributeService },
) { ) {
layer.hooks.init.tap('FeatureScalePlugin', () => { layer.hooks.init.tap('FeatureScalePlugin', () => {
console.time('FeatureScalePlugin')
this.scaleOptions = layer.getScaleOptions(); this.scaleOptions = layer.getScaleOptions();
const attributes = styleAttributeService.getLayerStyleAttributes(); const attributes = styleAttributeService.getLayerStyleAttributes();
const { dataArray } = layer.getSource().data; const { dataArray } = layer.getSource().data;
this.caculateScalesForAttributes(attributes || [], dataArray); this.caculateScalesForAttributes(attributes || [], dataArray);
console.timeEnd('FeatureScalePlugin') });
// 检测数据是不否需要更新
layer.hooks.beforeRenderData.tap('FeatureScalePlugin', (flag) => {
if (flag) {
this.scaleOptions = layer.getScaleOptions();
const attributes = styleAttributeService.getLayerStyleAttributes();
const { dataArray } = layer.getSource().data;
this.caculateScalesForAttributes(attributes || [], dataArray);
return true;
}
return false;
}); });
layer.hooks.beforeRender.tap('FeatureScalePlugin', () => { layer.hooks.beforeRender.tap('FeatureScalePlugin', () => {
@ -225,7 +236,7 @@ export default class FeatureScalePlugin implements ILayerPlugin {
} }
private createDefaultScaleConfig( private createDefaultScaleConfig(
type: ScaleTypes, type: ScaleTypeName,
field: string, field: string,
data?: IParseDataItem[], data?: IParseDataItem[],
) { ) {

View File

@ -38,7 +38,6 @@ export default class PixelPickingPlugin implements ILayerPlugin {
) { ) {
// TODO: 由于 Shader 目前无法根据是否开启拾取进行内容修改,因此即使不开启也需要生成 a_PickingColor // TODO: 由于 Shader 目前无法根据是否开启拾取进行内容修改,因此即使不开启也需要生成 a_PickingColor
layer.hooks.init.tap('PixelPickingPlugin', () => { layer.hooks.init.tap('PixelPickingPlugin', () => {
console.time('PixelPickingPlugin')
const { enablePicking } = layer.getLayerConfig(); const { enablePicking } = layer.getLayerConfig();
styleAttributeService.registerStyleAttribute({ styleAttributeService.registerStyleAttribute({
name: 'pickingColor', name: 'pickingColor',
@ -56,7 +55,6 @@ export default class PixelPickingPlugin implements ILayerPlugin {
enablePicking ? encodePickingColor(featureIdx) : [0, 0, 0], enablePicking ? encodePickingColor(featureIdx) : [0, 0, 0],
}, },
}); });
console.timeEnd('PixelPickingPlugin')
}); });
// 必须要与 PixelPickingPass 结合使用,因此必须开启 multiPassRenderer // 必须要与 PixelPickingPass 结合使用,因此必须开启 multiPassRenderer
// if (layer.multiPassRenderer) { // if (layer.multiPassRenderer) {

View File

@ -25,9 +25,7 @@ export default class RegisterStyleAttributePlugin implements ILayerPlugin {
}: { styleAttributeService: IStyleAttributeService }, }: { styleAttributeService: IStyleAttributeService },
) { ) {
layer.hooks.init.tap('RegisterStyleAttributePlugin', () => { layer.hooks.init.tap('RegisterStyleAttributePlugin', () => {
console.time('RegisterStyleAttributePlugin')
this.registerBuiltinAttributes(styleAttributeService); this.registerBuiltinAttributes(styleAttributeService);
console.timeEnd('RegisterStyleAttributePlugin')
}); });
} }
@ -56,6 +54,24 @@ export default class RegisterStyleAttributePlugin implements ILayerPlugin {
}, },
}); });
styleAttributeService.registerStyleAttribute({
name: 'filter',
type: AttributeType.Attribute,
descriptor: {
name: 'filter',
buffer: {
// give the WebGL driver a hint that this buffer may change
usage: gl.DYNAMIC_DRAW,
data: [],
type: gl.FLOAT,
},
size: 1,
update: (feature: IEncodeFeature, featureIdx: number) => {
const { filter } = feature;
return filter ? [1] : [0];
},
},
});
styleAttributeService.registerStyleAttribute({ styleAttributeService.registerStyleAttribute({
name: 'color', name: 'color',
type: AttributeType.Attribute, type: AttributeType.Attribute,

View File

@ -31,7 +31,7 @@ export default class ShaderUniformPlugin implements ILayerPlugin {
public apply(layer: ILayer) { public apply(layer: ILayer) {
layer.hooks.beforeRender.tap('ShaderUniformPlugin', () => { layer.hooks.beforeRender.tap('ShaderUniformPlugin', () => {
// 重新计算坐标系参数 // 重新计算坐标系参数
console.time('ShaderUniformPlugin')
this.coordinateSystemService.refresh(); this.coordinateSystemService.refresh();
const { width, height } = this.rendererService.getViewportSize(); const { width, height } = this.rendererService.getViewportSize();
@ -59,7 +59,7 @@ export default class ShaderUniformPlugin implements ILayerPlugin {
u_ModelMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], u_ModelMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
}), }),
); );
console.timeEnd('ShaderUniformPlugin')
// TODO脏检查决定是否需要渲染 // TODO脏检查决定是否需要渲染
}); });
} }

View File

@ -22,24 +22,46 @@ export default class UpdateStyleAttributePlugin implements ILayerPlugin {
}: { styleAttributeService: IStyleAttributeService }, }: { styleAttributeService: IStyleAttributeService },
) { ) {
layer.hooks.init.tap('UpdateStyleAttributePlugin', () => { layer.hooks.init.tap('UpdateStyleAttributePlugin', () => {
console.time('UpdateStyleAttributePlugin') this.updateStyleAtrribute(layer, { styleAttributeService });
const attributes = styleAttributeService.getLayerStyleAttributes() || []; });
attributes
.filter((attribute) => attribute.needRegenerateVertices) layer.hooks.beforeRenderData.tap('styleAttributeService', (flag) => {
.forEach((attribute) => { if (flag) {
// 精确更新某个/某些 feature(s),需要传入 featureIdx // styleAttributeService.createAttributesAndIndices(
styleAttributeService.updateAttributeByFeatureRange( // layer.getEncodedData(),
attribute.name, // );
layer.getEncodedData(), // 获取经过 mapping 最新的数据 layer.layerModelNeedUpdate = true;
attribute.featureRange.startIndex, return true;
attribute.featureRange.endIndex, }
); return false;
attribute.needRegenerateVertices = false; });
this.logger.debug(
`regenerate vertex attributes: ${attribute.name} finished`, layer.hooks.beforeRender.tap('UpdateStyleAttributePlugin', () => {
); this.updateStyleAtrribute(layer, { styleAttributeService });
});
console.timeEnd('UpdateStyleAttributePlugin')
}); });
} }
private updateStyleAtrribute(
layer: ILayer,
{
styleAttributeService,
}: { styleAttributeService: IStyleAttributeService },
) {
const attributes = styleAttributeService.getLayerStyleAttributes() || [];
attributes
.filter((attribute) => attribute.needRegenerateVertices)
.forEach((attribute) => {
// 精确更新某个/某些 feature(s),需要传入 featureIdx
styleAttributeService.updateAttributeByFeatureRange(
attribute.name,
layer.getEncodedData(), // 获取经过 mapping 最新的数据
attribute.featureRange.startIndex,
attribute.featureRange.endIndex,
);
attribute.needRegenerateVertices = false;
this.logger.debug(
`regenerate vertex attributes: ${attribute.name} finished`,
);
});
}
} }

View File

@ -20,11 +20,15 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
}; };
} }
protected renderModels() { protected renderModels() {
this.models.forEach((model) => if (this.layerModelNeedUpdate) {
this.models = this.layerModel.buildModels();
this.layerModelNeedUpdate = false;
}
this.models.forEach((model) => {
model.draw({ model.draw({
uniforms: this.layerModel.getUninforms(), uniforms: this.layerModel.getUninforms(),
}), });
); });
return this; return this;
} }
@ -59,4 +63,9 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
return 'text'; return 'text';
} }
} }
private updateData() {
// const bounds = this.mapService.getBounds();
// console.log(bounds);
}
} }

View File

@ -1,6 +1,8 @@
import { import {
AttributeType, AttributeType,
gl, gl,
IAttribute,
IElements,
IEncodeFeature, IEncodeFeature,
IModel, IModel,
IModelUniform, IModelUniform,
@ -29,6 +31,17 @@ export default class FillModel extends BaseModel {
}; };
} }
public getAttribute(): {
attributes: {
[attributeName: string]: IAttribute;
};
elements: IElements;
} {
return this.styleAttributeService.createAttributesAndIndices(
this.layer.getEncodedData(),
PointFillTriangulation,
);
}
public buildModels(): IModel[] { public buildModels(): IModel[] {
return [ return [
this.layer.buildLayerModel({ this.layer.buildLayerModel({

View File

@ -130,10 +130,16 @@ export default class AMapService
const amapBound = this.map.getBounds().toBounds(); const amapBound = this.map.getBounds().toBounds();
const NE = amapBound.getNorthEast(); const NE = amapBound.getNorthEast();
const SW = amapBound.getSouthWest(); const SW = amapBound.getSouthWest();
const center = this.getCenter();
const maxlng =
center.lng > NE.getLng() || center.lng < SW.getLng()
? 180 - NE.getLng()
: NE.getLng();
const minlng = center.lng < SW.getLng() ? SW.getLng() - 180 : SW.getLng();
// 兼容 Mapbox统一返回西南、东北 // 兼容 Mapbox统一返回西南、东北
return [ return [
[SW.getLng(), SW.getLat()], [minlng, SW.getLat()],
[NE.getLng(), NE.getLat()], [maxlng, NE.getLat()],
]; ];
} }

View File

@ -6,6 +6,9 @@ export const MapTheme: {
normal: 'mapbox://styles/mapbox/streets-v11', normal: 'mapbox://styles/mapbox/streets-v11',
blank: { blank: {
version: 8, version: 8,
sprite: 'https://lzxue.github.io/font-glyphs/sprite/sprite',
glyphs:
'https://gw.alipayobjects.com/os/antvdemo/assets/mapbox/glyphs/{fontstack}/{range}.pbf',
sources: {}, sources: {},
layers: [ layers: [
{ {

View File

@ -52,14 +52,14 @@ export default class ReglRendererService implements IRendererService {
// TODO: use extensions // TODO: use extensions
extensions: [ extensions: [
'OES_element_index_uint', 'OES_element_index_uint',
'EXT_shader_texture_lod', // IBL // 'EXT_shader_texture_lod', // IBL 兼容性问题
'OES_standard_derivatives', // wireframe // 'OES_standard_derivatives', // wireframe
'OES_texture_float', // shadow map 'OES_texture_float', // shadow map
'WEBGL_depth_texture', // 'WEBGL_depth_texture',
'angle_instanced_arrays', 'angle_instanced_arrays',
'EXT_texture_filter_anisotropic', // VSM shadow map // 'EXT_texture_filter_anisotropic', // VSM shadow map
], ],
optionalExtensions: ['oes_texture_float_linear'], // optionalExtensions: ['oes_texture_float_linear'],
// profile: true, // profile: true,
onDone: (err: Error | null, r?: regl.Regl | undefined): void => { onDone: (err: Error | null, r?: regl.Regl | undefined): void => {
if (err || !r) { if (err || !r) {
@ -131,6 +131,13 @@ export default class ReglRendererService implements IRendererService {
}) => { }) => {
// use WebGL context directly // use WebGL context directly
// @see https://github.com/regl-project/regl/blob/gh-pages/API.md#unsafe-escape-hatch // @see https://github.com/regl-project/regl/blob/gh-pages/API.md#unsafe-escape-hatch
const renderCanvas = this.$container?.getElementsByTagName('canvas')[0];
if (renderCanvas) {
renderCanvas.width = width;
renderCanvas.height = height;
renderCanvas.style.width = width / 2 + 'px';
renderCanvas.style.height = height / 2 + 'px';
}
this.gl._gl.viewport(x, y, width, height); this.gl._gl.viewport(x, y, width, height);
this.gl._refresh(); this.gl._refresh();
}; };

View File

@ -14,7 +14,7 @@ import {
Properties, Properties,
} from '@turf/helpers'; } from '@turf/helpers';
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import { cloneDeep, isString, isFunction } from 'lodash'; import { cloneDeep, isFunction, isString } from 'lodash';
import Supercluster from 'supercluster'; import Supercluster from 'supercluster';
import { SyncHook } from 'tapable'; import { SyncHook } from 'tapable';
import { getParser, getTransform } from './'; import { getParser, getTransform } from './';
@ -34,17 +34,19 @@ export default class Source extends EventEmitter {
}; };
public parser: IParserCfg = { type: 'geojson' }; public parser: IParserCfg = { type: 'geojson' };
public transforms: ITransform[] = []; public transforms: ITransform[] = [];
public cluster: boolean = false;
public clusterOptions: Partial<IClusterOptions> = {
enable: false,
radius: 40,
maxZoom: 20,
zoom: -99,
method: 'count',
};
// 原始数据 // 原始数据
private originData: any; private originData: any;
private rawData: any; private rawData: any;
private clusterOptions: Partial<IClusterOptions> = {
enable: false,
radius: 40,
maxZoom: 20,
method: 'count',
};
private cluster: boolean = false;
private clusterIndex: Supercluster; private clusterIndex: Supercluster;
constructor(data: any, cfg?: ISourceCFG) { constructor(data: any, cfg?: ISourceCFG) {
@ -58,6 +60,7 @@ export default class Source extends EventEmitter {
if (cfg.transforms) { if (cfg.transforms) {
this.transforms = cfg.transforms; this.transforms = cfg.transforms;
} }
this.cluster = cfg.cluster || false;
if (cfg.clusterOptions) { if (cfg.clusterOptions) {
this.cluster = true; this.cluster = true;
this.clusterOptions = { this.clusterOptions = {
@ -82,35 +85,40 @@ export default class Source extends EventEmitter {
public updateClusterData( public updateClusterData(
zoom: number, zoom: number,
bbox: [number, number, number, number], bbox: [number, number, number, number],
): any { ): void {
const { method = 'sum', field } = this.clusterOptions; const { method = 'sum', field } = this.clusterOptions;
const data = this.clusterIndex.getClusters(bbox, zoom); let data = this.clusterIndex.getClusters(bbox, zoom);
if (!field && !isFunction(method)) { this.clusterOptions.bbox = bbox;
return; this.clusterOptions.zoom = zoom;
} data.forEach((p) => {
if (!p.id) {
const clusterdata = data.map((item) => { p.properties.point_count = 1;
const id = item.id as number;
if (id) {
const points = this.clusterIndex.getLeaves(id, Infinity);
const properties = points.map((d) => d.properties);
let statNum;
if (isString(method) && field) {
const column = getColumn(properties, field);
statNum = statMap[method](column);
}
if (isFunction(method)) {
statNum = method(properties);
}
item.properties.stat = statNum;
} }
return item;
}); });
if (field || isFunction(method)) {
data = data.map((item) => {
const id = item.id as number;
if (id) {
const points = this.clusterIndex.getLeaves(id, Infinity);
const properties = points.map((d) => d.properties);
let statNum;
if (isString(method) && field) {
const column = getColumn(properties, field);
statNum = statMap[method](column);
}
if (isFunction(method)) {
statNum = method(properties);
}
item.properties.stat = statNum;
} else {
item.properties.point_count = 1;
}
return item;
});
}
this.data = getParser('geojson')({ this.data = getParser('geojson')({
type: 'FeatureCollection', type: 'FeatureCollection',
features: clusterdata, features: data,
}); });
this.executeTrans(); this.executeTrans();
} }

View File

@ -128,3 +128,17 @@ export function setTransform(el: ELType, value: string) {
// @ts-ignore // @ts-ignore
el.style[transformProp] = value; el.style[transformProp] = value;
} }
export function triggerResize() {
if (typeof Event === 'function') {
// modern browsers
window.dispatchEvent(new Event('resize'));
} else {
// for IE and other old browsers
// causes deprecation warning on modern browsers
const evt = window.document.createEvent('UIEvents');
// @ts-ignore
evt.initUIEvent('resize', true, false, window, 0);
window.dispatchEvent(evt);
}
}

View File

@ -16,34 +16,37 @@ export default class Point3D extends React.Component {
'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json',
); );
const pointsData = await response.json(); const pointsData = await response.json();
const scene = new Scene({ const scene = new Scene({
id: 'map', id: 'map',
map: new GaodeMap({ map: new GaodeMap({
center: [120.19382669582967, 30.258134], center: [120.19382669582967, 30.258134],
pitch: 0, pitch: 0,
style: 'light', style: 'dark',
zoom: 3, zoom: 3,
}), }),
// map: new Mapbox({
// center: [120.19382669582967, 30.258134],
// pitch: 0,
// style: 'mapbox://styles/mapbox/streets-v9',
// zoom: 1,
// }),
}); });
this.scene = scene;
const pointLayer = new PointLayer({}) const pointLayer = new PointLayer({})
.source(pointsData) .source(pointsData, {
.shape('circle') cluster: true,
.size('mag', [1, 25])
.color('mag', (mag) => {
return mag > 4.5 ? '#5B8FF9' : '#5CCEA1';
}) })
.shape('circle')
.scale('point_count', {
type: 'quantile',
})
.filter('point_count', (point_count: number) => {
return point_count > 1;
})
.size('point_count', [5, 10, 15, 20, 25])
.color('red')
.style({ .style({
opacity: 0.3, opacity: 0.3,
strokeWidth: 1, strokeWidth: 1,
}); });
scene.addLayer(pointLayer); scene.addLayer(pointLayer);
this.scene = scene; console.log(pointLayer);
} }
public render() { public render() {

View File

@ -22,16 +22,18 @@ export default class Point3D extends React.Component {
}), }),
}); });
const pointLayer = new PointLayer({ const pointLayer = new PointLayer({
enablePicking: true, enablePicking: false,
enableHighlight: true, enableHighlight: false,
enableTAA: true, enableTAA: false,
onHover: (pickedFeature: any) => { onHover: (pickedFeature: any) => {
// tslint:disable-next-line:no-console // tslint:disable-next-line:no-console
console.log('Scene4', pickedFeature.feature.name); console.log('Scene4', pickedFeature.feature.name);
}, },
}); });
pointLayer pointLayer
.source(data) .source(data, {
cluster: true,
})
.color('red') .color('red')
.shape('cylinder') .shape('cylinder')
.size([15, 10]); .size([15, 10]);
@ -39,7 +41,6 @@ export default class Point3D extends React.Component {
scene.render(); scene.render();
this.scene = scene; this.scene = scene;
} }
public render() { public render() {
return ( return (
<div <div

View File

@ -53,9 +53,9 @@ export default class DataUpdate extends React.Component {
}); });
scene.addLayer(layer); scene.addLayer(layer);
function animateMarker(timestamp: number) { function animateMarker(timestamp: number) {
console.time('updatedata');
layer.setData(pointOnCircle(timestamp / 1000)); layer.setData(pointOnCircle(timestamp / 1000));
console.timeEnd('updatedata');
scene.render(); scene.render();
// setTimeout(animateMarker, 100); // setTimeout(animateMarker, 100);
@ -63,7 +63,6 @@ export default class DataUpdate extends React.Component {
} }
layer.on('inited', () => { layer.on('inited', () => {
animateMarker(0); animateMarker(0);
console.log('inited');
}); });
} }

View File

@ -29,4 +29,4 @@
}, },
"include": ["packages"], "include": ["packages"],
"exclude": ["node_modules", "packages/**/dist"], "exclude": ["node_modules", "packages/**/dist"],
} }

View File

@ -8990,6 +8990,11 @@ element-resize-detector@^1.1.15:
dependencies: dependencies:
batch-processor "^1.0.0" batch-processor "^1.0.0"
element-resize-event@^3.0.3:
version "3.0.3"
resolved "https://registry.npmjs.org/element-resize-event/-/element-resize-event-3.0.3.tgz#3f59facef6b8f23fbd678a5f364ee5723af98a2a"
integrity sha512-vhGNxT87PdZA6Ak4E0QhArwGzNcSPUwSN7n9wCFLeBlY2NNuuiwguQuQIp7P5oB65PLJ892yKcHiqz1xLWeiug==
elliptic@^6.0.0: elliptic@^6.0.0:
version "6.5.2" version "6.5.2"
resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762"