my-openlayer 1.0.8 → 1.0.10
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/MyOl.js +7 -4
- package/core/VueTemplatePoint.js +24 -38
- package/package.json +3 -2
- package/types.d.ts +3 -2
- package/core/DomPoint.d.ts +0 -163
- package/core/DomPoint.js +0 -432
- package/core/VueTemPoint.d.ts +0 -163
- package/core/VueTemPoint.js +0 -432
package/MyOl.js
CHANGED
|
@@ -40,13 +40,16 @@ class MyOl {
|
|
|
40
40
|
// 准备图层
|
|
41
41
|
const layers = Array.isArray(this.options.layers) ? this.options.layers : [];
|
|
42
42
|
// 创建地图实例
|
|
43
|
-
|
|
43
|
+
// 确保 view 选项不会传递给 OpenLayers Map 构造函数,避免 "then is not a function" 错误
|
|
44
|
+
// 我们完全控制传递给 Map 的选项,不直接传递用户的 options
|
|
45
|
+
const mapOptions = {
|
|
44
46
|
target: id,
|
|
45
|
-
view: MyOl.createView(this.options),
|
|
47
|
+
view: this.options.view || MyOl.createView(this.options),
|
|
46
48
|
layers: layers,
|
|
47
49
|
controls: this.createControls()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
+
};
|
|
51
|
+
this.map = new Map(mapOptions);
|
|
52
|
+
if (this.options.token && (layers.length === 0 || this.options.annotation)) {
|
|
50
53
|
this.getMapBaseLayers();
|
|
51
54
|
}
|
|
52
55
|
// 初始化基础事件监听(地图错误等)
|
package/core/VueTemplatePoint.js
CHANGED
|
@@ -24,30 +24,38 @@ async function detectAndImportVue() {
|
|
|
24
24
|
Vue = null;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
//
|
|
27
|
+
// 同步版本的Vue检测(用于兼容性)
|
|
28
28
|
function detectVueSync() {
|
|
29
29
|
try {
|
|
30
|
-
//
|
|
30
|
+
// 尝试从全局对象获取Vue
|
|
31
31
|
if (typeof window !== 'undefined' && window.Vue) {
|
|
32
32
|
Vue = window.Vue;
|
|
33
33
|
isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
|
|
34
|
+
return;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
// 如果在Node.js环境中,尝试require
|
|
37
|
+
if (typeof window === 'undefined') {
|
|
38
|
+
try {
|
|
39
|
+
// 使用eval来避免TypeScript编译时的require检查
|
|
40
|
+
const requireFunc = eval('require');
|
|
41
|
+
Vue = requireFunc('vue');
|
|
42
|
+
isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
console.warn('Vue not found. Please ensure Vue is installed in your project.');
|
|
46
|
+
Vue = null;
|
|
47
|
+
}
|
|
38
48
|
}
|
|
39
49
|
}
|
|
40
50
|
catch (e) {
|
|
41
51
|
console.warn('Failed to detect Vue:', e);
|
|
42
|
-
Vue = null;
|
|
43
52
|
}
|
|
44
53
|
}
|
|
45
54
|
// 初始化Vue导入
|
|
46
55
|
detectVueSync();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// }
|
|
56
|
+
if (!Vue) {
|
|
57
|
+
detectAndImportVue();
|
|
58
|
+
}
|
|
51
59
|
/**
|
|
52
60
|
* Vue模板点位管理类
|
|
53
61
|
* 用于在地图上添加和管理Vue组件覆盖物
|
|
@@ -169,31 +177,18 @@ class VueTemplatePointInstanceImpl {
|
|
|
169
177
|
this.validateConstructorParams(map, options);
|
|
170
178
|
// 创建DOM元素
|
|
171
179
|
this.dom = this.createDomElement();
|
|
180
|
+
// 创建Vue应用实例
|
|
181
|
+
this.createVueApp();
|
|
172
182
|
// 创建覆盖层
|
|
173
183
|
this.anchor = this.createOverlay();
|
|
174
184
|
// 添加到地图
|
|
175
185
|
this.map.addOverlay(this.anchor);
|
|
176
|
-
// 异步创建Vue应用实例
|
|
177
|
-
this.initializeVueApp();
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
this.handleError('Failed to create Vue template point', error, { map, options });
|
|
181
|
-
throw error;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* 异步初始化Vue应用
|
|
186
|
-
* @private
|
|
187
|
-
*/
|
|
188
|
-
async initializeVueApp() {
|
|
189
|
-
try {
|
|
190
|
-
await this.createVueApp();
|
|
191
186
|
// 设置初始状态
|
|
192
187
|
this.state = VueTemplatePointState.MOUNTED;
|
|
193
188
|
this.setVisible(this.options.visible ?? true);
|
|
194
189
|
}
|
|
195
190
|
catch (error) {
|
|
196
|
-
this.handleError('Failed to
|
|
191
|
+
this.handleError('Failed to create Vue template point', error, { map, options });
|
|
197
192
|
throw error;
|
|
198
193
|
}
|
|
199
194
|
}
|
|
@@ -256,17 +251,8 @@ class VueTemplatePointInstanceImpl {
|
|
|
256
251
|
* 创建Vue应用实例
|
|
257
252
|
* @private
|
|
258
253
|
*/
|
|
259
|
-
|
|
254
|
+
createVueApp() {
|
|
260
255
|
const { Template, props } = this.options;
|
|
261
|
-
// 如果Vue不可用,尝试异步导入
|
|
262
|
-
if (!Vue) {
|
|
263
|
-
try {
|
|
264
|
-
await detectAndImportVue();
|
|
265
|
-
}
|
|
266
|
-
catch (error) {
|
|
267
|
-
throw new Error('Vue is not available. Please ensure Vue is installed in your project.');
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
256
|
if (!Vue) {
|
|
271
257
|
throw new Error('Vue is not available. Please ensure Vue is installed in your project.');
|
|
272
258
|
}
|
|
@@ -373,7 +359,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
373
359
|
* @param newProps 新的属性对象
|
|
374
360
|
* @throws 当操作失败时抛出错误
|
|
375
361
|
*/
|
|
376
|
-
|
|
362
|
+
updateProps(newProps) {
|
|
377
363
|
if (this.state === VueTemplatePointState.DESTROYED) {
|
|
378
364
|
throw new Error('Cannot update props on destroyed DOM point');
|
|
379
365
|
}
|
|
@@ -381,7 +367,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
381
367
|
// 重新创建Vue应用实例
|
|
382
368
|
this.destroyVueApp();
|
|
383
369
|
this.options.props = { ...this.options.props, ...newProps };
|
|
384
|
-
|
|
370
|
+
this.createVueApp();
|
|
385
371
|
}
|
|
386
372
|
catch (error) {
|
|
387
373
|
this.handleError('Failed to update props', error, { newProps });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-openlayer",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.10",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@turf/turf": "^7.2.0",
|
|
31
31
|
"ol": "^6.15.1",
|
|
32
|
-
"proj4": "^2.7.5"
|
|
32
|
+
"proj4": "^2.7.5",
|
|
33
|
+
"my-openlayer": "^1.0.9"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"@types/proj4": "^2.5.2",
|
package/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import BaseLayer from "ol/layer/Base";
|
|
2
2
|
import TileLayer from "ol/layer/Tile";
|
|
3
3
|
import { WMTS } from "ol/source";
|
|
4
|
+
import View from "ol/View";
|
|
4
5
|
export interface Feature {
|
|
5
6
|
type: string;
|
|
6
7
|
properties: any;
|
|
@@ -21,7 +22,7 @@ export interface MapInitType {
|
|
|
21
22
|
};
|
|
22
23
|
zoom?: number;
|
|
23
24
|
center?: number[];
|
|
24
|
-
view?:
|
|
25
|
+
view?: View;
|
|
25
26
|
minZoom?: number;
|
|
26
27
|
maxZoom?: number;
|
|
27
28
|
extent?: number[];
|
|
@@ -290,7 +291,7 @@ export interface VueTemplatePointInstance {
|
|
|
290
291
|
options: VueTemplatePointOptions;
|
|
291
292
|
setVisible(visible: boolean): void;
|
|
292
293
|
updatePosition(lgtd: number, lttd: number): void;
|
|
293
|
-
updateProps(newProps: Record<string, any>):
|
|
294
|
+
updateProps(newProps: Record<string, any>): void;
|
|
294
295
|
setStyle(styles: Partial<CSSStyleDeclaration>): void;
|
|
295
296
|
addClass(className: string): void;
|
|
296
297
|
removeClass(className: string): void;
|
package/core/DomPoint.d.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { Map } from 'ol';
|
|
2
|
-
import Overlay from 'ol/Overlay';
|
|
3
|
-
import { Coordinate } from 'ol/coordinate';
|
|
4
|
-
import { DomPointOptions, DomPointState } from '../types';
|
|
5
|
-
/**
|
|
6
|
-
* DOM点位管理类
|
|
7
|
-
* 用于在地图上添加和管理DOM元素覆盖物
|
|
8
|
-
*/
|
|
9
|
-
export default class DomPoint {
|
|
10
|
-
private readonly map;
|
|
11
|
-
private readonly errorHandler;
|
|
12
|
-
private app;
|
|
13
|
-
private readonly anchor;
|
|
14
|
-
private readonly dom;
|
|
15
|
-
private readonly id;
|
|
16
|
-
private readonly options;
|
|
17
|
-
private state;
|
|
18
|
-
private position;
|
|
19
|
-
/**
|
|
20
|
-
* 构造函数
|
|
21
|
-
* @param map OpenLayers地图实例
|
|
22
|
-
* @param options 配置选项
|
|
23
|
-
* @throws 当参数无效时抛出错误
|
|
24
|
-
*/
|
|
25
|
-
constructor(map: Map, options: DomPointOptions);
|
|
26
|
-
/**
|
|
27
|
-
* 验证构造函数参数
|
|
28
|
-
* @param map 地图实例
|
|
29
|
-
* @param options 配置选项
|
|
30
|
-
* @private
|
|
31
|
-
*/
|
|
32
|
-
private validateConstructorParams;
|
|
33
|
-
/**
|
|
34
|
-
* 合并默认配置选项
|
|
35
|
-
* @param options 用户配置选项
|
|
36
|
-
* @returns 合并后的配置选项
|
|
37
|
-
* @private
|
|
38
|
-
*/
|
|
39
|
-
private mergeDefaultOptions;
|
|
40
|
-
/**
|
|
41
|
-
* 生成唯一ID
|
|
42
|
-
* @returns 唯一标识符
|
|
43
|
-
* @private
|
|
44
|
-
*/
|
|
45
|
-
private generateUniqueId;
|
|
46
|
-
/**
|
|
47
|
-
* 创建DOM元素
|
|
48
|
-
* @returns DOM元素
|
|
49
|
-
* @private
|
|
50
|
-
*/
|
|
51
|
-
private createDomElement;
|
|
52
|
-
/**
|
|
53
|
-
* 创建Vue应用实例
|
|
54
|
-
* @private
|
|
55
|
-
*/
|
|
56
|
-
private createVueApp;
|
|
57
|
-
/**
|
|
58
|
-
* 创建覆盖层
|
|
59
|
-
* @returns 覆盖层实例
|
|
60
|
-
* @private
|
|
61
|
-
*/
|
|
62
|
-
private createOverlay;
|
|
63
|
-
/**
|
|
64
|
-
* 错误处理
|
|
65
|
-
* @param message 错误消息
|
|
66
|
-
* @param error 原始错误
|
|
67
|
-
* @param context 错误上下文
|
|
68
|
-
* @private
|
|
69
|
-
*/
|
|
70
|
-
private handleError;
|
|
71
|
-
/**
|
|
72
|
-
* 设置可见性
|
|
73
|
-
* @param visible 是否可见
|
|
74
|
-
* @throws 当操作失败时抛出错误
|
|
75
|
-
*/
|
|
76
|
-
setVisible(visible: boolean): void;
|
|
77
|
-
/**
|
|
78
|
-
* 获取当前可见性状态
|
|
79
|
-
* @returns 是否可见
|
|
80
|
-
*/
|
|
81
|
-
isVisible(): boolean;
|
|
82
|
-
/**
|
|
83
|
-
* 更新位置
|
|
84
|
-
* @param lgtd 新经度
|
|
85
|
-
* @param lttd 新纬度
|
|
86
|
-
* @throws 当操作失败时抛出错误
|
|
87
|
-
*/
|
|
88
|
-
updatePosition(lgtd: number, lttd: number): void;
|
|
89
|
-
/**
|
|
90
|
-
* 获取当前位置
|
|
91
|
-
* @returns 当前坐标位置
|
|
92
|
-
*/
|
|
93
|
-
getPosition(): Coordinate;
|
|
94
|
-
/**
|
|
95
|
-
* 更新组件属性
|
|
96
|
-
* @param newProps 新的属性对象
|
|
97
|
-
* @throws 当操作失败时抛出错误
|
|
98
|
-
*/
|
|
99
|
-
updateProps(newProps: Record<string, any>): void;
|
|
100
|
-
/**
|
|
101
|
-
* 设置CSS样式
|
|
102
|
-
* @param styles 样式对象
|
|
103
|
-
* @throws 当操作失败时抛出错误
|
|
104
|
-
*/
|
|
105
|
-
setStyle(styles: Partial<CSSStyleDeclaration>): void;
|
|
106
|
-
/**
|
|
107
|
-
* 添加CSS类名
|
|
108
|
-
* @param className 要添加的类名
|
|
109
|
-
* @throws 当操作失败时抛出错误
|
|
110
|
-
*/
|
|
111
|
-
addClass(className: string): void;
|
|
112
|
-
/**
|
|
113
|
-
* 移除CSS类名
|
|
114
|
-
* @param className 要移除的类名
|
|
115
|
-
* @throws 当操作失败时抛出错误
|
|
116
|
-
*/
|
|
117
|
-
removeClass(className: string): void;
|
|
118
|
-
/**
|
|
119
|
-
* 销毁Vue应用实例
|
|
120
|
-
* @private
|
|
121
|
-
*/
|
|
122
|
-
private destroyVueApp;
|
|
123
|
-
/**
|
|
124
|
-
* 移除点位
|
|
125
|
-
* @throws 当移除失败时抛出错误
|
|
126
|
-
*/
|
|
127
|
-
remove(): void;
|
|
128
|
-
/**
|
|
129
|
-
* 获取覆盖层
|
|
130
|
-
* @returns 覆盖层实例
|
|
131
|
-
*/
|
|
132
|
-
getOverlay(): Overlay;
|
|
133
|
-
/**
|
|
134
|
-
* 获取点位ID
|
|
135
|
-
* @returns 点位唯一标识符
|
|
136
|
-
*/
|
|
137
|
-
getId(): string;
|
|
138
|
-
/**
|
|
139
|
-
* 获取DOM元素
|
|
140
|
-
* @returns DOM元素
|
|
141
|
-
*/
|
|
142
|
-
getDomElement(): HTMLElement;
|
|
143
|
-
/**
|
|
144
|
-
* 获取当前状态
|
|
145
|
-
* @returns 当前状态
|
|
146
|
-
*/
|
|
147
|
-
getState(): DomPointState;
|
|
148
|
-
/**
|
|
149
|
-
* 获取配置选项
|
|
150
|
-
* @returns 配置选项的副本
|
|
151
|
-
*/
|
|
152
|
-
getOptions(): Readonly<DomPointOptions>;
|
|
153
|
-
/**
|
|
154
|
-
* 检查是否已销毁
|
|
155
|
-
* @returns 是否已销毁
|
|
156
|
-
*/
|
|
157
|
-
isDestroyed(): boolean;
|
|
158
|
-
/**
|
|
159
|
-
* 获取地图实例
|
|
160
|
-
* @returns 地图实例
|
|
161
|
-
*/
|
|
162
|
-
getMap(): Map;
|
|
163
|
-
}
|
package/core/DomPoint.js
DELETED
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
import Overlay from 'ol/Overlay';
|
|
2
|
-
import { DomPointState } from '../types';
|
|
3
|
-
import { ErrorHandler, ErrorType } from '../utils/ErrorHandler';
|
|
4
|
-
import { ValidationUtils } from '../utils/ValidationUtils';
|
|
5
|
-
// 动态导入Vue
|
|
6
|
-
let Vue = null;
|
|
7
|
-
let isVue3 = false;
|
|
8
|
-
// 检测Vue版本并导入
|
|
9
|
-
async function detectAndImportVue() {
|
|
10
|
-
try {
|
|
11
|
-
// 尝试动态导入Vue
|
|
12
|
-
const vueModule = await import('vue');
|
|
13
|
-
Vue = vueModule.default || vueModule;
|
|
14
|
-
// 检测Vue版本
|
|
15
|
-
if (Vue && (Vue.version?.startsWith('3') || Vue.createApp)) {
|
|
16
|
-
isVue3 = true;
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
isVue3 = false;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
catch (e) {
|
|
23
|
-
console.warn('Vue not found. Please ensure Vue is installed in your project.');
|
|
24
|
-
Vue = null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// 同步版本的Vue检测(用于兼容性)
|
|
28
|
-
function detectVueSync() {
|
|
29
|
-
try {
|
|
30
|
-
// 尝试从全局对象获取Vue
|
|
31
|
-
if (typeof window !== 'undefined' && window.Vue) {
|
|
32
|
-
Vue = window.Vue;
|
|
33
|
-
isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
// 如果在Node.js环境中,尝试require
|
|
37
|
-
if (typeof window === 'undefined') {
|
|
38
|
-
try {
|
|
39
|
-
// 使用eval来避免TypeScript编译时的require检查
|
|
40
|
-
const requireFunc = eval('require');
|
|
41
|
-
Vue = requireFunc('vue');
|
|
42
|
-
isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
|
|
43
|
-
}
|
|
44
|
-
catch (e) {
|
|
45
|
-
console.warn('Vue not found. Please ensure Vue is installed in your project.');
|
|
46
|
-
Vue = null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
catch (e) {
|
|
51
|
-
console.warn('Failed to detect Vue:', e);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// 初始化Vue导入
|
|
55
|
-
detectVueSync();
|
|
56
|
-
if (!Vue) {
|
|
57
|
-
detectAndImportVue();
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* DOM点位管理类
|
|
61
|
-
* 用于在地图上添加和管理DOM元素覆盖物
|
|
62
|
-
*/
|
|
63
|
-
export default class DomPoint {
|
|
64
|
-
/**
|
|
65
|
-
* 构造函数
|
|
66
|
-
* @param map OpenLayers地图实例
|
|
67
|
-
* @param options 配置选项
|
|
68
|
-
* @throws 当参数无效时抛出错误
|
|
69
|
-
*/
|
|
70
|
-
constructor(map, options) {
|
|
71
|
-
this.app = null;
|
|
72
|
-
this.state = DomPointState.CREATED;
|
|
73
|
-
this.errorHandler = ErrorHandler.getInstance();
|
|
74
|
-
try {
|
|
75
|
-
// 参数验证
|
|
76
|
-
this.validateConstructorParams(map, options);
|
|
77
|
-
this.map = map;
|
|
78
|
-
this.options = this.mergeDefaultOptions(options);
|
|
79
|
-
this.id = this.generateUniqueId();
|
|
80
|
-
this.position = [this.options.lgtd, this.options.lttd];
|
|
81
|
-
// 创建DOM元素
|
|
82
|
-
this.dom = this.createDomElement();
|
|
83
|
-
// 创建Vue应用实例
|
|
84
|
-
this.createVueApp();
|
|
85
|
-
// 创建覆盖层
|
|
86
|
-
this.anchor = this.createOverlay();
|
|
87
|
-
// 添加到地图
|
|
88
|
-
this.map.addOverlay(this.anchor);
|
|
89
|
-
// 设置初始状态
|
|
90
|
-
this.state = DomPointState.MOUNTED;
|
|
91
|
-
this.setVisible(this.options.visible ?? true);
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
this.handleError('Failed to create DOM point', error, { map, options });
|
|
95
|
-
throw error;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* 验证构造函数参数
|
|
100
|
-
* @param map 地图实例
|
|
101
|
-
* @param options 配置选项
|
|
102
|
-
* @private
|
|
103
|
-
*/
|
|
104
|
-
validateConstructorParams(map, options) {
|
|
105
|
-
ValidationUtils.validateRequired(map, 'Map instance is required');
|
|
106
|
-
ValidationUtils.validateRequired(options, 'Options are required');
|
|
107
|
-
const { Template, lgtd, lttd } = options;
|
|
108
|
-
ValidationUtils.validateRequired(Template, 'Template is required in options');
|
|
109
|
-
if (typeof lgtd !== 'number' || typeof lttd !== 'number') {
|
|
110
|
-
throw new Error('Longitude and lttd must be numbers');
|
|
111
|
-
}
|
|
112
|
-
ValidationUtils.validateCoordinate(lgtd, lttd);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* 合并默认配置选项
|
|
116
|
-
* @param options 用户配置选项
|
|
117
|
-
* @returns 合并后的配置选项
|
|
118
|
-
* @private
|
|
119
|
-
*/
|
|
120
|
-
mergeDefaultOptions(options) {
|
|
121
|
-
return {
|
|
122
|
-
positioning: 'center-center',
|
|
123
|
-
stopEvent: false,
|
|
124
|
-
visible: true,
|
|
125
|
-
zIndex: 1,
|
|
126
|
-
...options
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* 生成唯一ID
|
|
131
|
-
* @returns 唯一标识符
|
|
132
|
-
* @private
|
|
133
|
-
*/
|
|
134
|
-
generateUniqueId() {
|
|
135
|
-
return `dom-point-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* 创建DOM元素
|
|
139
|
-
* @returns DOM元素
|
|
140
|
-
* @private
|
|
141
|
-
*/
|
|
142
|
-
createDomElement() {
|
|
143
|
-
const element = document.createElement('div');
|
|
144
|
-
element.id = this.id;
|
|
145
|
-
if (this.options.className) {
|
|
146
|
-
element.className = this.options.className;
|
|
147
|
-
}
|
|
148
|
-
if (this.options.zIndex) {
|
|
149
|
-
element.style.zIndex = this.options.zIndex.toString();
|
|
150
|
-
}
|
|
151
|
-
return element;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* 创建Vue应用实例
|
|
155
|
-
* @private
|
|
156
|
-
*/
|
|
157
|
-
createVueApp() {
|
|
158
|
-
const { Template, props } = this.options;
|
|
159
|
-
if (!Vue) {
|
|
160
|
-
throw new Error('Vue is not available. Please ensure Vue is installed in your project.');
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
if (isVue3) {
|
|
164
|
-
// Vue 3
|
|
165
|
-
this.app = Vue.createApp({
|
|
166
|
-
...Template,
|
|
167
|
-
props: props || {}
|
|
168
|
-
});
|
|
169
|
-
this.app.mount(this.dom);
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
// Vue 2
|
|
173
|
-
this.app = new Vue({
|
|
174
|
-
el: this.dom,
|
|
175
|
-
render: (h) => h(Template, { props: props || {} })
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
throw new Error(`Failed to create Vue app: ${error}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* 创建覆盖层
|
|
185
|
-
* @returns 覆盖层实例
|
|
186
|
-
* @private
|
|
187
|
-
*/
|
|
188
|
-
createOverlay() {
|
|
189
|
-
const overlay = new Overlay({
|
|
190
|
-
element: this.dom,
|
|
191
|
-
positioning: this.options.positioning || 'center-center',
|
|
192
|
-
stopEvent: this.options.stopEvent || false
|
|
193
|
-
});
|
|
194
|
-
overlay.setPosition(this.position);
|
|
195
|
-
return overlay;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* 错误处理
|
|
199
|
-
* @param message 错误消息
|
|
200
|
-
* @param error 原始错误
|
|
201
|
-
* @param context 错误上下文
|
|
202
|
-
* @private
|
|
203
|
-
*/
|
|
204
|
-
handleError(message, error, context) {
|
|
205
|
-
this.errorHandler.createAndHandleError(`${message}: ${error}`, ErrorType.COMPONENT_ERROR, { ...context, domPointId: this.id });
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* 设置可见性
|
|
209
|
-
* @param visible 是否可见
|
|
210
|
-
* @throws 当操作失败时抛出错误
|
|
211
|
-
*/
|
|
212
|
-
setVisible(visible) {
|
|
213
|
-
if (this.state === DomPointState.DESTROYED) {
|
|
214
|
-
throw new Error('Cannot set visibility on destroyed DOM point');
|
|
215
|
-
}
|
|
216
|
-
ValidationUtils.validateType(visible, 'boolean', 'Visible parameter must be a boolean');
|
|
217
|
-
try {
|
|
218
|
-
this.dom.style.visibility = visible ? 'visible' : 'hidden';
|
|
219
|
-
this.state = visible ? DomPointState.VISIBLE : DomPointState.HIDDEN;
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
this.handleError('Failed to set visibility', error, { visible });
|
|
223
|
-
throw error;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* 获取当前可见性状态
|
|
228
|
-
* @returns 是否可见
|
|
229
|
-
*/
|
|
230
|
-
isVisible() {
|
|
231
|
-
return this.state === DomPointState.VISIBLE;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* 更新位置
|
|
235
|
-
* @param lgtd 新经度
|
|
236
|
-
* @param lttd 新纬度
|
|
237
|
-
* @throws 当操作失败时抛出错误
|
|
238
|
-
*/
|
|
239
|
-
updatePosition(lgtd, lttd) {
|
|
240
|
-
if (this.state === DomPointState.DESTROYED) {
|
|
241
|
-
throw new Error('Cannot update position on destroyed DOM point');
|
|
242
|
-
}
|
|
243
|
-
ValidationUtils.validateCoordinate(lgtd, lttd);
|
|
244
|
-
try {
|
|
245
|
-
this.position = [lgtd, lttd];
|
|
246
|
-
this.anchor.setPosition(this.position);
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
this.handleError('Failed to update position', error, { lgtd, lttd });
|
|
250
|
-
throw error;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* 获取当前位置
|
|
255
|
-
* @returns 当前坐标位置
|
|
256
|
-
*/
|
|
257
|
-
getPosition() {
|
|
258
|
-
return [...this.position];
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* 更新组件属性
|
|
262
|
-
* @param newProps 新的属性对象
|
|
263
|
-
* @throws 当操作失败时抛出错误
|
|
264
|
-
*/
|
|
265
|
-
updateProps(newProps) {
|
|
266
|
-
if (this.state === DomPointState.DESTROYED) {
|
|
267
|
-
throw new Error('Cannot update props on destroyed DOM point');
|
|
268
|
-
}
|
|
269
|
-
try {
|
|
270
|
-
// 重新创建Vue应用实例
|
|
271
|
-
this.destroyVueApp();
|
|
272
|
-
this.options.props = { ...this.options.props, ...newProps };
|
|
273
|
-
this.createVueApp();
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
this.handleError('Failed to update props', error, { newProps });
|
|
277
|
-
throw error;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* 设置CSS样式
|
|
282
|
-
* @param styles 样式对象
|
|
283
|
-
* @throws 当操作失败时抛出错误
|
|
284
|
-
*/
|
|
285
|
-
setStyle(styles) {
|
|
286
|
-
if (this.state === DomPointState.DESTROYED) {
|
|
287
|
-
throw new Error('Cannot set style on destroyed DOM point');
|
|
288
|
-
}
|
|
289
|
-
try {
|
|
290
|
-
Object.assign(this.dom.style, styles);
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
this.handleError('Failed to set style', error, { styles });
|
|
294
|
-
throw error;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* 添加CSS类名
|
|
299
|
-
* @param className 要添加的类名
|
|
300
|
-
* @throws 当操作失败时抛出错误
|
|
301
|
-
*/
|
|
302
|
-
addClass(className) {
|
|
303
|
-
if (this.state === DomPointState.DESTROYED) {
|
|
304
|
-
throw new Error('Cannot add class on destroyed DOM point');
|
|
305
|
-
}
|
|
306
|
-
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
307
|
-
try {
|
|
308
|
-
this.dom.classList.add(className);
|
|
309
|
-
}
|
|
310
|
-
catch (error) {
|
|
311
|
-
this.handleError('Failed to add class', error, { className });
|
|
312
|
-
throw error;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* 移除CSS类名
|
|
317
|
-
* @param className 要移除的类名
|
|
318
|
-
* @throws 当操作失败时抛出错误
|
|
319
|
-
*/
|
|
320
|
-
removeClass(className) {
|
|
321
|
-
if (this.state === DomPointState.DESTROYED) {
|
|
322
|
-
throw new Error('Cannot remove class on destroyed DOM point');
|
|
323
|
-
}
|
|
324
|
-
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
325
|
-
try {
|
|
326
|
-
this.dom.classList.remove(className);
|
|
327
|
-
}
|
|
328
|
-
catch (error) {
|
|
329
|
-
this.handleError('Failed to remove class', error, { className });
|
|
330
|
-
throw error;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* 销毁Vue应用实例
|
|
335
|
-
* @private
|
|
336
|
-
*/
|
|
337
|
-
destroyVueApp() {
|
|
338
|
-
if (this.app) {
|
|
339
|
-
try {
|
|
340
|
-
if (isVue3) {
|
|
341
|
-
// Vue 3: 使用 unmount
|
|
342
|
-
this.app.unmount();
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
345
|
-
// Vue 2: 使用 $destroy
|
|
346
|
-
this.app.$destroy();
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
catch (error) {
|
|
350
|
-
this.handleError('Failed to destroy Vue app', error);
|
|
351
|
-
}
|
|
352
|
-
finally {
|
|
353
|
-
this.app = null;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* 移除点位
|
|
359
|
-
* @throws 当移除失败时抛出错误
|
|
360
|
-
*/
|
|
361
|
-
remove() {
|
|
362
|
-
if (this.state === DomPointState.DESTROYED) {
|
|
363
|
-
console.warn('DOM point already destroyed');
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
try {
|
|
367
|
-
// 销毁Vue应用实例
|
|
368
|
-
this.destroyVueApp();
|
|
369
|
-
// 从地图移除覆盖层
|
|
370
|
-
this.map.removeOverlay(this.anchor);
|
|
371
|
-
// 清理DOM元素
|
|
372
|
-
if (this.dom && this.dom.parentNode) {
|
|
373
|
-
this.dom.parentNode.removeChild(this.dom);
|
|
374
|
-
}
|
|
375
|
-
// 更新状态
|
|
376
|
-
this.state = DomPointState.DESTROYED;
|
|
377
|
-
}
|
|
378
|
-
catch (error) {
|
|
379
|
-
this.handleError('Failed to remove DOM point', error);
|
|
380
|
-
throw error;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* 获取覆盖层
|
|
385
|
-
* @returns 覆盖层实例
|
|
386
|
-
*/
|
|
387
|
-
getOverlay() {
|
|
388
|
-
return this.anchor;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* 获取点位ID
|
|
392
|
-
* @returns 点位唯一标识符
|
|
393
|
-
*/
|
|
394
|
-
getId() {
|
|
395
|
-
return this.id;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* 获取DOM元素
|
|
399
|
-
* @returns DOM元素
|
|
400
|
-
*/
|
|
401
|
-
getDomElement() {
|
|
402
|
-
return this.dom;
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* 获取当前状态
|
|
406
|
-
* @returns 当前状态
|
|
407
|
-
*/
|
|
408
|
-
getState() {
|
|
409
|
-
return this.state;
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* 获取配置选项
|
|
413
|
-
* @returns 配置选项的副本
|
|
414
|
-
*/
|
|
415
|
-
getOptions() {
|
|
416
|
-
return Object.freeze({ ...this.options });
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* 检查是否已销毁
|
|
420
|
-
* @returns 是否已销毁
|
|
421
|
-
*/
|
|
422
|
-
isDestroyed() {
|
|
423
|
-
return this.state === DomPointState.DESTROYED;
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
* 获取地图实例
|
|
427
|
-
* @returns 地图实例
|
|
428
|
-
*/
|
|
429
|
-
getMap() {
|
|
430
|
-
return this.map;
|
|
431
|
-
}
|
|
432
|
-
}
|
package/core/VueTemPoint.d.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { Map } from 'ol';
|
|
2
|
-
import Overlay from 'ol/Overlay';
|
|
3
|
-
import { Coordinate } from 'ol/coordinate';
|
|
4
|
-
import { VueTemPointOptions, VueTemPointState } from '../types';
|
|
5
|
-
/**
|
|
6
|
-
* DOM点位管理类
|
|
7
|
-
* 用于在地图上添加和管理DOM元素覆盖物
|
|
8
|
-
*/
|
|
9
|
-
export default class VueTemPoint {
|
|
10
|
-
private readonly map;
|
|
11
|
-
private readonly errorHandler;
|
|
12
|
-
private app;
|
|
13
|
-
private readonly anchor;
|
|
14
|
-
private readonly dom;
|
|
15
|
-
private readonly id;
|
|
16
|
-
private readonly options;
|
|
17
|
-
private state;
|
|
18
|
-
private position;
|
|
19
|
-
/**
|
|
20
|
-
* 构造函数
|
|
21
|
-
* @param map OpenLayers地图实例
|
|
22
|
-
* @param options 配置选项
|
|
23
|
-
* @throws 当参数无效时抛出错误
|
|
24
|
-
*/
|
|
25
|
-
constructor(map: Map, options: VueTemPointOptions);
|
|
26
|
-
/**
|
|
27
|
-
* 验证构造函数参数
|
|
28
|
-
* @param map 地图实例
|
|
29
|
-
* @param options 配置选项
|
|
30
|
-
* @private
|
|
31
|
-
*/
|
|
32
|
-
private validateConstructorParams;
|
|
33
|
-
/**
|
|
34
|
-
* 合并默认配置选项
|
|
35
|
-
* @param options 用户配置选项
|
|
36
|
-
* @returns 合并后的配置选项
|
|
37
|
-
* @private
|
|
38
|
-
*/
|
|
39
|
-
private mergeDefaultOptions;
|
|
40
|
-
/**
|
|
41
|
-
* 生成唯一ID
|
|
42
|
-
* @returns 唯一标识符
|
|
43
|
-
* @private
|
|
44
|
-
*/
|
|
45
|
-
private generateUniqueId;
|
|
46
|
-
/**
|
|
47
|
-
* 创建DOM元素
|
|
48
|
-
* @returns DOM元素
|
|
49
|
-
* @private
|
|
50
|
-
*/
|
|
51
|
-
private createDomElement;
|
|
52
|
-
/**
|
|
53
|
-
* 创建Vue应用实例
|
|
54
|
-
* @private
|
|
55
|
-
*/
|
|
56
|
-
private createVueApp;
|
|
57
|
-
/**
|
|
58
|
-
* 创建覆盖层
|
|
59
|
-
* @returns 覆盖层实例
|
|
60
|
-
* @private
|
|
61
|
-
*/
|
|
62
|
-
private createOverlay;
|
|
63
|
-
/**
|
|
64
|
-
* 错误处理
|
|
65
|
-
* @param message 错误消息
|
|
66
|
-
* @param error 原始错误
|
|
67
|
-
* @param context 错误上下文
|
|
68
|
-
* @private
|
|
69
|
-
*/
|
|
70
|
-
private handleError;
|
|
71
|
-
/**
|
|
72
|
-
* 设置可见性
|
|
73
|
-
* @param visible 是否可见
|
|
74
|
-
* @throws 当操作失败时抛出错误
|
|
75
|
-
*/
|
|
76
|
-
setVisible(visible: boolean): void;
|
|
77
|
-
/**
|
|
78
|
-
* 获取当前可见性状态
|
|
79
|
-
* @returns 是否可见
|
|
80
|
-
*/
|
|
81
|
-
isVisible(): boolean;
|
|
82
|
-
/**
|
|
83
|
-
* 更新位置
|
|
84
|
-
* @param lgtd 新经度
|
|
85
|
-
* @param lttd 新纬度
|
|
86
|
-
* @throws 当操作失败时抛出错误
|
|
87
|
-
*/
|
|
88
|
-
updatePosition(lgtd: number, lttd: number): void;
|
|
89
|
-
/**
|
|
90
|
-
* 获取当前位置
|
|
91
|
-
* @returns 当前坐标位置
|
|
92
|
-
*/
|
|
93
|
-
getPosition(): Coordinate;
|
|
94
|
-
/**
|
|
95
|
-
* 更新组件属性
|
|
96
|
-
* @param newProps 新的属性对象
|
|
97
|
-
* @throws 当操作失败时抛出错误
|
|
98
|
-
*/
|
|
99
|
-
updateProps(newProps: Record<string, any>): void;
|
|
100
|
-
/**
|
|
101
|
-
* 设置CSS样式
|
|
102
|
-
* @param styles 样式对象
|
|
103
|
-
* @throws 当操作失败时抛出错误
|
|
104
|
-
*/
|
|
105
|
-
setStyle(styles: Partial<CSSStyleDeclaration>): void;
|
|
106
|
-
/**
|
|
107
|
-
* 添加CSS类名
|
|
108
|
-
* @param className 要添加的类名
|
|
109
|
-
* @throws 当操作失败时抛出错误
|
|
110
|
-
*/
|
|
111
|
-
addClass(className: string): void;
|
|
112
|
-
/**
|
|
113
|
-
* 移除CSS类名
|
|
114
|
-
* @param className 要移除的类名
|
|
115
|
-
* @throws 当操作失败时抛出错误
|
|
116
|
-
*/
|
|
117
|
-
removeClass(className: string): void;
|
|
118
|
-
/**
|
|
119
|
-
* 销毁Vue应用实例
|
|
120
|
-
* @private
|
|
121
|
-
*/
|
|
122
|
-
private destroyVueApp;
|
|
123
|
-
/**
|
|
124
|
-
* 移除点位
|
|
125
|
-
* @throws 当移除失败时抛出错误
|
|
126
|
-
*/
|
|
127
|
-
remove(): void;
|
|
128
|
-
/**
|
|
129
|
-
* 获取覆盖层
|
|
130
|
-
* @returns 覆盖层实例
|
|
131
|
-
*/
|
|
132
|
-
getOverlay(): Overlay;
|
|
133
|
-
/**
|
|
134
|
-
* 获取点位ID
|
|
135
|
-
* @returns 点位唯一标识符
|
|
136
|
-
*/
|
|
137
|
-
getId(): string;
|
|
138
|
-
/**
|
|
139
|
-
* 获取DOM元素
|
|
140
|
-
* @returns DOM元素
|
|
141
|
-
*/
|
|
142
|
-
getDomElement(): HTMLElement;
|
|
143
|
-
/**
|
|
144
|
-
* 获取当前状态
|
|
145
|
-
* @returns 当前状态
|
|
146
|
-
*/
|
|
147
|
-
getState(): VueTemPointState;
|
|
148
|
-
/**
|
|
149
|
-
* 获取配置选项
|
|
150
|
-
* @returns 配置选项的副本
|
|
151
|
-
*/
|
|
152
|
-
getOptions(): Readonly<VueTemPointOptions>;
|
|
153
|
-
/**
|
|
154
|
-
* 检查是否已销毁
|
|
155
|
-
* @returns 是否已销毁
|
|
156
|
-
*/
|
|
157
|
-
isDestroyed(): boolean;
|
|
158
|
-
/**
|
|
159
|
-
* 获取地图实例
|
|
160
|
-
* @returns 地图实例
|
|
161
|
-
*/
|
|
162
|
-
getMap(): Map;
|
|
163
|
-
}
|
package/core/VueTemPoint.js
DELETED
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
import Overlay from 'ol/Overlay';
|
|
2
|
-
import { VueTemPointState } from '../types';
|
|
3
|
-
import { ErrorHandler, ErrorType } from '../utils/ErrorHandler';
|
|
4
|
-
import { ValidationUtils } from '../utils/ValidationUtils';
|
|
5
|
-
// 动态导入Vue
|
|
6
|
-
let Vue = null;
|
|
7
|
-
let isVue3 = false;
|
|
8
|
-
// 检测Vue版本并导入
|
|
9
|
-
async function detectAndImportVue() {
|
|
10
|
-
try {
|
|
11
|
-
// 尝试动态导入Vue
|
|
12
|
-
const vueModule = await import('vue');
|
|
13
|
-
Vue = vueModule.default || vueModule;
|
|
14
|
-
// 检测Vue版本
|
|
15
|
-
if (Vue && (Vue.version?.startsWith('3') || Vue.createApp)) {
|
|
16
|
-
isVue3 = true;
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
isVue3 = false;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
catch (e) {
|
|
23
|
-
console.warn('Vue not found. Please ensure Vue is installed in your project.');
|
|
24
|
-
Vue = null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// 同步版本的Vue检测(用于兼容性)
|
|
28
|
-
function detectVueSync() {
|
|
29
|
-
try {
|
|
30
|
-
// 尝试从全局对象获取Vue
|
|
31
|
-
if (typeof window !== 'undefined' && window.Vue) {
|
|
32
|
-
Vue = window.Vue;
|
|
33
|
-
isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
// 如果在Node.js环境中,尝试require
|
|
37
|
-
if (typeof window === 'undefined') {
|
|
38
|
-
try {
|
|
39
|
-
// 使用eval来避免TypeScript编译时的require检查
|
|
40
|
-
const requireFunc = eval('require');
|
|
41
|
-
Vue = requireFunc('vue');
|
|
42
|
-
isVue3 = !!(Vue.version?.startsWith('3') || Vue.createApp);
|
|
43
|
-
}
|
|
44
|
-
catch (e) {
|
|
45
|
-
console.warn('Vue not found. Please ensure Vue is installed in your project.');
|
|
46
|
-
Vue = null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
catch (e) {
|
|
51
|
-
console.warn('Failed to detect Vue:', e);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// 初始化Vue导入
|
|
55
|
-
detectVueSync();
|
|
56
|
-
if (!Vue) {
|
|
57
|
-
detectAndImportVue();
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* DOM点位管理类
|
|
61
|
-
* 用于在地图上添加和管理DOM元素覆盖物
|
|
62
|
-
*/
|
|
63
|
-
export default class VueTemPoint {
|
|
64
|
-
/**
|
|
65
|
-
* 构造函数
|
|
66
|
-
* @param map OpenLayers地图实例
|
|
67
|
-
* @param options 配置选项
|
|
68
|
-
* @throws 当参数无效时抛出错误
|
|
69
|
-
*/
|
|
70
|
-
constructor(map, options) {
|
|
71
|
-
this.app = null;
|
|
72
|
-
this.state = VueTemPointState.CREATED;
|
|
73
|
-
this.errorHandler = ErrorHandler.getInstance();
|
|
74
|
-
try {
|
|
75
|
-
// 参数验证
|
|
76
|
-
this.validateConstructorParams(map, options);
|
|
77
|
-
this.map = map;
|
|
78
|
-
this.options = this.mergeDefaultOptions(options);
|
|
79
|
-
this.id = this.generateUniqueId();
|
|
80
|
-
this.position = [this.options.lgtd, this.options.lttd];
|
|
81
|
-
// 创建DOM元素
|
|
82
|
-
this.dom = this.createDomElement();
|
|
83
|
-
// 创建Vue应用实例
|
|
84
|
-
this.createVueApp();
|
|
85
|
-
// 创建覆盖层
|
|
86
|
-
this.anchor = this.createOverlay();
|
|
87
|
-
// 添加到地图
|
|
88
|
-
this.map.addOverlay(this.anchor);
|
|
89
|
-
// 设置初始状态
|
|
90
|
-
this.state = VueTemPointState.MOUNTED;
|
|
91
|
-
this.setVisible(this.options.visible ?? true);
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
this.handleError('Failed to create DOM point', error, { map, options });
|
|
95
|
-
throw error;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* 验证构造函数参数
|
|
100
|
-
* @param map 地图实例
|
|
101
|
-
* @param options 配置选项
|
|
102
|
-
* @private
|
|
103
|
-
*/
|
|
104
|
-
validateConstructorParams(map, options) {
|
|
105
|
-
ValidationUtils.validateRequired(map, 'Map instance is required');
|
|
106
|
-
ValidationUtils.validateRequired(options, 'Options are required');
|
|
107
|
-
const { Template, lgtd, lttd } = options;
|
|
108
|
-
ValidationUtils.validateRequired(Template, 'Template is required in options');
|
|
109
|
-
if (typeof lgtd !== 'number' || typeof lttd !== 'number') {
|
|
110
|
-
throw new Error('Longitude and lttd must be numbers');
|
|
111
|
-
}
|
|
112
|
-
ValidationUtils.validateCoordinate(lgtd, lttd);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* 合并默认配置选项
|
|
116
|
-
* @param options 用户配置选项
|
|
117
|
-
* @returns 合并后的配置选项
|
|
118
|
-
* @private
|
|
119
|
-
*/
|
|
120
|
-
mergeDefaultOptions(options) {
|
|
121
|
-
return {
|
|
122
|
-
positioning: 'center-center',
|
|
123
|
-
stopEvent: false,
|
|
124
|
-
visible: true,
|
|
125
|
-
zIndex: 1,
|
|
126
|
-
...options
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* 生成唯一ID
|
|
131
|
-
* @returns 唯一标识符
|
|
132
|
-
* @private
|
|
133
|
-
*/
|
|
134
|
-
generateUniqueId() {
|
|
135
|
-
return `dom-point-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* 创建DOM元素
|
|
139
|
-
* @returns DOM元素
|
|
140
|
-
* @private
|
|
141
|
-
*/
|
|
142
|
-
createDomElement() {
|
|
143
|
-
const element = document.createElement('div');
|
|
144
|
-
element.id = this.id;
|
|
145
|
-
if (this.options.className) {
|
|
146
|
-
element.className = this.options.className;
|
|
147
|
-
}
|
|
148
|
-
if (this.options.zIndex) {
|
|
149
|
-
element.style.zIndex = this.options.zIndex.toString();
|
|
150
|
-
}
|
|
151
|
-
return element;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* 创建Vue应用实例
|
|
155
|
-
* @private
|
|
156
|
-
*/
|
|
157
|
-
createVueApp() {
|
|
158
|
-
const { Template, props } = this.options;
|
|
159
|
-
if (!Vue) {
|
|
160
|
-
throw new Error('Vue is not available. Please ensure Vue is installed in your project.');
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
if (isVue3) {
|
|
164
|
-
// Vue 3
|
|
165
|
-
this.app = Vue.createApp({
|
|
166
|
-
...Template,
|
|
167
|
-
props: props || {}
|
|
168
|
-
});
|
|
169
|
-
this.app.mount(this.dom);
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
// Vue 2
|
|
173
|
-
this.app = new Vue({
|
|
174
|
-
el: this.dom,
|
|
175
|
-
render: (h) => h(Template, { props: props || {} })
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
throw new Error(`Failed to create Vue app: ${error}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* 创建覆盖层
|
|
185
|
-
* @returns 覆盖层实例
|
|
186
|
-
* @private
|
|
187
|
-
*/
|
|
188
|
-
createOverlay() {
|
|
189
|
-
const overlay = new Overlay({
|
|
190
|
-
element: this.dom,
|
|
191
|
-
positioning: this.options.positioning || 'center-center',
|
|
192
|
-
stopEvent: this.options.stopEvent || false
|
|
193
|
-
});
|
|
194
|
-
overlay.setPosition(this.position);
|
|
195
|
-
return overlay;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* 错误处理
|
|
199
|
-
* @param message 错误消息
|
|
200
|
-
* @param error 原始错误
|
|
201
|
-
* @param context 错误上下文
|
|
202
|
-
* @private
|
|
203
|
-
*/
|
|
204
|
-
handleError(message, error, context) {
|
|
205
|
-
this.errorHandler.createAndHandleError(`${message}: ${error}`, ErrorType.COMPONENT_ERROR, { ...context, domPointId: this.id });
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* 设置可见性
|
|
209
|
-
* @param visible 是否可见
|
|
210
|
-
* @throws 当操作失败时抛出错误
|
|
211
|
-
*/
|
|
212
|
-
setVisible(visible) {
|
|
213
|
-
if (this.state === VueTemPointState.DESTROYED) {
|
|
214
|
-
throw new Error('Cannot set visibility on destroyed DOM point');
|
|
215
|
-
}
|
|
216
|
-
ValidationUtils.validateType(visible, 'boolean', 'Visible parameter must be a boolean');
|
|
217
|
-
try {
|
|
218
|
-
this.dom.style.visibility = visible ? 'visible' : 'hidden';
|
|
219
|
-
this.state = visible ? VueTemPointState.VISIBLE : VueTemPointState.HIDDEN;
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
this.handleError('Failed to set visibility', error, { visible });
|
|
223
|
-
throw error;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* 获取当前可见性状态
|
|
228
|
-
* @returns 是否可见
|
|
229
|
-
*/
|
|
230
|
-
isVisible() {
|
|
231
|
-
return this.state === VueTemPointState.VISIBLE;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* 更新位置
|
|
235
|
-
* @param lgtd 新经度
|
|
236
|
-
* @param lttd 新纬度
|
|
237
|
-
* @throws 当操作失败时抛出错误
|
|
238
|
-
*/
|
|
239
|
-
updatePosition(lgtd, lttd) {
|
|
240
|
-
if (this.state === VueTemPointState.DESTROYED) {
|
|
241
|
-
throw new Error('Cannot update position on destroyed DOM point');
|
|
242
|
-
}
|
|
243
|
-
ValidationUtils.validateCoordinate(lgtd, lttd);
|
|
244
|
-
try {
|
|
245
|
-
this.position = [lgtd, lttd];
|
|
246
|
-
this.anchor.setPosition(this.position);
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
this.handleError('Failed to update position', error, { lgtd, lttd });
|
|
250
|
-
throw error;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* 获取当前位置
|
|
255
|
-
* @returns 当前坐标位置
|
|
256
|
-
*/
|
|
257
|
-
getPosition() {
|
|
258
|
-
return [...this.position];
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* 更新组件属性
|
|
262
|
-
* @param newProps 新的属性对象
|
|
263
|
-
* @throws 当操作失败时抛出错误
|
|
264
|
-
*/
|
|
265
|
-
updateProps(newProps) {
|
|
266
|
-
if (this.state === VueTemPointState.DESTROYED) {
|
|
267
|
-
throw new Error('Cannot update props on destroyed DOM point');
|
|
268
|
-
}
|
|
269
|
-
try {
|
|
270
|
-
// 重新创建Vue应用实例
|
|
271
|
-
this.destroyVueApp();
|
|
272
|
-
this.options.props = { ...this.options.props, ...newProps };
|
|
273
|
-
this.createVueApp();
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
this.handleError('Failed to update props', error, { newProps });
|
|
277
|
-
throw error;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* 设置CSS样式
|
|
282
|
-
* @param styles 样式对象
|
|
283
|
-
* @throws 当操作失败时抛出错误
|
|
284
|
-
*/
|
|
285
|
-
setStyle(styles) {
|
|
286
|
-
if (this.state === VueTemPointState.DESTROYED) {
|
|
287
|
-
throw new Error('Cannot set style on destroyed DOM point');
|
|
288
|
-
}
|
|
289
|
-
try {
|
|
290
|
-
Object.assign(this.dom.style, styles);
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
this.handleError('Failed to set style', error, { styles });
|
|
294
|
-
throw error;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* 添加CSS类名
|
|
299
|
-
* @param className 要添加的类名
|
|
300
|
-
* @throws 当操作失败时抛出错误
|
|
301
|
-
*/
|
|
302
|
-
addClass(className) {
|
|
303
|
-
if (this.state === VueTemPointState.DESTROYED) {
|
|
304
|
-
throw new Error('Cannot add class to destroyed DOM point');
|
|
305
|
-
}
|
|
306
|
-
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
307
|
-
try {
|
|
308
|
-
this.dom.classList.add(className);
|
|
309
|
-
}
|
|
310
|
-
catch (error) {
|
|
311
|
-
this.handleError('Failed to add class', error, { className });
|
|
312
|
-
throw error;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* 移除CSS类名
|
|
317
|
-
* @param className 要移除的类名
|
|
318
|
-
* @throws 当操作失败时抛出错误
|
|
319
|
-
*/
|
|
320
|
-
removeClass(className) {
|
|
321
|
-
if (this.state === VueTemPointState.DESTROYED) {
|
|
322
|
-
throw new Error('Cannot remove class from destroyed DOM point');
|
|
323
|
-
}
|
|
324
|
-
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
325
|
-
try {
|
|
326
|
-
this.dom.classList.remove(className);
|
|
327
|
-
}
|
|
328
|
-
catch (error) {
|
|
329
|
-
this.handleError('Failed to remove class', error, { className });
|
|
330
|
-
throw error;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* 销毁Vue应用实例
|
|
335
|
-
* @private
|
|
336
|
-
*/
|
|
337
|
-
destroyVueApp() {
|
|
338
|
-
if (this.app) {
|
|
339
|
-
try {
|
|
340
|
-
if (isVue3) {
|
|
341
|
-
// Vue 3: 使用 unmount
|
|
342
|
-
this.app.unmount();
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
345
|
-
// Vue 2: 使用 $destroy
|
|
346
|
-
this.app.$destroy();
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
catch (error) {
|
|
350
|
-
this.handleError('Failed to destroy Vue app', error);
|
|
351
|
-
}
|
|
352
|
-
finally {
|
|
353
|
-
this.app = null;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* 移除点位
|
|
359
|
-
* @throws 当移除失败时抛出错误
|
|
360
|
-
*/
|
|
361
|
-
remove() {
|
|
362
|
-
if (this.state === VueTemPointState.DESTROYED) {
|
|
363
|
-
console.warn('DOM point already destroyed');
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
try {
|
|
367
|
-
// 销毁Vue应用实例
|
|
368
|
-
this.destroyVueApp();
|
|
369
|
-
// 从地图移除覆盖层
|
|
370
|
-
this.map.removeOverlay(this.anchor);
|
|
371
|
-
// 清理DOM元素
|
|
372
|
-
if (this.dom && this.dom.parentNode) {
|
|
373
|
-
this.dom.parentNode.removeChild(this.dom);
|
|
374
|
-
}
|
|
375
|
-
// 更新状态
|
|
376
|
-
this.state = VueTemPointState.DESTROYED;
|
|
377
|
-
}
|
|
378
|
-
catch (error) {
|
|
379
|
-
this.handleError('Failed to remove DOM point', error);
|
|
380
|
-
throw error;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* 获取覆盖层
|
|
385
|
-
* @returns 覆盖层实例
|
|
386
|
-
*/
|
|
387
|
-
getOverlay() {
|
|
388
|
-
return this.anchor;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* 获取点位ID
|
|
392
|
-
* @returns 点位唯一标识符
|
|
393
|
-
*/
|
|
394
|
-
getId() {
|
|
395
|
-
return this.id;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* 获取DOM元素
|
|
399
|
-
* @returns DOM元素
|
|
400
|
-
*/
|
|
401
|
-
getDomElement() {
|
|
402
|
-
return this.dom;
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* 获取当前状态
|
|
406
|
-
* @returns 当前状态
|
|
407
|
-
*/
|
|
408
|
-
getState() {
|
|
409
|
-
return this.state;
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* 获取配置选项
|
|
413
|
-
* @returns 配置选项的副本
|
|
414
|
-
*/
|
|
415
|
-
getOptions() {
|
|
416
|
-
return Object.freeze({ ...this.options });
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* 检查是否已销毁
|
|
420
|
-
* @returns 是否已销毁
|
|
421
|
-
*/
|
|
422
|
-
isDestroyed() {
|
|
423
|
-
return this.state === VueTemPointState.DESTROYED;
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
* 获取地图实例
|
|
427
|
-
* @returns 地图实例
|
|
428
|
-
*/
|
|
429
|
-
getMap() {
|
|
430
|
-
return this.map;
|
|
431
|
-
}
|
|
432
|
-
}
|