my-openlayer 2.5.5 → 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 +10 -108
- package/README.md +116 -29
- package/core/line/Line.d.ts +19 -5
- package/core/line/Line.js +25 -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 +16 -0
- package/core/map/MapTools.js +35 -1
- package/core/point/Point.d.ts +40 -14
- package/core/point/Point.js +70 -4
- 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 +19 -16
- package/core/polygon/Polygon.js +41 -63
- 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 +4 -2
- package/index.js +2 -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
|
@@ -3,6 +3,7 @@ import { Point } from "ol/geom";
|
|
|
3
3
|
import { Heatmap } from "ol/layer";
|
|
4
4
|
import VectorSource from "ol/source/Vector";
|
|
5
5
|
import { ConfigManager, MapTools } from "../map";
|
|
6
|
+
import { ErrorHandler } from "../../utils/ErrorHandler";
|
|
6
7
|
/**
|
|
7
8
|
* 面热力图辅助类。
|
|
8
9
|
*/
|
|
@@ -28,11 +29,23 @@ export default class PolygonHeatmapLayer {
|
|
|
28
29
|
}
|
|
29
30
|
map.addLayer(heatmapLayer);
|
|
30
31
|
const valueKey = mergedOptions.valueKey || ConfigManager.DEFAULT_HEATMAP_VALUE_KEY;
|
|
31
|
-
|
|
32
|
+
// 计算归一化最大值。当数据里没有 valueKey 或值全为非数字时,max 是 NaN/-Infinity,
|
|
33
|
+
// 会导致 weight = value/max = NaN,OL 热力图整层不渲染。
|
|
34
|
+
// 此时回退到等权重 1(让用户至少看到热力图,再去补 valueKey)。
|
|
35
|
+
const numericValues = pointData
|
|
36
|
+
.map(item => Number(item[valueKey]))
|
|
37
|
+
.filter(v => Number.isFinite(v));
|
|
38
|
+
const max = numericValues.length > 0 ? Math.max(...numericValues) : 0;
|
|
39
|
+
const useFallbackWeight = max <= 0;
|
|
40
|
+
if (useFallbackWeight) {
|
|
41
|
+
ErrorHandler.getInstance().warn(`[Heatmap] 数据中未找到有效的 "${valueKey}" 字段,已回退为等权重渲染。请通过 options.valueKey 指定正确字段。`);
|
|
42
|
+
}
|
|
32
43
|
pointData.forEach(item => {
|
|
44
|
+
const raw = Number(item[valueKey]);
|
|
45
|
+
const weight = useFallbackWeight || !Number.isFinite(raw) ? 1 : raw / max;
|
|
33
46
|
heatmapLayer.getSource().addFeature(new Feature({
|
|
34
47
|
geometry: new Point([item.lgtd, item.lttd]),
|
|
35
|
-
weight
|
|
48
|
+
weight
|
|
36
49
|
}));
|
|
37
50
|
});
|
|
38
51
|
return heatmapLayer;
|
|
@@ -10,11 +10,11 @@ import type { MapJSONData, MaskLayerOptions } from "../../types";
|
|
|
10
10
|
export default class PolygonMaskLayer {
|
|
11
11
|
static setOutLayer(map: Map, data: MapJSONData, options?: {
|
|
12
12
|
layerName?: string;
|
|
13
|
-
extent?:
|
|
13
|
+
extent?: number[];
|
|
14
14
|
fillColor?: string;
|
|
15
15
|
strokeWidth?: number;
|
|
16
16
|
strokeColor?: string;
|
|
17
17
|
zIndex?: number;
|
|
18
18
|
}): VectorLayer<VectorSource<Feature<Geometry>>, Feature<Geometry>>;
|
|
19
|
-
static addMaskLayer(map: Map, data:
|
|
19
|
+
static addMaskLayer(map: Map, data: MapJSONData, options?: MaskLayerOptions): VectorLayer<VectorSource>;
|
|
20
20
|
}
|
|
@@ -98,7 +98,9 @@ export default class PolygonMaskLayer {
|
|
|
98
98
|
}) : undefined
|
|
99
99
|
}),
|
|
100
100
|
opacity: mergedOptions.opacity,
|
|
101
|
-
visible: mergedOptions.visible
|
|
101
|
+
visible: mergedOptions.visible,
|
|
102
|
+
// 显式传 zIndex,否则被天地图底图(zIndex 9)盖住,用户看不到 mask
|
|
103
|
+
zIndex: mergedOptions.zIndex
|
|
102
104
|
});
|
|
103
105
|
maskLayer.set('layerName', mergedOptions.layerName);
|
|
104
106
|
map.addLayer(maskLayer);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import Feature from "ol/Feature";
|
|
1
|
+
import Feature, { type FeatureLike } from "ol/Feature";
|
|
2
|
+
import { Style } from "ol/style";
|
|
2
3
|
import type { FeatureColorUpdateOptions, PolygonOptions } from "../../types";
|
|
3
4
|
/**
|
|
4
5
|
* 面图层样式工厂。
|
|
5
6
|
*/
|
|
6
7
|
export default class PolygonStyleFactory {
|
|
7
|
-
static getFeatureText(feature:
|
|
8
|
-
static createStyle(options: PolygonOptions):
|
|
8
|
+
static getFeatureText(feature: FeatureLike, options: PolygonOptions | FeatureColorUpdateOptions): string;
|
|
9
|
+
static createStyle(options: PolygonOptions): Style | Style[] | ((feature: FeatureLike) => Style | Style[]);
|
|
9
10
|
static updateSingleFeatureColor(feature: Feature, colorObj?: {
|
|
10
11
|
[propName: string]: string;
|
|
11
12
|
}, options?: FeatureColorUpdateOptions): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Projection as olProjProjection } from "ol/proj";
|
|
2
|
+
import type { Units } from "ol/proj/Units";
|
|
3
|
+
import type { MapInitType } from "../../types";
|
|
4
|
+
/**
|
|
5
|
+
* 项目内置 EPSG 编码。
|
|
6
|
+
*/
|
|
7
|
+
export declare const PROJECTIONS: {
|
|
8
|
+
readonly WGS84: "EPSG:4326";
|
|
9
|
+
readonly CGCS2000: "EPSG:4490";
|
|
10
|
+
readonly CGCS2000_3_DEGREE: "EPSG:4549";
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* 自定义投影注册元数据。
|
|
14
|
+
*/
|
|
15
|
+
export interface CustomProjectionRegistration {
|
|
16
|
+
/** EPSG 编码,例如 "EPSG:4528" */
|
|
17
|
+
code: string;
|
|
18
|
+
/** proj4 定义字符串 */
|
|
19
|
+
def: string;
|
|
20
|
+
/** 投影范围 [minX, minY, maxX, maxY] */
|
|
21
|
+
extent?: number[];
|
|
22
|
+
/** 世界范围 [minX, minY, maxX, maxY] */
|
|
23
|
+
worldExtent?: number[];
|
|
24
|
+
/** OL 投影单位(degrees / m / ft 等),未提供时从 proj4 定义自动推导 */
|
|
25
|
+
units?: Units;
|
|
26
|
+
}
|
|
27
|
+
export default class ProjectionManager {
|
|
28
|
+
/** 项目内置 EPSG 编码常量。 */
|
|
29
|
+
static readonly PROJECTIONS: {
|
|
30
|
+
readonly WGS84: "EPSG:4326";
|
|
31
|
+
readonly CGCS2000: "EPSG:4490";
|
|
32
|
+
readonly CGCS2000_3_DEGREE: "EPSG:4549";
|
|
33
|
+
};
|
|
34
|
+
/** 默认投影 = EPSG:4490 (CGCS2000)。 */
|
|
35
|
+
static readonly DEFAULT_PROJECTION: "EPSG:4490";
|
|
36
|
+
/**
|
|
37
|
+
* 注册内置投影 + 应用 options.projection 自定义投影。
|
|
38
|
+
*
|
|
39
|
+
* 幂等:重复调用安全。被 MyOl 构造函数和 MyOl.createView 都会调,外部一般无需直接调用。
|
|
40
|
+
*/
|
|
41
|
+
static initialize(options?: MapInitType): void;
|
|
42
|
+
/**
|
|
43
|
+
* 注册一个任意 EPSG 投影到 proj4 + OL。
|
|
44
|
+
*
|
|
45
|
+
* 这是 MyOl 之外的便利入口。units 未提供时由 proj4 自动推导。
|
|
46
|
+
*/
|
|
47
|
+
static register(registration: CustomProjectionRegistration): void;
|
|
48
|
+
/**
|
|
49
|
+
* 解析视图投影,优先复用已注册投影,避免丢失 proj4 推导的单位信息。
|
|
50
|
+
*
|
|
51
|
+
* 仅当 options 显式覆盖 extent / worldExtent / units 之一时才新建 Projection 实例。
|
|
52
|
+
*/
|
|
53
|
+
static resolveViewProjection(options: MapInitType, code: string): olProjProjection;
|
|
54
|
+
/**
|
|
55
|
+
* 缺失时注册 proj4 投影定义,避免生产构建依赖第三方模块默认副作用。
|
|
56
|
+
*/
|
|
57
|
+
private static ensureProj4Definition;
|
|
58
|
+
/**
|
|
59
|
+
* 应用用户显式提供的投影元数据。
|
|
60
|
+
*
|
|
61
|
+
* - 提供 units:以用户输入为权威,覆盖已注册投影
|
|
62
|
+
* - 未提供 units 但已注册:仅刷新 extent / worldExtent
|
|
63
|
+
* - 未提供 units 且未注册:新建 Projection(OL 会从 proj4 推导单位)
|
|
64
|
+
*/
|
|
65
|
+
private static applyCustomProjectionMetadata;
|
|
66
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 投影管理器
|
|
3
|
+
*
|
|
4
|
+
* 集中管理所有投影注册与解析逻辑,对外暴露内置常量(EPSG:4326 / 4490 / 4549)以及
|
|
5
|
+
* 自定义投影注册入口。MyOl 内部委托此类初始化投影,使用户也可以在 MyOl 实例之外
|
|
6
|
+
* 主动注册新的 EPSG。
|
|
7
|
+
*/
|
|
8
|
+
import proj4 from "proj4";
|
|
9
|
+
import { register as olProj4Register } from "ol/proj/proj4";
|
|
10
|
+
import { Projection as olProjProjection, addProjection as olProjAddProjection, get as olProjGetProjection } from "ol/proj";
|
|
11
|
+
/**
|
|
12
|
+
* 项目内置 EPSG 编码。
|
|
13
|
+
*/
|
|
14
|
+
export const PROJECTIONS = {
|
|
15
|
+
WGS84: "EPSG:4326",
|
|
16
|
+
CGCS2000: "EPSG:4490",
|
|
17
|
+
CGCS2000_3_DEGREE: "EPSG:4549"
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* 内置 EPSG 的 proj4 定义字符串。
|
|
21
|
+
*/
|
|
22
|
+
const PROJECTION_DEFINITIONS = {
|
|
23
|
+
[PROJECTIONS.WGS84]: "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
|
|
24
|
+
[PROJECTIONS.CGCS2000]: "+proj=longlat +ellps=GRS80 +no_defs",
|
|
25
|
+
[PROJECTIONS.CGCS2000_3_DEGREE]: "+proj=tmerc +lat_0=0 +lon_0=120 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs"
|
|
26
|
+
};
|
|
27
|
+
class ProjectionManager {
|
|
28
|
+
/**
|
|
29
|
+
* 注册内置投影 + 应用 options.projection 自定义投影。
|
|
30
|
+
*
|
|
31
|
+
* 幂等:重复调用安全。被 MyOl 构造函数和 MyOl.createView 都会调,外部一般无需直接调用。
|
|
32
|
+
*/
|
|
33
|
+
static initialize(options) {
|
|
34
|
+
ProjectionManager.ensureProj4Definition(PROJECTIONS.WGS84, PROJECTION_DEFINITIONS[PROJECTIONS.WGS84]);
|
|
35
|
+
ProjectionManager.ensureProj4Definition(PROJECTIONS.CGCS2000, PROJECTION_DEFINITIONS[PROJECTIONS.CGCS2000]);
|
|
36
|
+
ProjectionManager.ensureProj4Definition(PROJECTIONS.CGCS2000_3_DEGREE, PROJECTION_DEFINITIONS[PROJECTIONS.CGCS2000_3_DEGREE]);
|
|
37
|
+
// 用户自定义投影的 proj4 定义优先注入
|
|
38
|
+
if (options?.projection?.code && options.projection.def) {
|
|
39
|
+
proj4.defs(options.projection.code, options.projection.def);
|
|
40
|
+
}
|
|
41
|
+
// 注入 proj4 → OpenLayers
|
|
42
|
+
olProj4Register(proj4);
|
|
43
|
+
// 注册 CGCS2000 OL Projection(带 degrees 单位)
|
|
44
|
+
olProjAddProjection(new olProjProjection({
|
|
45
|
+
code: PROJECTIONS.CGCS2000,
|
|
46
|
+
extent: [-180, -90, 180, 90],
|
|
47
|
+
worldExtent: [-180, -90, 180, 90],
|
|
48
|
+
units: "degrees"
|
|
49
|
+
}));
|
|
50
|
+
if (options?.projection?.code) {
|
|
51
|
+
ProjectionManager.applyCustomProjectionMetadata(options.projection);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 注册一个任意 EPSG 投影到 proj4 + OL。
|
|
56
|
+
*
|
|
57
|
+
* 这是 MyOl 之外的便利入口。units 未提供时由 proj4 自动推导。
|
|
58
|
+
*/
|
|
59
|
+
static register(registration) {
|
|
60
|
+
const { code, def, extent, worldExtent, units } = registration;
|
|
61
|
+
ProjectionManager.ensureProj4Definition(code, def);
|
|
62
|
+
olProj4Register(proj4);
|
|
63
|
+
ProjectionManager.applyCustomProjectionMetadata({
|
|
64
|
+
code,
|
|
65
|
+
def,
|
|
66
|
+
extent,
|
|
67
|
+
worldExtent,
|
|
68
|
+
units
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 解析视图投影,优先复用已注册投影,避免丢失 proj4 推导的单位信息。
|
|
73
|
+
*
|
|
74
|
+
* 仅当 options 显式覆盖 extent / worldExtent / units 之一时才新建 Projection 实例。
|
|
75
|
+
*/
|
|
76
|
+
static resolveViewProjection(options, code) {
|
|
77
|
+
const registeredProjection = olProjGetProjection(code);
|
|
78
|
+
if (registeredProjection
|
|
79
|
+
&& !options.projection?.extent
|
|
80
|
+
&& !options.projection?.worldExtent
|
|
81
|
+
&& !options.projection?.units) {
|
|
82
|
+
return registeredProjection;
|
|
83
|
+
}
|
|
84
|
+
return new olProjProjection({
|
|
85
|
+
code,
|
|
86
|
+
extent: options.projection?.extent
|
|
87
|
+
?? registeredProjection?.getExtent()
|
|
88
|
+
?? [-180, -90, 180, 90],
|
|
89
|
+
worldExtent: options.projection?.worldExtent
|
|
90
|
+
?? registeredProjection?.getWorldExtent()
|
|
91
|
+
?? [-180, -90, 180, 90],
|
|
92
|
+
units: options.projection?.units
|
|
93
|
+
?? registeredProjection?.getUnits()
|
|
94
|
+
?? "degrees"
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 缺失时注册 proj4 投影定义,避免生产构建依赖第三方模块默认副作用。
|
|
99
|
+
*/
|
|
100
|
+
static ensureProj4Definition(code, definition) {
|
|
101
|
+
if (!proj4.defs(code)) {
|
|
102
|
+
proj4.defs(code, definition);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 应用用户显式提供的投影元数据。
|
|
107
|
+
*
|
|
108
|
+
* - 提供 units:以用户输入为权威,覆盖已注册投影
|
|
109
|
+
* - 未提供 units 但已注册:仅刷新 extent / worldExtent
|
|
110
|
+
* - 未提供 units 且未注册:新建 Projection(OL 会从 proj4 推导单位)
|
|
111
|
+
*/
|
|
112
|
+
static applyCustomProjectionMetadata(projection) {
|
|
113
|
+
const { code, extent, worldExtent, units } = projection;
|
|
114
|
+
const registeredProjection = olProjGetProjection(code);
|
|
115
|
+
if (units) {
|
|
116
|
+
olProjAddProjection(new olProjProjection({
|
|
117
|
+
code,
|
|
118
|
+
extent: extent ?? registeredProjection?.getExtent(),
|
|
119
|
+
worldExtent: worldExtent ?? registeredProjection?.getWorldExtent(),
|
|
120
|
+
units
|
|
121
|
+
}));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (registeredProjection) {
|
|
125
|
+
if (extent)
|
|
126
|
+
registeredProjection.setExtent(extent);
|
|
127
|
+
if (worldExtent)
|
|
128
|
+
registeredProjection.setWorldExtent(worldExtent);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (extent || worldExtent) {
|
|
132
|
+
olProjAddProjection(new olProjProjection({
|
|
133
|
+
code,
|
|
134
|
+
extent,
|
|
135
|
+
worldExtent
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** 项目内置 EPSG 编码常量。 */
|
|
141
|
+
ProjectionManager.PROJECTIONS = PROJECTIONS;
|
|
142
|
+
/** 默认投影 = EPSG:4490 (CGCS2000)。 */
|
|
143
|
+
ProjectionManager.DEFAULT_PROJECTION = PROJECTIONS.CGCS2000;
|
|
144
|
+
export default ProjectionManager;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as ProjectionManager, PROJECTIONS } from './ProjectionManager';
|
|
@@ -64,7 +64,7 @@ export default class SelectHandler {
|
|
|
64
64
|
/**
|
|
65
65
|
* 通过属性选择要素
|
|
66
66
|
*/
|
|
67
|
-
selectByProperty(propertyName: string, propertyValue:
|
|
67
|
+
selectByProperty(propertyName: string, propertyValue: unknown, options?: ProgrammaticSelectOptions): this;
|
|
68
68
|
/**
|
|
69
69
|
* 应用选择(编程式)
|
|
70
70
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Map as OLMap } from 'ol';
|
|
2
|
-
import { VueTemplatePointInstance } from '../../types';
|
|
2
|
+
import { ControlHandle, VueTemplatePointInstance } from '../../types';
|
|
3
3
|
/**
|
|
4
4
|
* Vue模板点位管理类
|
|
5
5
|
* 用于在地图上添加和管理Vue组件覆盖物
|
|
@@ -23,10 +23,8 @@ export default class VueTemplatePoint {
|
|
|
23
23
|
addVueTemplatePoint(pointDataList: any[], template: any, options?: {
|
|
24
24
|
positioning?: 'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right';
|
|
25
25
|
stopEvent?: boolean;
|
|
26
|
-
}): {
|
|
27
|
-
setVisible: (visible: boolean) => void;
|
|
26
|
+
}): ControlHandle<VueTemplatePointInstance[]> & {
|
|
28
27
|
setOneVisibleByProp: (propName: string, propValue: any, visible: boolean) => void;
|
|
29
|
-
remove: () => void;
|
|
30
28
|
getPoints: () => VueTemplatePointInstance[];
|
|
31
29
|
};
|
|
32
30
|
/**
|
|
@@ -113,6 +113,7 @@ export default class VueTemplatePoint {
|
|
|
113
113
|
this.vuePoints.set(instance.id, instance);
|
|
114
114
|
});
|
|
115
115
|
return {
|
|
116
|
+
target: instances,
|
|
116
117
|
setVisible: (visible) => {
|
|
117
118
|
instances.forEach((instance) => {
|
|
118
119
|
instance.setVisible(visible);
|
|
@@ -378,9 +379,22 @@ class VueTemplatePointInstanceImpl {
|
|
|
378
379
|
throw new Error('Cannot update props on destroyed DOM point');
|
|
379
380
|
}
|
|
380
381
|
try {
|
|
381
|
-
// 重新创建Vue
|
|
382
|
+
// 重新创建Vue应用实例。
|
|
383
|
+
// 注意:createVueApp 把 options.props 当 Vue 组件的 props 声明(非传值),
|
|
384
|
+
// 根组件没有父组件传值,因此必须把每个值包成 { default: value } 才能被
|
|
385
|
+
// Vue 当 prop 默认值消费,render 里才能读到。
|
|
382
386
|
this.destroyVueApp();
|
|
383
|
-
|
|
387
|
+
const normalized = { ...this.options.props };
|
|
388
|
+
for (const key of Object.keys(newProps)) {
|
|
389
|
+
const value = newProps[key];
|
|
390
|
+
// 已经是 { type, default } 形式则原样合并,否则包装为默认值
|
|
391
|
+
const isAlreadyDeclaration = value !== null
|
|
392
|
+
&& typeof value === 'object'
|
|
393
|
+
&& (Object.prototype.hasOwnProperty.call(value, 'default')
|
|
394
|
+
|| Object.prototype.hasOwnProperty.call(value, 'type'));
|
|
395
|
+
normalized[key] = isAlreadyDeclaration ? value : { default: value };
|
|
396
|
+
}
|
|
397
|
+
this.options.props = normalized;
|
|
384
398
|
this.createVueApp();
|
|
385
399
|
}
|
|
386
400
|
catch (error) {
|
package/docs/Line.md
CHANGED
|
@@ -65,18 +65,18 @@ interface FlowLineLayerHandle {
|
|
|
65
65
|
### addLine
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
|
-
addLine(data: MapJSONData, options
|
|
68
|
+
addLine(data: MapJSONData, options: LineOptions & { layerName: string }): LayerHandle<VectorLayer<VectorSource>>
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
添加静态线图层,返回统一 `LayerHandle`。
|
|
72
72
|
|
|
73
73
|
### addLineByUrl
|
|
74
74
|
|
|
75
75
|
```typescript
|
|
76
|
-
addLineByUrl(url: string, options
|
|
76
|
+
addLineByUrl(url: string, options: LineOptions & { layerName: string }): Promise<LayerHandle<VectorLayer<VectorSource>>>
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
从 URL
|
|
79
|
+
从 URL 加载 GeoJSON 后添加静态线图层,await 后返回完整 `LayerHandle`。
|
|
80
80
|
|
|
81
81
|
### removeLineLayer
|
|
82
82
|
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# my-openlayer 3.0 迁移指南
|
|
2
|
+
|
|
3
|
+
3.0 完成了一次系统性的 API 改造。图层类 `add*` 返回值会从原始 OpenLayers layer 改成统一 Handle;迁移后可以用同一套 `remove()` / `setVisible()` 管理生命周期。本指南分三段:
|
|
4
|
+
|
|
5
|
+
1. **必须改的**(编译错误)
|
|
6
|
+
2. **推荐改的**(用新 API 写新代码)
|
|
7
|
+
3. **保留旧 API 的期限**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. 必须改的(编译错误)
|
|
12
|
+
|
|
13
|
+
### 1.1 `layerName` 在公开 `add*` 签名上变成必填
|
|
14
|
+
|
|
15
|
+
所有 `Point.addPoint / addClusterPoint / addPulsePointLayer`、`Line.addLine / addLineByUrl / addFlowLine / addFlowLineByUrl`、`Polygon.addPolygon / addPolygonByUrl` 现在要求 `options.layerName` 是 `string`(不再可选)。
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// ❌ 2.x:layerName 可选,遗忘时取 ConfigManager 默认值 'lineLayer'
|
|
19
|
+
line.addLine(data)
|
|
20
|
+
line.addLine(data, { strokeColor: 'red' })
|
|
21
|
+
|
|
22
|
+
// ✅ 3.0:必须传 layerName
|
|
23
|
+
line.addLine(data, { layerName: 'my-line' })
|
|
24
|
+
line.addLine(data, { layerName: 'my-line', strokeColor: 'red' })
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> **为什么**:依赖默认 `layerName` 的两次调用会互相覆盖,是 2.x 最常见的"图层莫名消失"陷阱。
|
|
28
|
+
|
|
29
|
+
`PointOptions / LineOptions / PolygonOptions` interface **本身**没改(`layerName?: string` 仍然可选),所以已有的工厂函数、配置对象不受影响 —— 只是公开方法签名收紧了。
|
|
30
|
+
|
|
31
|
+
### 1.2 `add*` 返回值改为 Handle
|
|
32
|
+
|
|
33
|
+
真实图层类 `add*` 不再直接返回 OpenLayers layer,而是返回统一 `LayerHandle`。
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// ❌ 2.x
|
|
37
|
+
const layer = line.addLine(data, { layerName: 'l1' })
|
|
38
|
+
layer.getSource()
|
|
39
|
+
layer.setVisible(false)
|
|
40
|
+
|
|
41
|
+
// ✅ 3.0
|
|
42
|
+
const handle = line.addLine(data, { layerName: 'l1' })
|
|
43
|
+
handle.layer.getSource()
|
|
44
|
+
handle.setVisible(false)
|
|
45
|
+
handle.remove()
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`addDomPoint` / `addVueTemplatePoint` 不是 OL 图层,3.0 返回 `ControlHandle`:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
const domHandle = point.addDomPoint(points)
|
|
52
|
+
domHandle.target // Overlay[]
|
|
53
|
+
domHandle.anchors // 兼容原字段
|
|
54
|
+
|
|
55
|
+
const vueHandle = point.addVueTemplatePoint(points, Component)
|
|
56
|
+
vueHandle.target // VueTemplatePointInstance[]
|
|
57
|
+
vueHandle.getPoints() // 兼容原方法
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 2. 推荐改的(用新 API 写新代码)
|
|
63
|
+
|
|
64
|
+
### 2.1 用 `add*` 拿统一句柄
|
|
65
|
+
|
|
66
|
+
新代码统一用 `add*` 系列:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import type { LayerHandle } from 'my-openlayer'
|
|
70
|
+
|
|
71
|
+
// 跨 Point / Line / Polygon 一致的形态
|
|
72
|
+
const pointHandle: LayerHandle | null = myOl.getPoint().addPoint(data, { layerName: 'p1' })
|
|
73
|
+
const lineHandle: LayerHandle = myOl.getLine().addLine(data, { layerName: 'l1' })
|
|
74
|
+
const polyHandle: LayerHandle = myOl.getPolygon().addPolygon(data, { layerName: 'r1' })
|
|
75
|
+
|
|
76
|
+
// 统一生命周期
|
|
77
|
+
pointHandle?.setVisible(false)
|
|
78
|
+
pointHandle?.remove()
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
动画句柄(`PulsePointLayerHandle` / `FlowLineLayerHandle`)现在显式继承 `AnimatedLayerHandle`:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import type { AnimatedLayerHandle } from 'my-openlayer'
|
|
85
|
+
|
|
86
|
+
const flowHandle: AnimatedLayerHandle | null = myOl.getLine().addFlowLine(data, { layerName: 'flow' })
|
|
87
|
+
flowHandle?.start()
|
|
88
|
+
flowHandle?.pause?.()
|
|
89
|
+
flowHandle?.remove()
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 2.2 `*ByUrl` 统一异步返回 Handle
|
|
93
|
+
|
|
94
|
+
旧的 `Line.addLineByUrl` / `Polygon.addPolygonByUrl` 同步返回 layer,但 features 仍在异步加载,导致 `fitView` 经常失败、`getFeatures().length === 0`。3.0 改为先 `fetch` JSON,再调用对应 add 方法:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// ❌ 2.x:返回 layer 时 features 还在路上
|
|
98
|
+
const layer = polygon.addPolygonByUrl('/boundary.geojson', { layerName: 'b' })
|
|
99
|
+
// layer.getSource().getFeatures().length === 0 ← 经常踩坑
|
|
100
|
+
|
|
101
|
+
// ✅ 3.0:await 后拿到完整 LayerHandle
|
|
102
|
+
const handle = await polygon.addPolygonByUrl('/boundary.geojson', { layerName: 'b' })
|
|
103
|
+
console.log(handle.layer.getSource()?.getFeatures().length) // 准确
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2.3 Point 新增 `*ByUrl` Promise API
|
|
107
|
+
|
|
108
|
+
之前 `Point` 没有任何 `*ByUrl` 方法,必须自己 `fetch + addPoint`。3.0 补齐:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
// 从 URL 加载点位(自动识别 PointData[] 数组或 GeoJSON FeatureCollection)
|
|
112
|
+
const handle = await myOl.getPoint().addPointByUrl('/points.json', { layerName: 'p1' })
|
|
113
|
+
|
|
114
|
+
const handle = await myOl.getPoint().addPulsePointLayerByUrl('/villages.json', {
|
|
115
|
+
layerName: 'villages',
|
|
116
|
+
pulse: { enabled: true, frameCount: 24 }
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 2.4 投影注册抽到 `ProjectionManager`
|
|
121
|
+
|
|
122
|
+
2.x 用 `options.projection` 注册自定义投影。3.0 仍然支持,**外加**一个独立入口:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { ProjectionManager } from 'my-openlayer'
|
|
126
|
+
|
|
127
|
+
// 应用启动时一次性注册自定义 EPSG
|
|
128
|
+
ProjectionManager.register({
|
|
129
|
+
code: 'EPSG:2380',
|
|
130
|
+
def: '+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=500000 +y_0=0 +ellps=WGS84 +units=m +no_defs'
|
|
131
|
+
// units 省略时由 proj4 自动推导
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// 之后任何 new MyOl({ projection: { code: 'EPSG:2380' } }) 都能直接用
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 2.5 `ConfigManager.setDefaults` 全局覆盖默认值
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { ConfigManager } from 'my-openlayer'
|
|
141
|
+
|
|
142
|
+
// 应用启动时把所有线的默认宽度改成 3px
|
|
143
|
+
ConfigManager.setDefaults('LINE_OPTIONS', { strokeWidth: 3 })
|
|
144
|
+
|
|
145
|
+
// 嵌套对象深合并
|
|
146
|
+
ConfigManager.setDefaults('FLOW_LINE_OPTIONS', {
|
|
147
|
+
flowSymbol: { scale: 1.2 } // 其它 flowSymbol 字段保持原默认
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// 测试结束后重置
|
|
151
|
+
ConfigManager.resetDefaults() // 全部
|
|
152
|
+
ConfigManager.resetDefaults('LINE_OPTIONS') // 单组
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
所有现有 `add*` 方法都通过 `ConfigManager.DEFAULT_X` getter 读默认值,因此 `setDefaults` **立即对所有后续调用生效**,不需要改任何业务代码。
|
|
156
|
+
|
|
157
|
+
### 2.6 `PulsePointIconOptions.src` → `img`
|
|
158
|
+
|
|
159
|
+
为了和 `PointOptions.img` 命名统一:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// ❌ 2.x(仍可用,但 @deprecated)
|
|
163
|
+
point.addPulsePointLayer(data, {
|
|
164
|
+
layerName: 'p',
|
|
165
|
+
icon: { src: '/icon.svg', scale: 0.8 }
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// ✅ 3.0
|
|
169
|
+
point.addPulsePointLayer(data, {
|
|
170
|
+
layerName: 'p',
|
|
171
|
+
icon: { img: '/icon.svg', scale: 0.8 }
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
PointPulseLayer 同时识别 `img` 和 `src`,平滑过渡。
|
|
176
|
+
|
|
177
|
+
### 2.7 用具体错误类型做精细化处理
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { LayerNotFoundError, InvalidGeoJSONError, ProjectionError } from 'my-openlayer'
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
polygon.updateFeatureColor('nonexistent', { /* ... */ })
|
|
184
|
+
} catch (e) {
|
|
185
|
+
if (e instanceof LayerNotFoundError) {
|
|
186
|
+
// 友好提示
|
|
187
|
+
showToast(`图层 "${e.context.layerName}" 不存在,请先调用 addPolygon`)
|
|
188
|
+
} else if (e instanceof InvalidGeoJSONError) {
|
|
189
|
+
showToast('GeoJSON 数据格式有误')
|
|
190
|
+
} else {
|
|
191
|
+
throw e
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 3. 保留旧 API 的期限
|
|
199
|
+
|
|
200
|
+
下列旧 API 在 3.0 标了 `@deprecated`,**3.x 整个生命周期都仍然可用**,但 3.x 末尾(4.0)会移除。建议趁早迁移:
|
|
201
|
+
|
|
202
|
+
| 旧 API | 替代品 |
|
|
203
|
+
|---|---|
|
|
204
|
+
| `add*` 不传 `layerName`(仅使用 `ConfigManager.DEFAULT_*.layerName`) | `add*` 显式传 `layerName` |
|
|
205
|
+
| `addPolygonByUrl`(同步返回 layer) | `await addPolygonByUrl`(Promise<LayerHandle>) |
|
|
206
|
+
| `addLineByUrl`(同步返回 layer) | `await addLineByUrl`(Promise<LayerHandle>) |
|
|
207
|
+
| `MyOl.getView` | `MyOl.createView` |
|
|
208
|
+
| `PulsePointIconOptions.src` | `PulsePointIconOptions.img` |
|
|
209
|
+
| `(MyOl as any).initializeProjections` | `ProjectionManager.initialize` |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 4. 升级前后检查清单
|
|
214
|
+
|
|
215
|
+
- [ ] 所有 `add*` 调用都显式传 `layerName`(TS 编译会提示)
|
|
216
|
+
- [ ] `addPolygonByUrl` / `addLineByUrl` 调用处加 `await`,并通过 `handle.layer` 访问底层图层
|
|
217
|
+
- [ ] `MyOl.destroy()` 调用后是否真的需要重建地图(destroy 已强化级联清理,老代码可能不再需要手动 stop 各 handle)
|
|
218
|
+
- [ ] 自定义投影注册:尝试迁移到 `ProjectionManager.register` 集中管理
|
|
219
|
+
- [ ] 全局样式默认值:用 `ConfigManager.setDefaults` 替代多处复制 options
|
|
220
|
+
|
|
221
|
+
升级过程中遇到任何"老代码 TS 编译过不去"的情况,请优先翻看本指南第 1 节。
|