/
DataEncodePlugin.ts
126 lines (115 loc) · 3.59 KB
/
DataEncodePlugin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import {
IGlobalConfigService,
ILayer,
ILayerPlugin,
ILayerStyleAttribute,
IParseDataItem,
IStyleScale,
lazyInject,
StyleScaleType,
TYPES,
} from '@l7/core';
import { isString } from 'lodash';
import ScaleController from '../core/ScaleController';
import { rgb2arr } from '../utils/color';
export default class DataEncodePlugin implements ILayerPlugin {
@lazyInject(TYPES.IGlobalConfigService)
private readonly configService: IGlobalConfigService;
private scaleController: ScaleController;
private scaleCache: {
[fieldName: string]: IStyleScale;
} = {};
public apply(layer: ILayer) {
layer.hooks.init.tap('DataEncodePlugin', () => {
const source = layer.getSource();
const dataArray = source && source.data && source.data.dataArray;
if (!dataArray) {
return;
}
this.scaleController = new ScaleController(
this.configService.getConfig().scales || {},
);
// create scales by source data & config
Object.keys(layer.styleAttributes).forEach((attributeName) => {
const attribute = layer.styleAttributes[attributeName];
const scales: any[] = [];
attribute.names.forEach((field: string) => {
scales.push(this.getOrCreateScale(attribute, field, dataArray));
});
attribute.setScales(scales);
});
// mapping with source data
layer.setEncodedData(this.mapping(layer.styleAttributes, dataArray));
});
// TODO: remapping before render
// layer.hooks.beforeRender.tap()
}
private getOrCreateScale(
attribute: ILayerStyleAttribute,
field: string,
data: any[],
): IStyleScale {
let scale = this.scaleCache[field as string];
if (!scale) {
scale = this.scaleController.createScale(field as string, data);
if (
scale.type === StyleScaleType.VARIABLE &&
attribute.values &&
attribute.values.length > 0
) {
scale.scale.range(attribute.values);
}
this.scaleCache[field as string] = scale;
}
return {
...scale,
scale: scale.scale.copy(), // 存在相同字段映射不同通道的情况
};
}
private mapping(
attributes: {
[attributeName: string]: ILayerStyleAttribute;
},
data: IParseDataItem[],
): Array<{ [key: string]: unknown }> {
return data.map((record: IParseDataItem) => {
const encodeRecord: { [key: string]: unknown } = {
id: record._id,
coordinates: record.coordinates,
};
// TODO: 数据过滤
Object.keys(attributes).forEach((attributeName: string) => {
const attribute = attributes[attributeName];
// const { type } = attribute; // TODO: 支持常量 或变量
// if (type === StyleScaleType.CONSTANT) {
// return;
// }
let values = this.getAttrValue(attribute, record);
if (attributeName === 'color') {
values = values.map((c: unknown) => {
return rgb2arr(c as string);
});
}
encodeRecord[attributeName] =
Array.isArray(values) && values.length === 1 ? values[0] : values;
});
return encodeRecord;
});
}
private getAttrValue(
attribute: ILayerStyleAttribute,
record: { [key: string]: unknown },
) {
const scales = attribute.scales || [];
const params: unknown[] = [];
scales.forEach((scale) => {
const { field, type } = scale;
if (type === StyleScaleType.CONSTANT) {
params.push(scale.field);
} else {
params.push(record[field]);
}
});
return attribute.mapping ? attribute.mapping(...params) : [];
}
}