my-openlayer 1.0.0 → 1.0.2
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/dist/core/ConfigManager.d.ts +0 -25
- package/dist/core/ConfigManager.js +0 -52
- package/dist/core/DomPoint.js +10 -33
- package/dist/core/Line.d.ts +84 -13
- package/dist/core/Line.js +203 -79
- package/dist/core/MapBaseLayers.js +6 -13
- package/dist/core/MapTools.js +4 -7
- package/dist/core/MeasureHandler.js +4 -9
- package/dist/core/Point.d.ts +38 -0
- package/dist/core/Point.js +100 -71
- package/dist/core/Polygon.d.ts +25 -0
- package/dist/core/Polygon.js +94 -34
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/types.d.ts +282 -280
- package/dist/utils/ValidationUtils.d.ts +163 -0
- package/dist/utils/ValidationUtils.js +312 -0
- package/package.json +2 -2
|
@@ -66,31 +66,6 @@ export declare class ConfigManager {
|
|
|
66
66
|
textStrokeColor: string;
|
|
67
67
|
textStrokeWidth: number;
|
|
68
68
|
};
|
|
69
|
-
/**
|
|
70
|
-
* 验证坐标是否有效
|
|
71
|
-
* @param longitude 经度
|
|
72
|
-
* @param latitude 纬度
|
|
73
|
-
* @returns 是否有效
|
|
74
|
-
*/
|
|
75
|
-
static isValidCoordinate(longitude: number, latitude: number): boolean;
|
|
76
|
-
/**
|
|
77
|
-
* 验证颜色字符串是否有效
|
|
78
|
-
* @param color 颜色字符串
|
|
79
|
-
* @returns 是否有效
|
|
80
|
-
*/
|
|
81
|
-
static isValidColor(color: string): boolean;
|
|
82
|
-
/**
|
|
83
|
-
* 验证图层名称是否有效
|
|
84
|
-
* @param layerName 图层名称
|
|
85
|
-
* @returns 是否有效
|
|
86
|
-
*/
|
|
87
|
-
static isValidLayerName(layerName: string): boolean;
|
|
88
|
-
/**
|
|
89
|
-
* 验证范围是否有效
|
|
90
|
-
* @param extent 范围数组 [minX, minY, maxX, maxY]
|
|
91
|
-
* @returns 是否有效
|
|
92
|
-
*/
|
|
93
|
-
static isValidExtent(extent: number[]): boolean;
|
|
94
69
|
/**
|
|
95
70
|
* 合并配置选项
|
|
96
71
|
* @param defaultOptions 默认配置
|
|
@@ -3,58 +3,6 @@
|
|
|
3
3
|
* 用于统一管理默认配置和验证
|
|
4
4
|
*/
|
|
5
5
|
export class ConfigManager {
|
|
6
|
-
/**
|
|
7
|
-
* 验证坐标是否有效
|
|
8
|
-
* @param longitude 经度
|
|
9
|
-
* @param latitude 纬度
|
|
10
|
-
* @returns 是否有效
|
|
11
|
-
*/
|
|
12
|
-
static isValidCoordinate(longitude, latitude) {
|
|
13
|
-
return (typeof longitude === 'number' &&
|
|
14
|
-
typeof latitude === 'number' &&
|
|
15
|
-
!isNaN(longitude) &&
|
|
16
|
-
!isNaN(latitude) &&
|
|
17
|
-
longitude >= -180 &&
|
|
18
|
-
longitude <= 180 &&
|
|
19
|
-
latitude >= -90 &&
|
|
20
|
-
latitude <= 90);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* 验证颜色字符串是否有效
|
|
24
|
-
* @param color 颜色字符串
|
|
25
|
-
* @returns 是否有效
|
|
26
|
-
*/
|
|
27
|
-
static isValidColor(color) {
|
|
28
|
-
if (!color || typeof color !== 'string') {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
// 简单的颜色格式验证
|
|
32
|
-
const colorRegex = /^(#[0-9A-Fa-f]{3,8}|rgba?\([^)]+\)|[a-zA-Z]+)$/;
|
|
33
|
-
return colorRegex.test(color);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* 验证图层名称是否有效
|
|
37
|
-
* @param layerName 图层名称
|
|
38
|
-
* @returns 是否有效
|
|
39
|
-
*/
|
|
40
|
-
static isValidLayerName(layerName) {
|
|
41
|
-
return (typeof layerName === 'string' &&
|
|
42
|
-
layerName.length > 0 &&
|
|
43
|
-
layerName.trim().length > 0);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* 验证范围是否有效
|
|
47
|
-
* @param extent 范围数组 [minX, minY, maxX, maxY]
|
|
48
|
-
* @returns 是否有效
|
|
49
|
-
*/
|
|
50
|
-
static isValidExtent(extent) {
|
|
51
|
-
return (Array.isArray(extent) &&
|
|
52
|
-
extent.length === 4 &&
|
|
53
|
-
extent.every(coord => typeof coord === 'number' && !isNaN(coord)) &&
|
|
54
|
-
extent[0] < extent[2] && // minX < maxX
|
|
55
|
-
extent[1] < extent[3] // minY < maxY
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
6
|
/**
|
|
59
7
|
* 合并配置选项
|
|
60
8
|
* @param defaultOptions 默认配置
|
package/dist/core/DomPoint.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Overlay from 'ol/Overlay';
|
|
2
2
|
import { DomPointState } from '../types';
|
|
3
3
|
import { ErrorHandler, ErrorType } from '../utils/ErrorHandler';
|
|
4
|
+
import { ValidationUtils } from '../utils/ValidationUtils';
|
|
4
5
|
/**
|
|
5
6
|
* DOM点位管理类
|
|
6
7
|
* 用于在地图上添加和管理DOM元素覆盖物
|
|
@@ -50,28 +51,15 @@ export default class DomPoint {
|
|
|
50
51
|
* @private
|
|
51
52
|
*/
|
|
52
53
|
validateConstructorParams(map, options) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
if (!options) {
|
|
57
|
-
throw new Error('Options are required');
|
|
58
|
-
}
|
|
54
|
+
ValidationUtils.validateRequired(map, 'Map instance is required');
|
|
55
|
+
ValidationUtils.validateRequired(options, 'Options are required');
|
|
59
56
|
const { Vue, Template, longitude, latitude } = options;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
57
|
+
ValidationUtils.validateRequired(Vue, 'Vue is required in options');
|
|
58
|
+
ValidationUtils.validateRequired(Template, 'Template is required in options');
|
|
63
59
|
if (typeof longitude !== 'number' || typeof latitude !== 'number') {
|
|
64
60
|
throw new Error('Longitude and latitude must be numbers');
|
|
65
61
|
}
|
|
66
|
-
|
|
67
|
-
throw new Error('Valid longitude and latitude are required');
|
|
68
|
-
}
|
|
69
|
-
if (longitude < -180 || longitude > 180) {
|
|
70
|
-
throw new Error('Longitude must be between -180 and 180');
|
|
71
|
-
}
|
|
72
|
-
if (latitude < -90 || latitude > 90) {
|
|
73
|
-
throw new Error('Latitude must be between -90 and 90');
|
|
74
|
-
}
|
|
62
|
+
ValidationUtils.validateCoordinate(longitude, latitude);
|
|
75
63
|
}
|
|
76
64
|
/**
|
|
77
65
|
* 合并默认配置选项
|
|
@@ -181,9 +169,7 @@ export default class DomPoint {
|
|
|
181
169
|
if (this.state === DomPointState.DESTROYED) {
|
|
182
170
|
throw new Error('Cannot set visibility on destroyed DOM point');
|
|
183
171
|
}
|
|
184
|
-
|
|
185
|
-
throw new Error('Visible parameter must be a boolean');
|
|
186
|
-
}
|
|
172
|
+
ValidationUtils.validateType(visible, 'boolean', 'Visible parameter must be a boolean');
|
|
187
173
|
try {
|
|
188
174
|
this.dom.style.visibility = visible ? 'visible' : 'hidden';
|
|
189
175
|
this.state = visible ? DomPointState.VISIBLE : DomPointState.HIDDEN;
|
|
@@ -210,12 +196,7 @@ export default class DomPoint {
|
|
|
210
196
|
if (this.state === DomPointState.DESTROYED) {
|
|
211
197
|
throw new Error('Cannot update position on destroyed DOM point');
|
|
212
198
|
}
|
|
213
|
-
|
|
214
|
-
throw new Error('Longitude and latitude must be numbers');
|
|
215
|
-
}
|
|
216
|
-
if (isNaN(longitude) || isNaN(latitude)) {
|
|
217
|
-
throw new Error('Valid longitude and latitude are required');
|
|
218
|
-
}
|
|
199
|
+
ValidationUtils.validateCoordinate(longitude, latitude);
|
|
219
200
|
try {
|
|
220
201
|
this.position = [longitude, latitude];
|
|
221
202
|
this.anchor.setPosition(this.position);
|
|
@@ -278,9 +259,7 @@ export default class DomPoint {
|
|
|
278
259
|
if (this.state === DomPointState.DESTROYED) {
|
|
279
260
|
throw new Error('Cannot add class on destroyed DOM point');
|
|
280
261
|
}
|
|
281
|
-
|
|
282
|
-
throw new Error('Valid class name is required');
|
|
283
|
-
}
|
|
262
|
+
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
284
263
|
try {
|
|
285
264
|
this.dom.classList.add(className);
|
|
286
265
|
}
|
|
@@ -298,9 +277,7 @@ export default class DomPoint {
|
|
|
298
277
|
if (this.state === DomPointState.DESTROYED) {
|
|
299
278
|
throw new Error('Cannot remove class on destroyed DOM point');
|
|
300
279
|
}
|
|
301
|
-
|
|
302
|
-
throw new Error('Valid class name is required');
|
|
303
|
-
}
|
|
280
|
+
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
304
281
|
try {
|
|
305
282
|
this.dom.classList.remove(className);
|
|
306
283
|
}
|
package/dist/core/Line.d.ts
CHANGED
|
@@ -1,21 +1,52 @@
|
|
|
1
1
|
import Map from "ol/Map";
|
|
2
2
|
import VectorSource from "ol/source/Vector";
|
|
3
3
|
import VectorLayer from "ol/layer/Vector";
|
|
4
|
-
import { Style } from "ol/style";
|
|
5
4
|
import { LineOptions, MapJSONData } from "../types";
|
|
5
|
+
/**
|
|
6
|
+
* 河流级别宽度映射配置
|
|
7
|
+
*/
|
|
8
|
+
interface RiverLevelWidthMap {
|
|
9
|
+
[level: number]: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 河流图层配置选项
|
|
13
|
+
*/
|
|
14
|
+
interface RiverLayerOptions extends LineOptions {
|
|
15
|
+
/** 河流级别数量,默认为5 */
|
|
16
|
+
levelCount?: number;
|
|
17
|
+
/** 缩放级别偏移量,默认为8 */
|
|
18
|
+
zoomOffset?: number;
|
|
19
|
+
/** 河流级别宽度映射 */
|
|
20
|
+
levelWidthMap?: RiverLevelWidthMap;
|
|
21
|
+
/** 是否删除同名图层 */
|
|
22
|
+
removeExisting?: boolean;
|
|
23
|
+
}
|
|
6
24
|
/**
|
|
7
25
|
* 线要素管理类
|
|
8
|
-
*
|
|
26
|
+
* 用于在地图上添加和管理线要素,包括普通线要素、河流图层等
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const lineManager = new Line(map);
|
|
31
|
+
* const layer = lineManager.addLine(geoJsonData, {
|
|
32
|
+
* type: 'road',
|
|
33
|
+
* strokeColor: '#ff0000',
|
|
34
|
+
* strokeWidth: 3
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
9
37
|
*/
|
|
10
38
|
export default class Line {
|
|
39
|
+
/** OpenLayers 地图实例 */
|
|
11
40
|
private readonly map;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
41
|
+
/** 河流图层列表 */
|
|
42
|
+
private riverLayerList;
|
|
43
|
+
/** 河流图层显示状态 */
|
|
44
|
+
private riverLayerShow;
|
|
45
|
+
/** 默认河流级别宽度映射 */
|
|
46
|
+
private readonly defaultLevelWidthMap;
|
|
15
47
|
/**
|
|
16
48
|
* 构造函数
|
|
17
49
|
* @param map OpenLayers地图实例
|
|
18
|
-
* @throws 当地图实例无效时抛出错误
|
|
19
50
|
*/
|
|
20
51
|
constructor(map: Map);
|
|
21
52
|
/**
|
|
@@ -23,14 +54,54 @@ export default class Line {
|
|
|
23
54
|
* @param data GeoJSON格式的线数据
|
|
24
55
|
* @param options 配置项
|
|
25
56
|
* @returns 创建的矢量图层
|
|
26
|
-
* @throws 当数据格式无效时抛出错误
|
|
27
57
|
*/
|
|
28
|
-
addLine(data: MapJSONData, options
|
|
29
|
-
|
|
58
|
+
addLine(data: MapJSONData, options?: LineOptions): VectorLayer<VectorSource>;
|
|
59
|
+
/**
|
|
60
|
+
* 添加分级河流图层,根据缩放级别显示不同级别的河流
|
|
61
|
+
* @param fyRiverJson 河流 GeoJSON 数据
|
|
62
|
+
* @param options 河流图层配置选项
|
|
63
|
+
* @throws {Error} 当数据格式无效时抛出错误
|
|
64
|
+
*/
|
|
65
|
+
addRiverLayersByZoom(fyRiverJson: MapJSONData, options?: RiverLayerOptions): void;
|
|
66
|
+
/**
|
|
67
|
+
* 显示或隐藏河流图层
|
|
68
|
+
* @param show 是否显示河流图层
|
|
69
|
+
*/
|
|
30
70
|
showRiverLayer(show: boolean): void;
|
|
71
|
+
/**
|
|
72
|
+
* 根据缩放级别显示对应的河流图层
|
|
73
|
+
* 缩放级别越高,显示的河流级别越详细
|
|
74
|
+
*/
|
|
31
75
|
showRiverLayerByZoom(): void;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
76
|
+
/**
|
|
77
|
+
* 添加按级别显示不同宽度的河流图层
|
|
78
|
+
* @param data 河流 GeoJSON 数据
|
|
79
|
+
* @param options 河流图层配置选项
|
|
80
|
+
* @returns 创建的河流图层
|
|
81
|
+
*/
|
|
82
|
+
addRiverWidthByLevel(data: MapJSONData, options?: RiverLayerOptions): VectorLayer<VectorSource>;
|
|
83
|
+
/**
|
|
84
|
+
* 移除线图层
|
|
85
|
+
* @param layerName 图层名称
|
|
86
|
+
*/
|
|
87
|
+
removeLineLayer(layerName: string): void;
|
|
88
|
+
/**
|
|
89
|
+
* 清除所有河流图层
|
|
90
|
+
*/
|
|
91
|
+
clearRiverLayers(): void;
|
|
92
|
+
/**
|
|
93
|
+
* 获取河流图层显示状态
|
|
94
|
+
* @returns 河流图层是否显示
|
|
95
|
+
*/
|
|
96
|
+
getRiverLayerVisibility(): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* 获取河流图层列表
|
|
99
|
+
* @returns 河流图层数组的副本
|
|
100
|
+
*/
|
|
101
|
+
getRiverLayers(): VectorLayer<VectorSource>[];
|
|
102
|
+
/**
|
|
103
|
+
* 销毁线管理器,清理所有资源
|
|
104
|
+
*/
|
|
105
|
+
destroy(): void;
|
|
36
106
|
}
|
|
107
|
+
export {};
|
package/dist/core/Line.js
CHANGED
|
@@ -2,23 +2,42 @@ import VectorSource from "ol/source/Vector";
|
|
|
2
2
|
import GeoJSON from "ol/format/GeoJSON";
|
|
3
3
|
import VectorLayer from "ol/layer/Vector";
|
|
4
4
|
import { Stroke, Style } from "ol/style";
|
|
5
|
+
import { Feature } from "ol";
|
|
5
6
|
import MapTools from "./MapTools";
|
|
7
|
+
import { ValidationUtils } from "../utils/ValidationUtils";
|
|
6
8
|
/**
|
|
7
9
|
* 线要素管理类
|
|
8
|
-
*
|
|
10
|
+
* 用于在地图上添加和管理线要素,包括普通线要素、河流图层等
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const lineManager = new Line(map);
|
|
15
|
+
* const layer = lineManager.addLine(geoJsonData, {
|
|
16
|
+
* type: 'road',
|
|
17
|
+
* strokeColor: '#ff0000',
|
|
18
|
+
* strokeWidth: 3
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
9
21
|
*/
|
|
10
22
|
export default class Line {
|
|
11
23
|
/**
|
|
12
24
|
* 构造函数
|
|
13
25
|
* @param map OpenLayers地图实例
|
|
14
|
-
* @throws 当地图实例无效时抛出错误
|
|
15
26
|
*/
|
|
16
27
|
constructor(map) {
|
|
28
|
+
/** 河流图层列表 */
|
|
17
29
|
this.riverLayerList = [];
|
|
30
|
+
/** 河流图层显示状态 */
|
|
18
31
|
this.riverLayerShow = false;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
/** 默认河流级别宽度映射 */
|
|
33
|
+
this.defaultLevelWidthMap = {
|
|
34
|
+
1: 2,
|
|
35
|
+
2: 1,
|
|
36
|
+
3: 0.5,
|
|
37
|
+
4: 0.5,
|
|
38
|
+
5: 0.5
|
|
39
|
+
};
|
|
40
|
+
ValidationUtils.validateMapInstance(map);
|
|
22
41
|
this.map = map;
|
|
23
42
|
}
|
|
24
43
|
/**
|
|
@@ -26,104 +45,144 @@ export default class Line {
|
|
|
26
45
|
* @param data GeoJSON格式的线数据
|
|
27
46
|
* @param options 配置项
|
|
28
47
|
* @returns 创建的矢量图层
|
|
29
|
-
* @throws 当数据格式无效时抛出错误
|
|
30
48
|
*/
|
|
31
|
-
addLine(data, options) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
throw new Error(`Invalid GeoJSON data: ${error}`);
|
|
44
|
-
}
|
|
45
|
-
if (!features || features.length === 0) {
|
|
46
|
-
console.warn('No features found in line data');
|
|
47
|
-
}
|
|
49
|
+
addLine(data, options = {}) {
|
|
50
|
+
ValidationUtils.validateGeoJSONData(data);
|
|
51
|
+
const defaultOptions = {
|
|
52
|
+
type: 'line',
|
|
53
|
+
strokeColor: 'rgba(3, 122, 255, 1)',
|
|
54
|
+
strokeWidth: 2,
|
|
55
|
+
visible: true,
|
|
56
|
+
zIndex: 15,
|
|
57
|
+
layerName: options.layerName || 'lineLayer'
|
|
58
|
+
};
|
|
59
|
+
const mergedOptions = { ...defaultOptions, ...options };
|
|
60
|
+
const features = new GeoJSON().readFeatures(data, options.projectionOptOptions);
|
|
48
61
|
const layer = new VectorLayer({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}),
|
|
54
|
-
style:
|
|
55
|
-
feature
|
|
56
|
-
|
|
62
|
+
properties: {
|
|
63
|
+
name: mergedOptions.layerName,
|
|
64
|
+
layerName: mergedOptions.layerName
|
|
65
|
+
},
|
|
66
|
+
source: new VectorSource({ features }),
|
|
67
|
+
style: (feature) => {
|
|
68
|
+
if (feature instanceof Feature) {
|
|
69
|
+
feature.set('type', mergedOptions.type);
|
|
70
|
+
feature.set('layerName', mergedOptions.type);
|
|
71
|
+
}
|
|
57
72
|
return new Style({
|
|
58
73
|
stroke: new Stroke({
|
|
59
|
-
color:
|
|
60
|
-
width:
|
|
61
|
-
lineDash:
|
|
62
|
-
lineDashOffset:
|
|
63
|
-
})
|
|
74
|
+
color: mergedOptions.strokeColor,
|
|
75
|
+
width: mergedOptions.strokeWidth,
|
|
76
|
+
lineDash: mergedOptions.lineDash,
|
|
77
|
+
lineDashOffset: mergedOptions.lineDashOffset
|
|
78
|
+
})
|
|
64
79
|
});
|
|
65
80
|
},
|
|
66
|
-
zIndex:
|
|
81
|
+
zIndex: mergedOptions.zIndex
|
|
67
82
|
});
|
|
68
|
-
layer.setVisible(
|
|
69
|
-
this[options.type + 'Layer'] = layer;
|
|
83
|
+
layer.setVisible(mergedOptions.visible);
|
|
70
84
|
this.map.addLayer(layer);
|
|
71
85
|
return layer;
|
|
72
86
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
87
|
+
/**
|
|
88
|
+
* 添加分级河流图层,根据缩放级别显示不同级别的河流
|
|
89
|
+
* @param fyRiverJson 河流 GeoJSON 数据
|
|
90
|
+
* @param options 河流图层配置选项
|
|
91
|
+
* @throws {Error} 当数据格式无效时抛出错误
|
|
92
|
+
*/
|
|
93
|
+
addRiverLayersByZoom(fyRiverJson, options = {}) {
|
|
94
|
+
ValidationUtils.validateGeoJSONData(fyRiverJson);
|
|
95
|
+
const defaultOptions = {
|
|
96
|
+
type: 'river',
|
|
97
|
+
levelCount: 5,
|
|
98
|
+
zoomOffset: 8,
|
|
99
|
+
strokeColor: 'rgb(0,113,255)',
|
|
100
|
+
strokeWidth: 3,
|
|
101
|
+
visible: true,
|
|
102
|
+
zIndex: 15,
|
|
103
|
+
layerName: 'riverLayer',
|
|
104
|
+
removeExisting: options.removeExisting ?? false,
|
|
105
|
+
levelWidthMap: this.defaultLevelWidthMap
|
|
106
|
+
};
|
|
107
|
+
const mergedOptions = { ...defaultOptions, ...options };
|
|
108
|
+
// 清除现有河流图层
|
|
109
|
+
if (mergedOptions.removeExisting) {
|
|
110
|
+
this.clearRiverLayers();
|
|
111
|
+
}
|
|
112
|
+
this.riverLayerShow = mergedOptions.visible;
|
|
76
113
|
this.riverLayerList = [];
|
|
77
|
-
|
|
114
|
+
// 创建分级河流图层
|
|
115
|
+
for (let level = 1; level <= mergedOptions.levelCount; level++) {
|
|
78
116
|
const vectorSource = new VectorSource({
|
|
79
117
|
format: new GeoJSON(),
|
|
80
|
-
loader:
|
|
118
|
+
loader: () => {
|
|
81
119
|
const geojson = new GeoJSON();
|
|
82
120
|
fyRiverJson.features.forEach((feature) => {
|
|
83
|
-
if (feature.properties.level ===
|
|
84
|
-
|
|
85
|
-
|
|
121
|
+
if (feature.properties && feature.properties.level === level) {
|
|
122
|
+
try {
|
|
123
|
+
const olFeature = geojson.readFeature(feature);
|
|
124
|
+
vectorSource.addFeature(olFeature);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
console.warn(`Failed to load river feature at level ${level}:`, error);
|
|
128
|
+
}
|
|
86
129
|
}
|
|
87
130
|
});
|
|
88
|
-
}
|
|
89
|
-
// 其他配置
|
|
131
|
+
}
|
|
90
132
|
});
|
|
91
133
|
const riverLayer = new VectorLayer({
|
|
92
|
-
|
|
93
|
-
|
|
134
|
+
properties: {
|
|
135
|
+
name: mergedOptions.layerName,
|
|
136
|
+
layerName: mergedOptions.layerName,
|
|
137
|
+
riverLevel: level
|
|
138
|
+
},
|
|
94
139
|
source: vectorSource,
|
|
95
|
-
style:
|
|
96
|
-
feature
|
|
97
|
-
|
|
140
|
+
style: (feature) => {
|
|
141
|
+
if (feature instanceof Feature) {
|
|
142
|
+
feature.set('type', mergedOptions.layerName);
|
|
143
|
+
feature.set('layerName', mergedOptions.layerName);
|
|
144
|
+
}
|
|
98
145
|
return new Style({
|
|
99
146
|
stroke: new Stroke({
|
|
100
|
-
color:
|
|
101
|
-
width:
|
|
147
|
+
color: mergedOptions.strokeColor,
|
|
148
|
+
width: mergedOptions.strokeWidth
|
|
102
149
|
})
|
|
103
150
|
});
|
|
104
151
|
},
|
|
105
|
-
zIndex:
|
|
152
|
+
zIndex: mergedOptions.zIndex
|
|
106
153
|
});
|
|
107
154
|
riverLayer.setVisible(false);
|
|
108
155
|
this.riverLayerList.push(riverLayer);
|
|
109
156
|
this.map.addLayer(riverLayer);
|
|
110
157
|
}
|
|
111
|
-
|
|
158
|
+
// 设置缩放事件监听
|
|
112
159
|
MapTools.mapOnEvent(this.map, 'moveend', () => {
|
|
113
160
|
this.showRiverLayerByZoom();
|
|
114
161
|
});
|
|
162
|
+
// 初始显示
|
|
163
|
+
this.showRiverLayerByZoom();
|
|
115
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* 显示或隐藏河流图层
|
|
167
|
+
* @param show 是否显示河流图层
|
|
168
|
+
*/
|
|
116
169
|
showRiverLayer(show) {
|
|
117
170
|
this.riverLayerShow = show;
|
|
118
|
-
this.riverNamePointLayer.setVisible(show);
|
|
119
171
|
this.showRiverLayerByZoom();
|
|
120
172
|
}
|
|
121
|
-
|
|
173
|
+
/**
|
|
174
|
+
* 根据缩放级别显示对应的河流图层
|
|
175
|
+
* 缩放级别越高,显示的河流级别越详细
|
|
176
|
+
*/
|
|
122
177
|
showRiverLayerByZoom() {
|
|
123
178
|
const zoom = this.map.getView().getZoom();
|
|
179
|
+
if (!zoom) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
124
182
|
this.riverLayerList.forEach((layer, index) => {
|
|
125
|
-
//
|
|
126
|
-
|
|
183
|
+
// 计算显示阈值:级别索引 + 1(因为level从1开始)+ 缩放偏移量(默认8)
|
|
184
|
+
const displayThreshold = index + 1 + 8;
|
|
185
|
+
if (zoom > displayThreshold) {
|
|
127
186
|
layer.setVisible(this.riverLayerShow);
|
|
128
187
|
}
|
|
129
188
|
else {
|
|
@@ -131,27 +190,92 @@ export default class Line {
|
|
|
131
190
|
}
|
|
132
191
|
});
|
|
133
192
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
193
|
+
/**
|
|
194
|
+
* 添加按级别显示不同宽度的河流图层
|
|
195
|
+
* @param data 河流 GeoJSON 数据
|
|
196
|
+
* @param options 河流图层配置选项
|
|
197
|
+
* @returns 创建的河流图层
|
|
198
|
+
*/
|
|
199
|
+
addRiverWidthByLevel(data, options = {}) {
|
|
200
|
+
ValidationUtils.validateGeoJSONData(data);
|
|
201
|
+
// 合并默认配置
|
|
202
|
+
const mergedOptions = {
|
|
203
|
+
type: 'river',
|
|
138
204
|
layerName: 'river',
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
205
|
+
strokeColor: 'rgba(3, 122, 255, 1)',
|
|
206
|
+
strokeWidth: 2,
|
|
207
|
+
visible: true,
|
|
208
|
+
zIndex: 15,
|
|
209
|
+
levelWidthMap: this.defaultLevelWidthMap,
|
|
210
|
+
removeExisting: options.removeExisting ?? false,
|
|
211
|
+
...options
|
|
212
|
+
};
|
|
213
|
+
// 移除同名图层(如果存在)
|
|
214
|
+
if (mergedOptions.removeExisting && mergedOptions.layerName) {
|
|
215
|
+
MapTools.removeLayer(this.map, mergedOptions.layerName);
|
|
216
|
+
}
|
|
217
|
+
// 解析 GeoJSON 数据
|
|
218
|
+
const features = new GeoJSON().readFeatures(data, options.projectionOptOptions);
|
|
219
|
+
// 创建河流图层
|
|
220
|
+
const riverLayer = new VectorLayer({
|
|
221
|
+
properties: {
|
|
222
|
+
name: mergedOptions.layerName,
|
|
223
|
+
layerName: mergedOptions.layerName
|
|
224
|
+
},
|
|
225
|
+
source: new VectorSource({ features }),
|
|
226
|
+
style: (feature) => {
|
|
227
|
+
const level = feature.get('level');
|
|
228
|
+
const levelWidth = mergedOptions.levelWidthMap[Number(level)] || 1;
|
|
229
|
+
return new Style({
|
|
230
|
+
stroke: new Stroke({
|
|
231
|
+
color: mergedOptions.strokeColor,
|
|
232
|
+
width: levelWidth
|
|
233
|
+
})
|
|
234
|
+
});
|
|
235
|
+
},
|
|
236
|
+
zIndex: mergedOptions.zIndex
|
|
144
237
|
});
|
|
238
|
+
riverLayer.setVisible(mergedOptions.visible);
|
|
145
239
|
this.map.addLayer(riverLayer);
|
|
240
|
+
return riverLayer;
|
|
146
241
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
242
|
+
/**
|
|
243
|
+
* 移除线图层
|
|
244
|
+
* @param layerName 图层名称
|
|
245
|
+
*/
|
|
246
|
+
removeLineLayer(layerName) {
|
|
247
|
+
ValidationUtils.validateLayerName(layerName);
|
|
248
|
+
MapTools.removeLayer(this.map, layerName);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* 清除所有河流图层
|
|
252
|
+
*/
|
|
253
|
+
clearRiverLayers() {
|
|
254
|
+
this.riverLayerList.forEach(layer => {
|
|
255
|
+
this.map.removeLayer(layer);
|
|
155
256
|
});
|
|
257
|
+
this.riverLayerList = [];
|
|
258
|
+
this.riverLayerShow = false;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* 获取河流图层显示状态
|
|
262
|
+
* @returns 河流图层是否显示
|
|
263
|
+
*/
|
|
264
|
+
getRiverLayerVisibility() {
|
|
265
|
+
return this.riverLayerShow;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* 获取河流图层列表
|
|
269
|
+
* @returns 河流图层数组的副本
|
|
270
|
+
*/
|
|
271
|
+
getRiverLayers() {
|
|
272
|
+
return [...this.riverLayerList];
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* 销毁线管理器,清理所有资源
|
|
276
|
+
*/
|
|
277
|
+
destroy() {
|
|
278
|
+
// 清除所有河流图层
|
|
279
|
+
this.clearRiverLayers();
|
|
156
280
|
}
|
|
157
281
|
}
|