my-openlayer 2.5.4 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/MyOl.d.ts +3 -22
- package/MyOl.js +52 -112
- package/README.md +116 -29
- package/core/line/Line.d.ts +24 -5
- package/core/line/Line.js +38 -10
- package/core/map/ConfigManager.d.ts +169 -89
- package/core/map/ConfigManager.js +157 -175
- package/core/map/MapBaseLayers.d.ts +6 -0
- package/core/map/MapBaseLayers.js +9 -0
- package/core/map/MapTools.d.ts +17 -1
- package/core/map/MapTools.js +39 -5
- package/core/point/Point.d.ts +54 -14
- package/core/point/Point.js +132 -76
- package/core/point/PointOverlay.d.ts +2 -4
- package/core/point/PointOverlay.js +2 -1
- package/core/point/PointPulseLayer.js +6 -4
- package/core/polygon/Polygon.d.ts +32 -17
- package/core/polygon/Polygon.js +87 -64
- package/core/polygon/PolygonHeatmapLayer.js +15 -2
- package/core/polygon/PolygonMaskLayer.d.ts +2 -2
- package/core/polygon/PolygonMaskLayer.js +3 -1
- package/core/polygon/PolygonStyleFactory.d.ts +4 -3
- package/core/projection/ProjectionManager.d.ts +66 -0
- package/core/projection/ProjectionManager.js +144 -0
- package/core/projection/index.d.ts +2 -0
- package/core/projection/index.js +1 -0
- package/core/select/SelectHandler.d.ts +1 -1
- package/core/vue-template-point/VueTemplatePoint.d.ts +2 -4
- package/core/vue-template-point/VueTemplatePoint.js +16 -2
- package/docs/.vitepress/config.mts +1 -0
- package/docs/Line.md +4 -4
- package/docs/MIGRATION-3.0.md +221 -0
- package/docs/Point.md +24 -6
- package/docs/Polygon.md +14 -5
- package/index.d.ts +6 -3
- package/index.js +4 -1
- package/package.json +6 -3
- package/types/base.d.ts +4 -4
- package/types/common.d.ts +8 -6
- package/types/handle.d.ts +34 -0
- package/types/handle.js +1 -0
- package/types/index.d.ts +1 -0
- package/types/line.d.ts +3 -2
- package/types/map.d.ts +1 -1
- package/types/point.d.ts +11 -3
- package/utils/ErrorHandler.d.ts +12 -0
- package/utils/ErrorHandler.js +21 -0
|
@@ -1,8 +1,163 @@
|
|
|
1
|
+
const BUILTIN_DEFAULTS = {
|
|
2
|
+
POINT_OPTIONS: { visible: true, zIndex: 21 },
|
|
3
|
+
POINT_TEXT_OPTIONS: {
|
|
4
|
+
textFont: '12px Calibri,sans-serif',
|
|
5
|
+
textFillColor: '#FFF',
|
|
6
|
+
textStrokeColor: '#000',
|
|
7
|
+
textStrokeWidth: 3,
|
|
8
|
+
textOffsetY: 20
|
|
9
|
+
},
|
|
10
|
+
POINT_ICON_SCALE: 1,
|
|
11
|
+
CLUSTER_OPTIONS: { distance: 40, minDistance: 0, zIndex: 21 },
|
|
12
|
+
DOM_POINT_OVERLAY_OPTIONS: { positioning: 'center-center', stopEvent: false },
|
|
13
|
+
LINE_OPTIONS: {
|
|
14
|
+
type: 'line',
|
|
15
|
+
strokeColor: 'rgba(3, 122, 255, 1)',
|
|
16
|
+
strokeWidth: 2,
|
|
17
|
+
visible: true,
|
|
18
|
+
layerName: 'lineLayer',
|
|
19
|
+
zIndex: 15
|
|
20
|
+
},
|
|
21
|
+
FLOW_LINE_OPTIONS: {
|
|
22
|
+
type: 'line',
|
|
23
|
+
strokeColor: 'rgba(3, 122, 255, 1)',
|
|
24
|
+
strokeWidth: 2,
|
|
25
|
+
visible: true,
|
|
26
|
+
layerName: 'lineLayer',
|
|
27
|
+
duration: 4000,
|
|
28
|
+
loop: true,
|
|
29
|
+
autoStart: true,
|
|
30
|
+
showBaseLine: true,
|
|
31
|
+
animationMode: 'icon',
|
|
32
|
+
flowSymbol: {
|
|
33
|
+
scale: 0.8,
|
|
34
|
+
rotateWithView: true,
|
|
35
|
+
count: 1,
|
|
36
|
+
spacing: 0.15
|
|
37
|
+
},
|
|
38
|
+
trailEnabled: false,
|
|
39
|
+
trailLength: 0,
|
|
40
|
+
zIndex: 16
|
|
41
|
+
},
|
|
42
|
+
POLYGON_OPTIONS: {
|
|
43
|
+
zIndex: 11,
|
|
44
|
+
visible: true,
|
|
45
|
+
textFont: '14px Calibri,sans-serif',
|
|
46
|
+
textFillColor: '#FFF',
|
|
47
|
+
textStrokeColor: '#409EFF',
|
|
48
|
+
textStrokeWidth: 2
|
|
49
|
+
},
|
|
50
|
+
POLYGON_COLOR_MAP: {
|
|
51
|
+
'0': 'rgba(255, 0, 0, 0.6)',
|
|
52
|
+
'1': 'rgba(245, 154, 35, 0.6)',
|
|
53
|
+
'2': 'rgba(255, 238, 0, 0.6)',
|
|
54
|
+
'3': 'rgba(1, 111, 255, 0.6)'
|
|
55
|
+
},
|
|
56
|
+
IMAGE_OPTIONS: { opacity: 1, visible: true, layerName: 'imageLayer', zIndex: 11 },
|
|
57
|
+
MASK_OPTIONS: { fillColor: 'rgba(0, 0, 0, 0.5)', opacity: 1, visible: true, layerName: 'maskLayer', zIndex: 12 },
|
|
58
|
+
TEXT_OPTIONS: { textFont: '14px Calibri,sans-serif', textFillColor: '#FFF', textStrokeColor: '#409EFF', textStrokeWidth: 2 },
|
|
59
|
+
HEATMAP_OPTIONS: { blur: 15, radius: 10, zIndex: 11, opacity: 1 },
|
|
60
|
+
HEATMAP_VALUE_KEY: 'value',
|
|
61
|
+
TIANDITU_CONFIG: {
|
|
62
|
+
BASE_URL: '//t{0-7}.tianditu.gov.cn/DataServer',
|
|
63
|
+
PROJECTION: 'EPSG:4326',
|
|
64
|
+
DEFAULT_ZINDEX: 9,
|
|
65
|
+
ANNOTATION_ZINDEX_OFFSET: 10
|
|
66
|
+
},
|
|
67
|
+
MAP_LAYERS_OPTIONS: { zIndex: 9, annotation: false, mapClip: false, mapClipData: undefined },
|
|
68
|
+
MYOL_OPTIONS: { layers: undefined, zoom: 10, center: [119.81, 29.969], extent: undefined },
|
|
69
|
+
VUE_TEMPLATE_POINT_OPTIONS: { positioning: 'center-center', stopEvent: false, visible: true, zIndex: 1 },
|
|
70
|
+
RIVER_LEVEL_WIDTH_MAP: { 1: 2, 2: 1, 3: 0.5, 4: 0.5, 5: 0.5 },
|
|
71
|
+
RIVER_LAYERS_BY_ZOOM_OPTIONS: {
|
|
72
|
+
type: 'river', levelCount: 5, zoomOffset: 8, strokeColor: 'rgb(0,113,255)', strokeWidth: 3,
|
|
73
|
+
visible: true, zIndex: 15, layerName: 'riverLayer', removeExisting: false
|
|
74
|
+
},
|
|
75
|
+
RIVER_WIDTH_BY_LEVEL_OPTIONS: {
|
|
76
|
+
type: 'river', layerName: 'river', strokeColor: 'rgba(3, 122, 255, 1)', strokeWidth: 2,
|
|
77
|
+
visible: true, zIndex: 15, removeExisting: false
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* 当前生效的 defaults。运行时通过 setDefaults 修改这里的值,getter 再合并。
|
|
82
|
+
* 深拷贝一份避免外部意外修改 BUILTIN_DEFAULTS。
|
|
83
|
+
*/
|
|
84
|
+
const currentDefaults = deepClone(BUILTIN_DEFAULTS);
|
|
85
|
+
function deepClone(obj) {
|
|
86
|
+
if (obj === null || typeof obj !== 'object')
|
|
87
|
+
return obj;
|
|
88
|
+
if (obj instanceof Date)
|
|
89
|
+
return new Date(obj.getTime());
|
|
90
|
+
if (Array.isArray(obj))
|
|
91
|
+
return obj.map(item => deepClone(item));
|
|
92
|
+
const cloned = {};
|
|
93
|
+
for (const k in obj) {
|
|
94
|
+
if (Object.prototype.hasOwnProperty.call(obj, k))
|
|
95
|
+
cloned[k] = deepClone(obj[k]);
|
|
96
|
+
}
|
|
97
|
+
return cloned;
|
|
98
|
+
}
|
|
99
|
+
function deepMerge(base, partial) {
|
|
100
|
+
const result = Array.isArray(base) ? [...base] : { ...base };
|
|
101
|
+
for (const k of Object.keys(partial)) {
|
|
102
|
+
const v = partial[k];
|
|
103
|
+
if (v && typeof v === 'object' && !Array.isArray(v) && !(v instanceof Date)) {
|
|
104
|
+
result[k] = deepMerge(result[k] ?? {}, v);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
result[k] = v;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
1
112
|
/**
|
|
2
113
|
* 配置管理类
|
|
3
114
|
* 用于统一管理默认配置和验证
|
|
115
|
+
*
|
|
116
|
+
* 运行时修改默认值:调用 ConfigManager.setDefaults('LINE_OPTIONS', { strokeWidth: 4 })
|
|
117
|
+
* 之后所有新创建的 Line/FlowLine 都将以此为默认。
|
|
4
118
|
*/
|
|
5
|
-
class ConfigManager {
|
|
119
|
+
export default class ConfigManager {
|
|
120
|
+
/** 运行时覆盖默认配置。partial 会与现有 default 做深合并,未提到的键保持原值。 */
|
|
121
|
+
static setDefaults(group, partial) {
|
|
122
|
+
currentDefaults[group] = deepMerge(currentDefaults[group], partial);
|
|
123
|
+
}
|
|
124
|
+
/** 取当前运行时 default(含 setDefaults 覆盖后的结果),返回深拷贝避免被外部修改。 */
|
|
125
|
+
static getDefaults(group) {
|
|
126
|
+
return deepClone(currentDefaults[group]);
|
|
127
|
+
}
|
|
128
|
+
/** 把所有 setDefaults 覆盖清掉,恢复到内置默认值。 */
|
|
129
|
+
static resetDefaults(group) {
|
|
130
|
+
if (group) {
|
|
131
|
+
currentDefaults[group] = deepClone(BUILTIN_DEFAULTS[group]);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
Object.keys(BUILTIN_DEFAULTS).forEach(k => {
|
|
135
|
+
currentDefaults[k] = deepClone(BUILTIN_DEFAULTS[k]);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ---------------- 兼容性 getter(旧 callsite 直接读字段,setDefaults 透明生效)----------------
|
|
140
|
+
static get DEFAULT_POINT_OPTIONS() { return currentDefaults.POINT_OPTIONS; }
|
|
141
|
+
static get DEFAULT_POINT_TEXT_OPTIONS() { return currentDefaults.POINT_TEXT_OPTIONS; }
|
|
142
|
+
static get DEFAULT_POINT_ICON_SCALE() { return currentDefaults.POINT_ICON_SCALE; }
|
|
143
|
+
static get DEFAULT_CLUSTER_OPTIONS() { return currentDefaults.CLUSTER_OPTIONS; }
|
|
144
|
+
static get DEFAULT_DOM_POINT_OVERLAY_OPTIONS() { return currentDefaults.DOM_POINT_OVERLAY_OPTIONS; }
|
|
145
|
+
static get DEFAULT_LINE_OPTIONS() { return currentDefaults.LINE_OPTIONS; }
|
|
146
|
+
static get DEFAULT_FLOW_LINE_OPTIONS() { return currentDefaults.FLOW_LINE_OPTIONS; }
|
|
147
|
+
static get DEFAULT_POLYGON_OPTIONS() { return currentDefaults.POLYGON_OPTIONS; }
|
|
148
|
+
static get DEFAULT_POLYGON_COLOR_MAP() { return currentDefaults.POLYGON_COLOR_MAP; }
|
|
149
|
+
static get DEFAULT_IMAGE_OPTIONS() { return currentDefaults.IMAGE_OPTIONS; }
|
|
150
|
+
static get DEFAULT_MASK_OPTIONS() { return currentDefaults.MASK_OPTIONS; }
|
|
151
|
+
static get DEFAULT_TEXT_OPTIONS() { return currentDefaults.TEXT_OPTIONS; }
|
|
152
|
+
static get DEFAULT_HEATMAP_OPTIONS() { return currentDefaults.HEATMAP_OPTIONS; }
|
|
153
|
+
static get DEFAULT_HEATMAP_VALUE_KEY() { return currentDefaults.HEATMAP_VALUE_KEY; }
|
|
154
|
+
static get TIANDITU_CONFIG() { return currentDefaults.TIANDITU_CONFIG; }
|
|
155
|
+
static get DEFAULT_MAP_LAYERS_OPTIONS() { return currentDefaults.MAP_LAYERS_OPTIONS; }
|
|
156
|
+
static get DEFAULT_MYOL_OPTIONS() { return currentDefaults.MYOL_OPTIONS; }
|
|
157
|
+
static get DEFAULT_VUE_TEMPLATE_POINT_OPTIONS() { return currentDefaults.VUE_TEMPLATE_POINT_OPTIONS; }
|
|
158
|
+
static get DEFAULT_RIVER_LEVEL_WIDTH_MAP() { return currentDefaults.RIVER_LEVEL_WIDTH_MAP; }
|
|
159
|
+
static get DEFAULT_RIVER_LAYERS_BY_ZOOM_OPTIONS() { return currentDefaults.RIVER_LAYERS_BY_ZOOM_OPTIONS; }
|
|
160
|
+
static get DEFAULT_RIVER_WIDTH_BY_LEVEL_OPTIONS() { return currentDefaults.RIVER_WIDTH_BY_LEVEL_OPTIONS; }
|
|
6
161
|
/**
|
|
7
162
|
* 合并配置选项
|
|
8
163
|
* @param defaultOptions 默认配置
|
|
@@ -29,179 +184,6 @@ class ConfigManager {
|
|
|
29
184
|
* @returns 克隆后的对象
|
|
30
185
|
*/
|
|
31
186
|
static deepClone(obj) {
|
|
32
|
-
|
|
33
|
-
return obj;
|
|
34
|
-
}
|
|
35
|
-
if (obj instanceof Date) {
|
|
36
|
-
return new Date(obj.getTime());
|
|
37
|
-
}
|
|
38
|
-
if (Array.isArray(obj)) {
|
|
39
|
-
return obj.map(item => ConfigManager.deepClone(item));
|
|
40
|
-
}
|
|
41
|
-
const cloned = {};
|
|
42
|
-
for (const key in obj) {
|
|
43
|
-
if (obj.hasOwnProperty(key)) {
|
|
44
|
-
cloned[key] = ConfigManager.deepClone(obj[key]);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return cloned;
|
|
187
|
+
return deepClone(obj);
|
|
48
188
|
}
|
|
49
189
|
}
|
|
50
|
-
/**
|
|
51
|
-
* 默认点位配置
|
|
52
|
-
*/
|
|
53
|
-
ConfigManager.DEFAULT_POINT_OPTIONS = {
|
|
54
|
-
visible: true,
|
|
55
|
-
zIndex: 21
|
|
56
|
-
};
|
|
57
|
-
ConfigManager.DEFAULT_POINT_TEXT_OPTIONS = {
|
|
58
|
-
textFont: '12px Calibri,sans-serif',
|
|
59
|
-
textFillColor: '#FFF',
|
|
60
|
-
textStrokeColor: '#000',
|
|
61
|
-
textStrokeWidth: 3,
|
|
62
|
-
textOffsetY: 20
|
|
63
|
-
};
|
|
64
|
-
ConfigManager.DEFAULT_POINT_ICON_SCALE = 1;
|
|
65
|
-
ConfigManager.DEFAULT_CLUSTER_OPTIONS = {
|
|
66
|
-
distance: 40,
|
|
67
|
-
minDistance: 0,
|
|
68
|
-
zIndex: 21
|
|
69
|
-
};
|
|
70
|
-
ConfigManager.DEFAULT_DOM_POINT_OVERLAY_OPTIONS = {
|
|
71
|
-
positioning: 'center-center',
|
|
72
|
-
stopEvent: false
|
|
73
|
-
};
|
|
74
|
-
/**
|
|
75
|
-
* 默认线配置
|
|
76
|
-
*/
|
|
77
|
-
ConfigManager.DEFAULT_LINE_OPTIONS = {
|
|
78
|
-
type: 'line',
|
|
79
|
-
strokeColor: 'rgba(3, 122, 255, 1)',
|
|
80
|
-
strokeWidth: 2,
|
|
81
|
-
visible: true,
|
|
82
|
-
layerName: 'lineLayer',
|
|
83
|
-
zIndex: 15
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* 默认流动线动画配置
|
|
87
|
-
*/
|
|
88
|
-
ConfigManager.DEFAULT_FLOW_LINE_OPTIONS = {
|
|
89
|
-
...ConfigManager.DEFAULT_LINE_OPTIONS,
|
|
90
|
-
duration: 4000,
|
|
91
|
-
loop: true,
|
|
92
|
-
autoStart: true,
|
|
93
|
-
showBaseLine: true,
|
|
94
|
-
animationMode: 'icon',
|
|
95
|
-
flowSymbol: {
|
|
96
|
-
scale: 0.8,
|
|
97
|
-
rotateWithView: true,
|
|
98
|
-
count: 1,
|
|
99
|
-
spacing: 0.15
|
|
100
|
-
},
|
|
101
|
-
trailEnabled: false,
|
|
102
|
-
trailLength: 0,
|
|
103
|
-
zIndex: 16
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* 默认面配置
|
|
107
|
-
*/
|
|
108
|
-
ConfigManager.DEFAULT_POLYGON_OPTIONS = {
|
|
109
|
-
zIndex: 11,
|
|
110
|
-
visible: true,
|
|
111
|
-
textFont: '14px Calibri,sans-serif',
|
|
112
|
-
textFillColor: '#FFF',
|
|
113
|
-
textStrokeColor: '#409EFF',
|
|
114
|
-
textStrokeWidth: 2
|
|
115
|
-
};
|
|
116
|
-
ConfigManager.DEFAULT_POLYGON_COLOR_MAP = {
|
|
117
|
-
'0': 'rgba(255, 0, 0, 0.6)',
|
|
118
|
-
'1': 'rgba(245, 154, 35, 0.6)',
|
|
119
|
-
'2': 'rgba(255, 238, 0, 0.6)',
|
|
120
|
-
'3': 'rgba(1, 111, 255, 0.6)'
|
|
121
|
-
};
|
|
122
|
-
/**
|
|
123
|
-
* 默认图片图层配置
|
|
124
|
-
*/
|
|
125
|
-
ConfigManager.DEFAULT_IMAGE_OPTIONS = {
|
|
126
|
-
opacity: 1,
|
|
127
|
-
visible: true,
|
|
128
|
-
layerName: 'imageLayer',
|
|
129
|
-
zIndex: 11
|
|
130
|
-
};
|
|
131
|
-
/**
|
|
132
|
-
* 默认遮罩图层配置
|
|
133
|
-
*/
|
|
134
|
-
ConfigManager.DEFAULT_MASK_OPTIONS = {
|
|
135
|
-
fillColor: 'rgba(0, 0, 0, 0.5)',
|
|
136
|
-
opacity: 1,
|
|
137
|
-
visible: true,
|
|
138
|
-
layerName: 'maskLayer'
|
|
139
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* 默认文本配置
|
|
142
|
-
*/
|
|
143
|
-
ConfigManager.DEFAULT_TEXT_OPTIONS = {
|
|
144
|
-
textFont: '14px Calibri,sans-serif',
|
|
145
|
-
textFillColor: '#FFF',
|
|
146
|
-
textStrokeColor: '#409EFF',
|
|
147
|
-
textStrokeWidth: 2
|
|
148
|
-
};
|
|
149
|
-
ConfigManager.DEFAULT_HEATMAP_OPTIONS = {
|
|
150
|
-
blur: 15,
|
|
151
|
-
radius: 10,
|
|
152
|
-
zIndex: 11,
|
|
153
|
-
opacity: 1
|
|
154
|
-
};
|
|
155
|
-
ConfigManager.DEFAULT_HEATMAP_VALUE_KEY = 'value';
|
|
156
|
-
ConfigManager.TIANDITU_CONFIG = {
|
|
157
|
-
BASE_URL: '//t{0-7}.tianditu.gov.cn/DataServer',
|
|
158
|
-
PROJECTION: 'EPSG:4326',
|
|
159
|
-
DEFAULT_ZINDEX: 9,
|
|
160
|
-
ANNOTATION_ZINDEX_OFFSET: 10
|
|
161
|
-
};
|
|
162
|
-
ConfigManager.DEFAULT_MAP_LAYERS_OPTIONS = {
|
|
163
|
-
zIndex: ConfigManager.TIANDITU_CONFIG.DEFAULT_ZINDEX,
|
|
164
|
-
annotation: false,
|
|
165
|
-
mapClip: false,
|
|
166
|
-
mapClipData: undefined
|
|
167
|
-
};
|
|
168
|
-
ConfigManager.DEFAULT_MYOL_OPTIONS = {
|
|
169
|
-
layers: undefined,
|
|
170
|
-
zoom: 10,
|
|
171
|
-
center: [119.81, 29.969],
|
|
172
|
-
extent: undefined
|
|
173
|
-
};
|
|
174
|
-
ConfigManager.DEFAULT_VUE_TEMPLATE_POINT_OPTIONS = {
|
|
175
|
-
positioning: 'center-center',
|
|
176
|
-
stopEvent: false,
|
|
177
|
-
visible: true,
|
|
178
|
-
zIndex: 1
|
|
179
|
-
};
|
|
180
|
-
ConfigManager.DEFAULT_RIVER_LEVEL_WIDTH_MAP = {
|
|
181
|
-
1: 2,
|
|
182
|
-
2: 1,
|
|
183
|
-
3: 0.5,
|
|
184
|
-
4: 0.5,
|
|
185
|
-
5: 0.5
|
|
186
|
-
};
|
|
187
|
-
ConfigManager.DEFAULT_RIVER_LAYERS_BY_ZOOM_OPTIONS = {
|
|
188
|
-
type: 'river',
|
|
189
|
-
levelCount: 5,
|
|
190
|
-
zoomOffset: 8,
|
|
191
|
-
strokeColor: 'rgb(0,113,255)',
|
|
192
|
-
strokeWidth: 3,
|
|
193
|
-
visible: true,
|
|
194
|
-
zIndex: 15,
|
|
195
|
-
layerName: 'riverLayer',
|
|
196
|
-
removeExisting: false
|
|
197
|
-
};
|
|
198
|
-
ConfigManager.DEFAULT_RIVER_WIDTH_BY_LEVEL_OPTIONS = {
|
|
199
|
-
type: 'river',
|
|
200
|
-
layerName: 'river',
|
|
201
|
-
strokeColor: 'rgba(3, 122, 255, 1)',
|
|
202
|
-
strokeWidth: 2,
|
|
203
|
-
visible: true,
|
|
204
|
-
zIndex: 15,
|
|
205
|
-
removeExisting: false
|
|
206
|
-
};
|
|
207
|
-
export default ConfigManager;
|
|
@@ -8,6 +8,7 @@ import { Tile as TileLayer } from "ol/layer";
|
|
|
8
8
|
import { TileWMS } from "ol/source";
|
|
9
9
|
import WMTSTileGrid from "ol/tilegrid/WMTS";
|
|
10
10
|
import XYZ from "ol/source/XYZ";
|
|
11
|
+
import BaseLayer from "ol/layer/Base";
|
|
11
12
|
import { MapLayersOptions, TiandituType, AnnotationLayerOptions, AnnotationType } from "../../types";
|
|
12
13
|
/**
|
|
13
14
|
* GeoServer图层选项接口
|
|
@@ -100,6 +101,11 @@ export default class MapBaseLayers {
|
|
|
100
101
|
* 获取当前底图类型
|
|
101
102
|
*/
|
|
102
103
|
getCurrentBaseLayerType(): string | null;
|
|
104
|
+
/**
|
|
105
|
+
* 获取当前可见底图对应的 BaseLayer 数组(多 layer 的底图类型会返回多个)。
|
|
106
|
+
* 用于 MapTools.setMapClip 等需要直接操作底图实例的场景。
|
|
107
|
+
*/
|
|
108
|
+
getCurrentBaseLayers(): BaseLayer[];
|
|
103
109
|
/**
|
|
104
110
|
* 获取默认底图类型
|
|
105
111
|
* @private
|
|
@@ -183,6 +183,15 @@ export default class MapBaseLayers {
|
|
|
183
183
|
getCurrentBaseLayerType() {
|
|
184
184
|
return this.currentBaseLayerType;
|
|
185
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* 获取当前可见底图对应的 BaseLayer 数组(多 layer 的底图类型会返回多个)。
|
|
188
|
+
* 用于 MapTools.setMapClip 等需要直接操作底图实例的场景。
|
|
189
|
+
*/
|
|
190
|
+
getCurrentBaseLayers() {
|
|
191
|
+
if (!this.currentBaseLayerType)
|
|
192
|
+
return [];
|
|
193
|
+
return (this.layers[this.currentBaseLayerType] ?? []);
|
|
194
|
+
}
|
|
186
195
|
/**
|
|
187
196
|
* 获取默认底图类型
|
|
188
197
|
* @private
|
package/core/map/MapTools.d.ts
CHANGED
|
@@ -33,7 +33,22 @@ export default class MapTools {
|
|
|
33
33
|
* 使用 Canvas clip 实现裁剪,支持多个闭合区域
|
|
34
34
|
* 注意:此方法会修改 baseLayer 的 prerender 和 postrender 事件
|
|
35
35
|
*/
|
|
36
|
-
static setMapClip(baseLayer:
|
|
36
|
+
static setMapClip(baseLayer: BaseLayer, data: MapJSONData): BaseLayer;
|
|
37
|
+
/**
|
|
38
|
+
* 用 GeoJSON 区域裁剪地图上**所有**图层(底图 + 注记 + 用户 vector 层)。
|
|
39
|
+
*
|
|
40
|
+
* 每个图层都会绑定 prerender/postrender 进行 canvas clip。这是 setMapClip
|
|
41
|
+
* 的批量版本,用于"整张地图只在某区域内可见"的需求(例如行政区聚焦)。
|
|
42
|
+
*
|
|
43
|
+
* 实例方法 mapTools.clipMap(data) 会自动用当前 map。
|
|
44
|
+
*/
|
|
45
|
+
clipMap(data: MapJSONData): void;
|
|
46
|
+
/**
|
|
47
|
+
* 用 GeoJSON 区域裁剪地图上所有图层(静态版本)。
|
|
48
|
+
* @param map 地图实例
|
|
49
|
+
* @param data 裁剪边界 GeoJSON
|
|
50
|
+
*/
|
|
51
|
+
static clipMap(map: Map, data: MapJSONData): void;
|
|
37
52
|
/**
|
|
38
53
|
* 移除图层
|
|
39
54
|
* @param layerName 图层名称
|
|
@@ -68,6 +83,7 @@ export default class MapTools {
|
|
|
68
83
|
* @param lttd 纬度
|
|
69
84
|
* @param zoom 缩放级别
|
|
70
85
|
* @param duration 动画时长
|
|
86
|
+
* @param projection
|
|
71
87
|
* @returns 定位是否成功
|
|
72
88
|
*/
|
|
73
89
|
locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number, projection?: {
|
package/core/map/MapTools.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import VectorSource from "ol/source/Vector";
|
|
3
3
|
import GeoJSON from "ol/format/GeoJSON";
|
|
4
|
+
import ImageStatic from "ol/source/ImageStatic";
|
|
4
5
|
import { ErrorHandler, ErrorType } from "../../utils/ErrorHandler";
|
|
5
6
|
import ValidationUtils from "../../utils/ValidationUtils";
|
|
6
7
|
import ProjectionUtils from "../../utils/ProjectionUtils";
|
|
@@ -84,7 +85,7 @@ class MapTools {
|
|
|
84
85
|
: event.frameState.coordinateToPixelTransform;
|
|
85
86
|
ctx.save();
|
|
86
87
|
ctx.beginPath();
|
|
87
|
-
features.forEach(
|
|
88
|
+
features.forEach(feature => {
|
|
88
89
|
const geometry = feature.getGeometry();
|
|
89
90
|
if (!geometry)
|
|
90
91
|
return;
|
|
@@ -112,15 +113,15 @@ class MapTools {
|
|
|
112
113
|
};
|
|
113
114
|
if (type === 'MultiPolygon') {
|
|
114
115
|
// MultiPolygon: [Polygon, Polygon] -> Polygon: [OuterRing, InnerRing, ...]
|
|
115
|
-
coordinates.forEach(
|
|
116
|
-
polygonCoords.forEach(
|
|
116
|
+
coordinates.forEach(polygonCoords => {
|
|
117
|
+
polygonCoords.forEach(ringCoords => {
|
|
117
118
|
drawRing(ringCoords);
|
|
118
119
|
});
|
|
119
120
|
});
|
|
120
121
|
}
|
|
121
122
|
else if (type === 'Polygon') {
|
|
122
123
|
// Polygon: [OuterRing, InnerRing, ...]
|
|
123
|
-
coordinates.forEach(
|
|
124
|
+
coordinates.forEach(ringCoords => {
|
|
124
125
|
drawRing(ringCoords);
|
|
125
126
|
});
|
|
126
127
|
}
|
|
@@ -133,6 +134,38 @@ class MapTools {
|
|
|
133
134
|
});
|
|
134
135
|
return baseLayer;
|
|
135
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* 用 GeoJSON 区域裁剪地图上**所有**图层(底图 + 注记 + 用户 vector 层)。
|
|
139
|
+
*
|
|
140
|
+
* 每个图层都会绑定 prerender/postrender 进行 canvas clip。这是 setMapClip
|
|
141
|
+
* 的批量版本,用于"整张地图只在某区域内可见"的需求(例如行政区聚焦)。
|
|
142
|
+
*
|
|
143
|
+
* 实例方法 mapTools.clipMap(data) 会自动用当前 map。
|
|
144
|
+
*/
|
|
145
|
+
clipMap(data) {
|
|
146
|
+
if (!this.map) {
|
|
147
|
+
throw new Error('Map instance is not available');
|
|
148
|
+
}
|
|
149
|
+
MapTools.clipMap(this.map, data);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 用 GeoJSON 区域裁剪地图上所有图层(静态版本)。
|
|
153
|
+
* @param map 地图实例
|
|
154
|
+
* @param data 裁剪边界 GeoJSON
|
|
155
|
+
*/
|
|
156
|
+
static clipMap(map, data) {
|
|
157
|
+
if (!map) {
|
|
158
|
+
throw new Error('Map instance is required');
|
|
159
|
+
}
|
|
160
|
+
map.getLayers().getArray().forEach(layer => {
|
|
161
|
+
try {
|
|
162
|
+
MapTools.setMapClip(layer, data);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
ErrorHandler.getInstance().warn('clipMap: 单层裁剪失败,跳过', { layer, error });
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
136
169
|
/**
|
|
137
170
|
* 移除图层
|
|
138
171
|
* @param layerName 图层名称
|
|
@@ -183,6 +216,7 @@ class MapTools {
|
|
|
183
216
|
* @param lttd 纬度
|
|
184
217
|
* @param zoom 缩放级别
|
|
185
218
|
* @param duration 动画时长
|
|
219
|
+
* @param projection
|
|
186
220
|
* @returns 定位是否成功
|
|
187
221
|
*/
|
|
188
222
|
locationAction(lgtd, lttd, zoom = 20, duration = 3000, projection) {
|
|
@@ -286,7 +320,7 @@ class MapTools {
|
|
|
286
320
|
layers.forEach((layer) => {
|
|
287
321
|
try {
|
|
288
322
|
const source = layer?.getSource?.();
|
|
289
|
-
const extent = source?.getExtent?.();
|
|
323
|
+
const extent = source?.getExtent?.() ?? (source instanceof ImageStatic ? source.getImageExtent() : undefined);
|
|
290
324
|
if (extent && !isEmpty(extent)) {
|
|
291
325
|
extend(overallExtent, extent);
|
|
292
326
|
hasValidExtent = true;
|
package/core/point/Point.d.ts
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import Map from "ol/Map";
|
|
2
2
|
import VectorLayer from "ol/layer/Vector";
|
|
3
3
|
import VectorSource from "ol/source/Vector";
|
|
4
|
-
import
|
|
4
|
+
import Overlay from 'ol/Overlay';
|
|
5
|
+
import { PointOptions, ClusterOptions, PointData, VueTemplatePointInstance, TwinkleItem, PulsePointOptions, PulsePointLayerHandle, LayerHandle, ControlHandle } from '../../types';
|
|
5
6
|
export default class Point {
|
|
6
7
|
private map;
|
|
8
|
+
/** 由本实例创建的纯图层(addPoint / addClusterPoint)。destroyAll 时统一移除。 */
|
|
9
|
+
private readonly managedLayers;
|
|
10
|
+
/** 由本实例创建的、需要主动 remove 的句柄(Pulse / DOM / Vue 模板)。 */
|
|
11
|
+
private readonly managedDisposables;
|
|
12
|
+
/** VueTemplatePoint 实例复用,避免每次调用 addVueTemplatePoint 都 new 一个无主实例。 */
|
|
13
|
+
private vueTemplatePoint?;
|
|
7
14
|
constructor(map: Map);
|
|
15
|
+
/** @internal */
|
|
16
|
+
private trackLayer;
|
|
17
|
+
/** @internal */
|
|
18
|
+
private trackDisposable;
|
|
19
|
+
/**
|
|
20
|
+
* 销毁本实例创建的所有图层与动画句柄。供 MyOl.destroy 调用。
|
|
21
|
+
*/
|
|
22
|
+
destroyAll(): void;
|
|
8
23
|
/**
|
|
9
24
|
* 创建文本样式
|
|
10
25
|
* @private
|
|
@@ -52,40 +67,65 @@ export default class Point {
|
|
|
52
67
|
* img: String 图标
|
|
53
68
|
* }
|
|
54
69
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
70
|
+
/** *********************创建普通点图层*********************/
|
|
71
|
+
private createPointLayer;
|
|
72
|
+
/** *********************创建聚合点图层*********************/
|
|
73
|
+
private createClusterPointLayer;
|
|
74
|
+
/** *********************添加普通点*********************/
|
|
75
|
+
addPoint(pointData: PointData[], options: PointOptions & {
|
|
76
|
+
layerName: string;
|
|
77
|
+
}): LayerHandle<VectorLayer<VectorSource>> | null;
|
|
78
|
+
/** *********************添加聚合点*********************/
|
|
79
|
+
addClusterPoint(pointData: PointData[], options: ClusterOptions & {
|
|
80
|
+
layerName: string;
|
|
81
|
+
}): LayerHandle<VectorLayer<VectorSource>> | null;
|
|
82
|
+
/** @internal 把 VectorLayer 包成 LayerHandle 的内部工具。 */
|
|
83
|
+
private toLayerHandle;
|
|
57
84
|
/**
|
|
58
85
|
* 添加高性能闪烁点图层。
|
|
59
86
|
*
|
|
60
87
|
* 与 addDomPoint 不同,该方法使用 VectorLayer 批量渲染点位,并通过单个
|
|
61
88
|
* requestAnimationFrame 驱动闪烁圈,适合村庄预警等大量点位场景。
|
|
62
89
|
*/
|
|
63
|
-
addPulsePointLayer(pointData: PointData[], options: PulsePointOptions
|
|
90
|
+
addPulsePointLayer(pointData: PointData[], options: PulsePointOptions & {
|
|
91
|
+
layerName: string;
|
|
92
|
+
}): PulsePointLayerHandle | null;
|
|
93
|
+
/**
|
|
94
|
+
* P1-2:从 URL 加载点位数据并添加为静态点图层。
|
|
95
|
+
*
|
|
96
|
+
* 期望 URL 返回 `PointData[]` 形态的 JSON 数组(含 lgtd / lttd)或 FeatureCollection。
|
|
97
|
+
* features 加载/解析完成后 Promise resolve 为 LayerHandle。
|
|
98
|
+
*/
|
|
99
|
+
addPointByUrl(url: string, options: PointOptions & {
|
|
100
|
+
layerName: string;
|
|
101
|
+
}): Promise<LayerHandle<VectorLayer<VectorSource>> | null>;
|
|
102
|
+
/**
|
|
103
|
+
* P1-2:从 URL 加载点位数据并添加为高性能闪烁点图层。
|
|
104
|
+
*/
|
|
105
|
+
addPulsePointLayerByUrl(url: string, options: PulsePointOptions & {
|
|
106
|
+
layerName: string;
|
|
107
|
+
}): Promise<PulsePointLayerHandle | null>;
|
|
64
108
|
/**
|
|
65
109
|
* 添加闪烁点
|
|
66
110
|
* @param twinkleList 闪烁点数据
|
|
67
111
|
* @param callback
|
|
68
112
|
*/
|
|
69
|
-
addDomPoint(twinkleList: TwinkleItem[], callback?: Function): {
|
|
70
|
-
anchors:
|
|
71
|
-
remove: () => void;
|
|
72
|
-
setVisible: (visible: boolean) => void;
|
|
113
|
+
addDomPoint(twinkleList: TwinkleItem[], callback?: Function): ControlHandle<Overlay[]> & {
|
|
114
|
+
anchors: Overlay[];
|
|
73
115
|
};
|
|
74
116
|
/**
|
|
75
117
|
* 添加vue组件为点位
|
|
76
118
|
* @param pointDataList 点位信息列表
|
|
77
119
|
* @param template vue组件模板
|
|
78
|
-
* @param
|
|
120
|
+
* @param options
|
|
79
121
|
* @returns 返回控制对象,包含显示、隐藏、移除方法
|
|
80
122
|
* @throws 当参数无效时抛出错误
|
|
81
123
|
*/
|
|
82
|
-
addVueTemplatePoint(pointDataList: PointData[], template:
|
|
124
|
+
addVueTemplatePoint(pointDataList: PointData[], template: object, options?: {
|
|
83
125
|
positioning?: 'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right';
|
|
84
126
|
stopEvent?: boolean;
|
|
85
|
-
}): {
|
|
86
|
-
|
|
87
|
-
setOneVisibleByProp: (propName: string, propValue: any, visible: boolean) => void;
|
|
88
|
-
remove: () => void;
|
|
127
|
+
}): ControlHandle<VueTemplatePointInstance[]> & {
|
|
128
|
+
setOneVisibleByProp: (propName: string, propValue: unknown, visible: boolean) => void;
|
|
89
129
|
getPoints: () => VueTemplatePointInstance[];
|
|
90
130
|
};
|
|
91
131
|
/**
|