Merge pull request #419 from antvis/district_attach

chore(layer): regl 对象销毁问题,数据频繁更新减少内存占用
This commit is contained in:
@thinkinggis 2020-07-04 14:22:45 +08:00 committed by GitHub
commit cdfca2f8e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 168 additions and 29 deletions

View File

@ -1,9 +1,9 @@
import { Scene, HeatmapLayer } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import { GaodeMap } from '@antv/l7-maps';
const scene = new Scene({
id: 'map',
map: new Mapbox({
map: new GaodeMap({
style: 'dark',
pitch: 58.5,
center: [ 111.8759, 30.6942 ],

View File

@ -57,6 +57,7 @@ export interface ILayerModel {
getDefaultStyle(): unknown;
getAnimateUniforms(): IModelUniform;
buildModels(): IModel[];
initModels(): IModel[];
needUpdate(): boolean;
}
export interface IModelUniform {
@ -118,6 +119,7 @@ export interface ILayer {
prepareBuildModel(): void;
renderModels(): void;
buildModels(): void;
rebuildModels(): void;
buildLayerModel(
options: ILayerModelInitializationOptions &
Partial<IModelInitializationOptions>,
@ -155,6 +157,8 @@ export interface ILayer {
setBlend(type: keyof typeof BlendType): void;
// animate(field: string, option: any): ILayer;
render(): ILayer;
clear(): void;
clearModels(): void;
destroy(): void;
source(data: any, option?: ISourceCFG): ILayer;
setData(data: any, option?: ISourceCFG): ILayer;

View File

@ -320,6 +320,8 @@ export default class StyleAttributeService implements IStyleAttributeService {
attribute.vertexAttribute.destroy();
}
});
this.attributesAndIndices.elements.destroy();
this.attributes = [];
}
}

View File

@ -6,6 +6,9 @@ export default class CityBuildingLayer extends BaseLayer {
public type: string = 'PolygonLayer';
public buildModels() {
this.layerModel = new CityBuildModel(this);
this.models = this.layerModel.initModels();
}
public rebuildModels() {
this.models = this.layerModel.buildModels();
}
public setLight(t: number) {

View File

@ -29,7 +29,7 @@ export default class CityBuildModel extends BaseModel {
};
}
public buildModels(): IModel[] {
public initModels(): IModel[] {
this.startModelAnimate();
return [
this.layer.buildLayerModel({

View File

@ -709,7 +709,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
// 清除所有属性以及关联的 vao
this.styleAttributeService.clearAllAttributes();
// 销毁所有 model
this.models.forEach((model) => model.destroy());
// this.models.forEach((model) => model.destroy());
this.hooks.afterDestroy.call();
@ -726,6 +726,8 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
public clear() {
this.styleAttributeService.clearAllAttributes();
// 销毁所有 model
}
public clearModels() {
this.models.forEach((model) => model.destroy());
}
@ -887,6 +889,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
public buildModels() {
throw new Error('Method not implemented.');
}
public rebuildModels() {
throw new Error('Method not implemented.');
}
public renderModels() {
if (this.layerModelNeedUpdate && this.layerModel) {

View File

@ -97,6 +97,9 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
public buildModels(): IModel[] {
throw new Error('Method not implemented.');
}
public initModels(): IModel[] {
throw new Error('Method not implemented.');
}
public getAttribute(): {
attributes: {
[attributeName: string]: IAttribute;

View File

@ -10,6 +10,9 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
public buildModels() {
const shape = this.getModelType();
this.layerModel = new HeatMapModels[shape](this);
this.models = this.layerModel.initModels();
}
public rebuildModels() {
this.models = this.layerModel.buildModels();
}
public renderModels() {

View File

@ -32,6 +32,10 @@ export default class GridModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -33,6 +33,10 @@ export default class Grid3DModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -55,7 +55,7 @@ export default class HeatMapModel extends BaseModel {
throw new Error('Method not implemented.');
}
public buildModels(): IModel[] {
public initModels(): IModel[] {
const {
createFramebuffer,
clear,
@ -99,6 +99,11 @@ export default class HeatMapModel extends BaseModel {
return [this.intensityModel, this.colorModel];
}
public buildModels(): IModel[] {
return this.initModels();
}
protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({
name: 'dir',

View File

@ -34,6 +34,10 @@ export default class HexagonModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -8,6 +8,9 @@ export default class ImageLayer extends BaseLayer<IImageLayerStyleOptions> {
public buildModels() {
const modelType = this.getModelType();
this.layerModel = new ImageModels[modelType](this);
this.models = this.layerModel.initModels();
}
public rebuildModels() {
this.models = this.layerModel.buildModels();
}
protected getConfigSchema() {

View File

@ -31,7 +31,7 @@ export default class ImageModel extends BaseModel {
u_texture: this.texture,
};
}
public buildModels() {
public initModels() {
const source = this.layer.getSource();
const { createTexture2D } = this.rendererService;
this.texture = createTexture2D({
@ -58,6 +58,9 @@ export default class ImageModel extends BaseModel {
}),
];
}
public buildModels() {
return this.initModels();
}
protected getConfigSchema() {
return {

View File

@ -8,6 +8,9 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
public buildModels() {
const shape = this.getModelType();
this.layerModel = new LineModels[shape](this);
this.models = this.layerModel.initModels();
}
public rebuildModels() {
this.models = this.layerModel.buildModels();
}

View File

@ -44,6 +44,10 @@ export default class ArcModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -41,6 +41,10 @@ export default class Arc3DModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -43,6 +43,10 @@ export default class GreatCircleModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -41,6 +41,10 @@ export default class LineModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -39,6 +39,9 @@ export default class DataMappingPlugin implements ILayerPlugin {
// remapping before render
layer.hooks.beforeRender.tap('DataMappingPlugin', () => {
if (layer.layerModelNeedUpdate) {
return;
}
const attributes = styleAttributeService.getLayerStyleAttributes() || [];
const filter = styleAttributeService.getLayerStyleAttribute('filter');
const { dataArray } = layer.getSource().data;

View File

@ -76,10 +76,14 @@ export default class FeatureScalePlugin implements ILayerPlugin {
// return;
// }
this.caculateScalesForAttributes(attributes || [], dataArray);
layer.layerModelNeedUpdate = true;
return true;
});
layer.hooks.beforeRender.tap('FeatureScalePlugin', () => {
if (layer.layerModelNeedUpdate) {
return;
}
this.scaleOptions = layer.getScaleOptions();
const attributes = styleAttributeService.getLayerStyleAttributes();
if (attributes) {

View File

@ -17,8 +17,10 @@ export default class LayerModelPlugin implements ILayerPlugin {
layer.hooks.beforeRenderData.tap('DataSourcePlugin', () => {
// 更新Model 配置项
layer.prepareBuildModel();
layer.clearModels();
// 初始化 Model
layer.buildModels();
layer.rebuildModels();
layer.layerModelNeedUpdate = false;
return false;
});

View File

@ -25,10 +25,10 @@ export default class UpdateStyleAttributePlugin implements ILayerPlugin {
this.initStyleAttribute(layer, { styleAttributeService });
});
layer.hooks.beforeRenderData.tap('styleAttributeService', () => {
layer.layerModelNeedUpdate = true;
return true;
});
// layer.hooks.beforeRenderData.tap('styleAttributeService', () => {
// // layer.layerModelNeedUpdate = true;
// return true;
// });
layer.hooks.beforeRender.tap('UpdateStyleAttributePlugin', () => {
if (layer.layerModelNeedUpdate) {

View File

@ -11,6 +11,11 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
public buildModels() {
const modelType = this.getModelType();
this.layerModel = new PointModels[modelType](this);
this.models = this.layerModel.initModels();
}
public rebuildModels() {
// const modelType = this.getModelType();
// this.layerModel = new PointModels[modelType](this);
this.models = this.layerModel.buildModels();
}
protected getConfigSchema() {

View File

@ -14,6 +14,9 @@ export default class ExtrudeModel extends BaseModel {
u_opacity: opacity || 1.0,
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [

View File

@ -54,6 +54,9 @@ export default class FillModel extends BaseModel {
PointFillTriangulation,
);
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -29,7 +29,7 @@ export default class IconeModel extends BaseModel {
};
}
public buildModels(): IModel[] {
public initModels(): IModel[] {
this.initIconFontGlyphs();
this.registerBuiltinAttributes();
this.updateTexture();

View File

@ -30,13 +30,17 @@ export default class ImageModel extends BaseModel {
};
}
public buildModels(): IModel[] {
public initModels(): IModel[] {
this.registerBuiltinAttributes();
this.updateTexture();
this.iconService.on('imageUpdate', () => {
this.updateTexture();
this.layer.render(); // TODO 调用全局render
});
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({
moduleName: 'pointImage',
@ -49,7 +53,6 @@ export default class ImageModel extends BaseModel {
}),
];
}
protected registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({
@ -107,6 +110,9 @@ export default class ImageModel extends BaseModel {
private updateTexture() {
const { createTexture2D } = this.rendererService;
if (this.texture) {
this.texture.destroy();
}
this.texture = createTexture2D({
data: this.iconService.getCanvas(),
mag: gl.LINEAR,

View File

@ -45,6 +45,11 @@ export default class NormalModel extends BaseModel {
u_stroke_color: rgb2arr(stroke),
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -141,7 +141,7 @@ export default class TextModel extends BaseModel {
};
}
public buildModels(): IModel[] {
public initModels(): IModel[] {
this.layer.on('remapping', () => {
this.initGlyph();
this.updateTexture();
@ -156,6 +156,10 @@ export default class TextModel extends BaseModel {
textAnchor,
textAllowOverlap,
};
return this.buildModels();
}
public buildModels(): IModel[] {
this.initGlyph();
this.updateTexture();
this.filterGlyphs();
@ -391,6 +395,9 @@ export default class TextModel extends BaseModel {
const { createTexture2D } = this.rendererService;
const { canvas } = this.fontService;
this.textureHeight = canvas.height;
if (this.texture) {
this.texture.destroy();
}
this.texture = createTexture2D({
data: canvas,
mag: gl.LINEAR,

View File

@ -12,9 +12,11 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
public buildModels() {
const shape = this.getModelType();
this.layerModel = new PolygonModels[shape](this);
this.models = this.layerModel.initModels();
}
public rebuildModels() {
this.models = this.layerModel.buildModels();
}
protected getConfigSchema() {
return {
properties: {

View File

@ -16,6 +16,10 @@ export default class ExtrudeModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -29,6 +29,10 @@ export default class FillModel extends BaseModel {
};
}
public initModels(): IModel[] {
return this.buildModels();
}
public buildModels(): IModel[] {
return [
this.layer.buildLayerModel({

View File

@ -14,6 +14,9 @@ export default class RaterLayer extends BaseLayer<IRasterLayerStyleOptions> {
public buildModels() {
const modelType = this.getModelType();
this.layerModel = new RasterModels[modelType](this);
this.models = this.layerModel.initModels();
}
public rebuildModels() {
this.models = this.layerModel.buildModels();
}
protected getConfigSchema() {

View File

@ -50,7 +50,7 @@ export default class RasterModel extends BaseModel {
};
}
public buildModels() {
public initModels() {
const source = this.layer.getSource();
const { createTexture2D } = this.rendererService;
const parserDataItem = source.data.dataArray[0];
@ -85,6 +85,9 @@ export default class RasterModel extends BaseModel {
];
}
public buildModels() {
return this.initModels();
}
protected registerBuiltinAttributes() {
// point layer size;
this.styleAttributeService.registerStyleAttribute({

View File

@ -30,7 +30,7 @@
"inversify": "^5.0.1",
"lodash": "^4.17.15",
"reflect-metadata": "^0.1.13",
"regl": "1.3.13"
"regl": "^1.6.1"
},
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0",
"publishConfig": {

View File

@ -1,5 +1,6 @@
import {
gl,
IAttribute,
IModel,
IModelDrawOptions,
IModelInitializationOptions,
@ -26,7 +27,10 @@ import ReglTexture2D from './ReglTexture2D';
*/
export default class ReglModel implements IModel {
private reGl: regl.Regl;
private destroyed: boolean = false;
private drawCommand: regl.DrawCommand;
private drawParams: regl.DrawConfig;
private options: IModelInitializationOptions;
private uniforms: {
[key: string]: IUniform;
} = {};
@ -48,6 +52,7 @@ export default class ReglModel implements IModel {
instances,
} = options;
const reglUniforms: { [key: string]: IUniform } = {};
this.options = options;
if (uniforms) {
this.uniforms = this.extractUniforms(uniforms);
Object.keys(uniforms).forEach((uniformName) => {
@ -86,7 +91,9 @@ export default class ReglModel implements IModel {
this.initBlendDrawParams({ blend }, drawParams);
this.initStencilDrawParams({ stencil }, drawParams);
this.initCullDrawParams({ cull }, drawParams);
this.drawCommand = reGl(drawParams);
this.drawParams = drawParams;
}
public addUniforms(uniforms: { [key: string]: IUniform }) {
@ -97,6 +104,12 @@ export default class ReglModel implements IModel {
}
public draw(options: IModelDrawOptions) {
if (
this.drawParams.attributes &&
Object.keys(this.drawParams.attributes).length === 0
) {
return;
}
const uniforms: {
[key: string]: IUniform;
} = {
@ -135,7 +148,15 @@ export default class ReglModel implements IModel {
}
public destroy() {
// don't need do anything since we will call `rendererService.cleanup()`
// @ts-ignore
this.drawParams.elements.destroy();
if (this.options.attributes) {
Object.values(this.options.attributes).forEach((attr: any) => {
// @ts-ignore
(attr as ReglAttribute).destroy();
});
}
this.destroyed = true;
}
/**

View File

@ -148,6 +148,14 @@ export default class Source extends EventEmitter {
return feature?._id;
}
public destroy() {
this.removeAllListeners();
this.originData = null;
this.clusterIndex = null;
// @ts-ignore
this.data = null;
}
private initCfg(cfg?: ISourceCFG) {
if (cfg) {
if (cfg.parser) {
@ -193,12 +201,6 @@ export default class Source extends EventEmitter {
const clusterOptions = this.clusterOptions || {};
this.clusterIndex = cluster(this.data, clusterOptions);
// this.clusterIndex = new Supercluster({
// radius,
// minZoom,
// maxZoom,
// });
// this.clusterIndex.load(this.rawData.features);
}
private init() {

View File

@ -22431,10 +22431,10 @@ regjsparser@^0.6.4:
dependencies:
jsesc "~0.5.0"
regl@1.3.13:
version "1.3.13"
resolved "https://registry.npmjs.org/regl/-/regl-1.3.13.tgz#c376bfa6477995a9be9cd21495a0c9beb9b2f3af"
integrity sha512-TTiCabJbbUykCL4otjqOvKqDFJhvJOT7xB51JxcDeSHGrEJl1zz4RthPcoOogqfuR3ECN4Te790DfHCXzli5WQ==
regl@^1.6.1:
version "1.6.1"
resolved "https://registry.npmjs.org/regl/-/regl-1.6.1.tgz#6930172cda9b8fb65724abc0d4930d79333f5460"
integrity sha512-7Z9rmpEqmLNwC9kCYCyfyu47eWZaQWeNpwZfwz99QueXN8B/Ow40DB0N+OeUeM/yu9pZAB01+JgJ+XghGveVoA==
rehype-react@^5.0.0:
version "5.0.1"