@hzab/map-combine 0.1.0 → 0.1.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/CHANGELOG.md +1 -0
- package/package.json +1 -1
- package/src/basic/BasicBusiness.ts +72 -0
- package/src/basic/BasicElement.ts +35 -0
- package/src/basic/BasicMarker.ts +45 -0
- package/src/basic/MapCombine.ts +11 -1
- package/src/basic/ReactPopup.tsx +24 -1
- package/src/openlayer/OpenlayerMap.ts +82 -27
- package/src/openlayer/openlayer-tile-gcj02-wgs84.js +144 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { setValue } from "../utils";
|
|
2
|
+
// import { type BasicElementOption, type BasicElement } from "./BasicElement";
|
|
3
|
+
import { MapCombine } from "./MapCombine";
|
|
4
|
+
|
|
5
|
+
export interface BasicBusinessOption {
|
|
6
|
+
/** 组件名,唯一标识 */
|
|
7
|
+
name: string;
|
|
8
|
+
/** 组件是否显示 */
|
|
9
|
+
show: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export abstract class BasicBusiness<T extends BasicBusinessOption> {
|
|
13
|
+
protected readonly _option: T;
|
|
14
|
+
protected readonly _map: MapCombine;
|
|
15
|
+
protected _elements = [];
|
|
16
|
+
/** 唯一标识 */
|
|
17
|
+
get name() {
|
|
18
|
+
return this._option.name;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** 是否显示 */
|
|
22
|
+
get show() {
|
|
23
|
+
return this._option.show;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
set show(val) {
|
|
27
|
+
setValue(this._option, "show", val, () => {
|
|
28
|
+
this._elements.forEach((e) => {
|
|
29
|
+
e?.update({
|
|
30
|
+
show: val,
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
constructor(map: MapCombine, option: T) {
|
|
37
|
+
this._map = map;
|
|
38
|
+
this._option = option;
|
|
39
|
+
// const oldElement = map.bussinesses.get(this.name);
|
|
40
|
+
// if (oldElement) {
|
|
41
|
+
// oldElement.destroy();
|
|
42
|
+
// }
|
|
43
|
+
// map.bussinesses.set(this.name, this);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** 地图展示时触发一次 */
|
|
47
|
+
onMapLoaded?(): void;
|
|
48
|
+
/** 每一帧触发一次 */
|
|
49
|
+
onFrame?(): void;
|
|
50
|
+
/** 视图变化先触发一次 */
|
|
51
|
+
onBeforeViewChange?(): void;
|
|
52
|
+
/** 视图变化时连续触发 */
|
|
53
|
+
onViewChange?(): void;
|
|
54
|
+
/** 视图变化后触发一次 */
|
|
55
|
+
onAfterViewChange?(): void;
|
|
56
|
+
/** 鼠标在地图上移动时触发 */
|
|
57
|
+
onMouseMove?(): void;
|
|
58
|
+
/** 鼠标在地图上单击左键 */
|
|
59
|
+
onMouseLClick?(): void;
|
|
60
|
+
/** 鼠标在地图上单击右键 */
|
|
61
|
+
onMouseRClick?(): void;
|
|
62
|
+
|
|
63
|
+
/** 销毁组件 */
|
|
64
|
+
destroy() {
|
|
65
|
+
this._map.bussinesses.delete(this.name);
|
|
66
|
+
if (this._map.isAlive) {
|
|
67
|
+
this._elements.forEach((e) => e?.destroy());
|
|
68
|
+
this.onDestroy?.();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
onDestroy?(): void;
|
|
72
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface BasicElementOption {
|
|
2
|
+
/** 是否显示 */
|
|
3
|
+
show: boolean
|
|
4
|
+
/** 鼠标样式 */
|
|
5
|
+
cursor: string
|
|
6
|
+
/** 元素是否静默(不触发鼠标事件) */
|
|
7
|
+
silent: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export abstract class BasicElement<T extends BasicElementOption> {
|
|
11
|
+
option: T
|
|
12
|
+
constructor(option: T) {
|
|
13
|
+
this.option = option
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
update(option: Partial<T>) {
|
|
17
|
+
Object.assign(this.option, option)
|
|
18
|
+
this._onUpdate(option)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
protected abstract _onUpdate(option: Partial<T>): void
|
|
22
|
+
|
|
23
|
+
/** 鼠标进入回调 */
|
|
24
|
+
onMouseIn?(): void
|
|
25
|
+
/** 鼠标离开回调 */
|
|
26
|
+
onMouseOut?(): void
|
|
27
|
+
/** 鼠标移动回调 */
|
|
28
|
+
onMouseMove?(): void
|
|
29
|
+
/** 鼠标点击回调 */
|
|
30
|
+
onClick?(): void
|
|
31
|
+
/** 鼠标右键点击回调 */
|
|
32
|
+
onRClick?(): void
|
|
33
|
+
/** 销毁元素 */
|
|
34
|
+
abstract destroy(): void
|
|
35
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BasicElement, type BasicElementOption } from './BasicElement'
|
|
2
|
+
|
|
3
|
+
export interface BasicMarkerOption extends BasicElementOption {
|
|
4
|
+
/** 经度 */
|
|
5
|
+
lon: number
|
|
6
|
+
/** 纬度 */
|
|
7
|
+
lat: number
|
|
8
|
+
/** 海拔 */
|
|
9
|
+
alt: number
|
|
10
|
+
/** 图标 */
|
|
11
|
+
icon?: string
|
|
12
|
+
/** 宽度 */
|
|
13
|
+
width: number
|
|
14
|
+
/** 高度 */
|
|
15
|
+
height: number
|
|
16
|
+
/** 横向偏移 */
|
|
17
|
+
x: number
|
|
18
|
+
/** 纵向偏移 */
|
|
19
|
+
y: number
|
|
20
|
+
/** 旋转角度 */
|
|
21
|
+
rotation: number
|
|
22
|
+
img?: HTMLCanvasElement | HTMLImageElement
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export abstract class BasicMarker extends BasicElement<BasicMarkerOption> {
|
|
26
|
+
constructor(option: Partial<BasicMarkerOption> = {}) {
|
|
27
|
+
super(Object.assign({
|
|
28
|
+
show: true,
|
|
29
|
+
cursor: 'pointer',
|
|
30
|
+
silent: false,
|
|
31
|
+
lon: 120,
|
|
32
|
+
lat: 30,
|
|
33
|
+
alt: 0,
|
|
34
|
+
width: 64,
|
|
35
|
+
height: 64,
|
|
36
|
+
x: 0,
|
|
37
|
+
y: -32,
|
|
38
|
+
rotation: 0,
|
|
39
|
+
icon: BasicMarker.defualtIcon,
|
|
40
|
+
}, option))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** 默认图标 */
|
|
44
|
+
static defualtIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA7NJREFUeF7lmwlu3DAMRZ2TtbmNbtHmFr5Nk5O1YCAHiobL5yK5wAwQZPEmPn5+0bLzcjz55+XJ4z+2AWit/TyOg75+DNDp9+vz3n/4oO/nef7ekZylAHrQv3rgkXgIysdKGEsAFATOwXpbAaIUwKLAZxilIMoAtNaoZknu3g/JfPQC9PgSEGkAjqxToG9XdOd5Xqb3FfBglPQ3BGYaQgpAH/AfI2UU9DsXsJXqAYgGIwUhDAAIPjWwEU4vL00VBPjVAsptzwD4K1zwU+qRjFsBGD4TAh4C0Foj2XPGFRqEFfikBrquVHbu67sBKFlwX9wT+LyvkoRXj/pcAP6X4AmG4kEuP/AC4KTvuiAjZ+r7H6ZERB0KBFgFMAAp++d5es5B9XtNaZyHuHt/YVxwUjyD51wfrntnpwift5cDp0zoHBCAbPYVw7KUDgUhlAKkggwAdHDRe4QLDlTPAmTzWBTAg/yR2jdkPy6A0CKJeEMEXovrD/IABHmh2ed8Q+wUFWCmnKNlYCpAGJQJIOobCgQzm1wZWOoJAbBOmnXmaD0L8FRwCICHKQYEMMvflPHletGyE44rB2AGEg1g6hLdAFcBqBqI6RsGAGqZVcVGwCMlUAXAVE62BLr3zONVwSMAZg+AAmmthXqHHgTXPJkKWqWAqAmG+3MO3nEcyDTIgSs3QUoSMhhp5UbMpLbCbNW/pBzrOKQEQi2m0gvQpm8rxcDqryl/of5N4zQBCCdGfUBbv7PuBK/taPAh30ABcPVsloFiaGjwZgaHmcNd/3QsCoDLJKSCBAT4/BmVQgCUeoZUYGSJU0PFeaHS8QBIqWDq8q6XH8aXJT6fG3oXSKN3ndd4YABVKoCLH9xRuHOEsg97gNGiwkYFxgTvFl2rGC/gUoCiApdhwREaO0Y7xhQAqeFAusOqwJVEwNIPeQDg5i73jgLJGl9aAXeWQvXzSbcHTNNZ6mlRRAFC3bulnyoBa1boL0iUv+goTHkpA04pwGhzS/0gs1yuKS0NYIcfVNd9iQnOVIXaTMnTUFi47lcBcK8AWSaovABREry7FQYGLD0JDg14laqWKABoklwQql6CspJWYoKMH6SUsCv48hKYmqTQu4S730FcooChHFwQVk53UiksBaD0CLTpmyfcEfzSEgDa5S8IdwW/BUBXgfZ8QPqHCdesYbn9bSUAKmEe35bgtynACWFb8NsBAOWwNfhbACgQtgd/GwCmT7gl+NsBXGrwPg2KOj533PJGqHKwK8719AD+Aby+uV/6QmnsAAAAAElFTkSuQmCC'
|
|
45
|
+
}
|
package/src/basic/MapCombine.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { Polygon, PolygonOption } from "./Polygon";
|
|
|
6
6
|
import { Polyline, PolylineOption } from "./Polyline";
|
|
7
7
|
import { ReactPoint, ReactPointOption, drawReactPoint } from "./ReactPoint";
|
|
8
8
|
import { Tile3D, Tile3DOption } from "./Tile3D";
|
|
9
|
+
import { type BasicBusiness, type BasicBusinessOption } from "./BasicBusiness";
|
|
10
|
+
|
|
9
11
|
export abstract class MapCombine {
|
|
10
12
|
/* 用于挂载html元素的根节点 */
|
|
11
13
|
readonly htmllayer = document.createElement("div");
|
|
@@ -24,6 +26,10 @@ export abstract class MapCombine {
|
|
|
24
26
|
abstract get zoom(): number
|
|
25
27
|
abstract set zoom(val)
|
|
26
28
|
|
|
29
|
+
bussinesses = new Map<string, BasicBusiness<BasicBusinessOption>>();
|
|
30
|
+
|
|
31
|
+
/** 地图是否存在 */
|
|
32
|
+
isAlive = true;
|
|
27
33
|
constructor() {
|
|
28
34
|
const { htmllayer } = this
|
|
29
35
|
htmllayer.style.zIndex = "1000";
|
|
@@ -33,7 +39,10 @@ export abstract class MapCombine {
|
|
|
33
39
|
htmllayer.style.left = "0";
|
|
34
40
|
htmllayer.style.top = "0";
|
|
35
41
|
this.menu = new ContextMenu(this);
|
|
36
|
-
(window as any).map = this
|
|
42
|
+
(window as any).map = this;
|
|
43
|
+
setTimeout(() => {
|
|
44
|
+
this.bussinesses.forEach((e) => e.show && e.onMapLoaded?.());
|
|
45
|
+
}, 100);
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
createReactPoint<K>(option?: Partial<ReactPointOption<K>>): ReactPoint<K> {
|
|
@@ -61,6 +70,7 @@ export abstract class MapCombine {
|
|
|
61
70
|
abstract geographyTcanvas(p: number[]): number[]
|
|
62
71
|
|
|
63
72
|
destroy() {
|
|
73
|
+
this.isAlive = false;
|
|
64
74
|
this.htmllayer.remove()
|
|
65
75
|
this.event.trigger('destroy')
|
|
66
76
|
}
|
package/src/basic/ReactPopup.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactElement } from "react";
|
|
2
2
|
import ReactDOM from "react-dom";
|
|
3
|
+
import { MapCombine } from "./MapCombine";
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
export interface ReactPopupOption {
|
|
@@ -7,16 +8,22 @@ export interface ReactPopupOption {
|
|
|
7
8
|
element: ReactElement;
|
|
8
9
|
/** 层高 */
|
|
9
10
|
zIndex?: number;
|
|
11
|
+
show?: boolean;
|
|
12
|
+
name?: string
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
export class ReactPopup {
|
|
13
16
|
private dom: HTMLDivElement;
|
|
14
17
|
option: ReactPopupOption;
|
|
15
18
|
node: HTMLDivElement;
|
|
19
|
+
map: MapCombine;
|
|
16
20
|
constructor(map, option: ReactPopupOption = {
|
|
17
21
|
element: <></>,
|
|
18
|
-
zIndex: 10
|
|
22
|
+
zIndex: 10,
|
|
23
|
+
show: true,
|
|
24
|
+
name: "bubble"
|
|
19
25
|
}) {
|
|
26
|
+
this.map = map;
|
|
20
27
|
this.dom = document.createElement("div");
|
|
21
28
|
this.option = option;
|
|
22
29
|
const coordinate = map.geographyTcanvas(map.event.geography)
|
|
@@ -27,6 +34,22 @@ export class ReactPopup {
|
|
|
27
34
|
ReactDOM.render(option.element ?? <></>, this.dom);
|
|
28
35
|
}
|
|
29
36
|
|
|
37
|
+
get show(): boolean {
|
|
38
|
+
return this.option.show;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
set show(val: boolean) {
|
|
42
|
+
if (val !== this.show) {
|
|
43
|
+
this.option.show = val;
|
|
44
|
+
this.dom.style.display = val ? "" : "none";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
showAt(lon, lat) {
|
|
48
|
+
const coordinate = this.map.geographyTcanvas([lon, lat, 0])
|
|
49
|
+
this.dom.style.position = "absolute";
|
|
50
|
+
this.dom.style.top = coordinate[1] + "px";
|
|
51
|
+
this.dom.style.left = coordinate[0] + "px";
|
|
52
|
+
}
|
|
30
53
|
destroy() {
|
|
31
54
|
this.dom.remove();
|
|
32
55
|
ReactDOM.unmountComponentAtNode(this.dom);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { MapCombine } from "../basic/MapCombine";
|
|
2
2
|
import { PointOption, Point } from "../basic/Point";
|
|
3
3
|
import Map from "ol/Map.js";
|
|
4
|
+
import View from "ol/View";
|
|
5
|
+
import XYZ from "ol/source/XYZ";
|
|
6
|
+
import Tile from "ol/layer/Tile";
|
|
4
7
|
import DragPan from "ol/interaction/DragPan";
|
|
5
8
|
import { Projection } from "../utils/Projection";
|
|
6
9
|
import VectorSource from "ol/source/Vector";
|
|
@@ -15,19 +18,32 @@ import { drawPoint } from "./OpenlayerPoint";
|
|
|
15
18
|
import { drawPolyline } from "./OpenlayerPolyline";
|
|
16
19
|
import { drawPolygon } from "./OpenlayerPolygon";
|
|
17
20
|
import { Tile3DOption, Tile3D } from "../basic/Tile3D";
|
|
21
|
+
import { gcjMecator } from "./openlayer-tile-gcj02-wgs84";
|
|
22
|
+
|
|
23
|
+
export interface IOpenlayerOption {
|
|
24
|
+
container;
|
|
25
|
+
url: string | string[];
|
|
26
|
+
center?: number[];
|
|
27
|
+
zoom?: number;
|
|
28
|
+
maxZoom?: number;
|
|
29
|
+
minZoom?: number;
|
|
30
|
+
/** 地图瓦片转换规则 GCJ02 转 WGS84 */
|
|
31
|
+
proj?: "GCJ02->WGS84";
|
|
32
|
+
}
|
|
18
33
|
|
|
19
34
|
export class OpenlayerMap extends MapCombine {
|
|
20
35
|
viewer: Map;
|
|
21
36
|
container: HTMLDivElement;
|
|
22
37
|
dragPan: DragPan;
|
|
23
|
-
vectors: VectorSource
|
|
38
|
+
vectors: VectorSource;
|
|
39
|
+
option: IOpenlayerOption;
|
|
24
40
|
offset: number[];
|
|
25
41
|
fov = 0.9272952180016121;
|
|
26
42
|
get cursor(): string {
|
|
27
|
-
return
|
|
43
|
+
return this.container.style.cursor;
|
|
28
44
|
}
|
|
29
45
|
set cursor(val: string) {
|
|
30
|
-
|
|
46
|
+
this.container.style.cursor = val;
|
|
31
47
|
}
|
|
32
48
|
get moveable(): boolean {
|
|
33
49
|
return this.dragPan.getActive();
|
|
@@ -36,8 +52,8 @@ export class OpenlayerMap extends MapCombine {
|
|
|
36
52
|
this.dragPan.setActive(val);
|
|
37
53
|
}
|
|
38
54
|
get center(): number[] {
|
|
39
|
-
const center = this.viewer.getView().getCenter()
|
|
40
|
-
return [Projection.xToLon(center[0]), Projection.yToLat(center[1]), 0]
|
|
55
|
+
const center = this.viewer.getView().getCenter()!;
|
|
56
|
+
return [Projection.xToLon(center[0]), Projection.yToLat(center[1]), 0];
|
|
41
57
|
}
|
|
42
58
|
set center(val: number[]) {
|
|
43
59
|
const { viewer } = this;
|
|
@@ -45,19 +61,59 @@ export class OpenlayerMap extends MapCombine {
|
|
|
45
61
|
view.setCenter([Projection.lonToX(val[0]), Projection.latToY(val[1])]);
|
|
46
62
|
}
|
|
47
63
|
get zoom(): number {
|
|
48
|
-
return this.viewer.getView().getZoom()
|
|
64
|
+
return this.viewer.getView().getZoom();
|
|
49
65
|
}
|
|
50
66
|
set zoom(val: number) {
|
|
51
67
|
this.viewer.getView().setZoom(val);
|
|
52
68
|
}
|
|
53
69
|
|
|
54
|
-
constructor(viewer
|
|
55
|
-
super()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
constructor(viewer?: Map) {
|
|
71
|
+
super();
|
|
72
|
+
viewer && this._initParamsEvent(viewer);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
init(opt: IOpenlayerOption) {
|
|
76
|
+
this.option = opt;
|
|
77
|
+
const { container, center = [120.2288892, 30.2349677, 0], zoom = 13, url, maxZoom, minZoom, proj } = opt || {};
|
|
78
|
+
|
|
79
|
+
const viewer = new Map({
|
|
80
|
+
target: container,
|
|
81
|
+
controls: [],
|
|
82
|
+
view: new View({
|
|
83
|
+
projection: "EPSG:3857",
|
|
84
|
+
center: fromLonLat(center),
|
|
85
|
+
zoom: zoom,
|
|
86
|
+
maxZoom: maxZoom ?? 18,
|
|
87
|
+
minZoom: minZoom ?? 3,
|
|
88
|
+
}),
|
|
89
|
+
layers: [
|
|
90
|
+
new Tile({
|
|
91
|
+
visible: true,
|
|
92
|
+
source: new XYZ({
|
|
93
|
+
projection: proj === "GCJ02->WGS84" ? gcjMecator : undefined,
|
|
94
|
+
urls: Array.isArray(url) ? url : [url],
|
|
95
|
+
crossOrigin: "anonymous",
|
|
96
|
+
}),
|
|
97
|
+
}),
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
this._initParamsEvent(viewer);
|
|
102
|
+
|
|
103
|
+
return new OpenlayerMap(viewer);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private _initParamsEvent(viewer) {
|
|
107
|
+
if (!viewer) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.viewer = viewer;
|
|
111
|
+
this.container = viewer.getViewport() as HTMLDivElement;
|
|
112
|
+
this.container.appendChild(this.htmllayer);
|
|
113
|
+
this.cursor = "default";
|
|
114
|
+
|
|
59
115
|
const { center } = this;
|
|
60
|
-
this.offset = fromLonLat(center)
|
|
116
|
+
this.offset = fromLonLat(center);
|
|
61
117
|
|
|
62
118
|
this.vectors = new VectorSource();
|
|
63
119
|
this.viewer.addLayer(
|
|
@@ -71,29 +127,29 @@ export class OpenlayerMap extends MapCombine {
|
|
|
71
127
|
.getArray()
|
|
72
128
|
.find((interaction) => {
|
|
73
129
|
if (interaction instanceof DoubleClickZoom) {
|
|
74
|
-
interaction.setActive(false)
|
|
130
|
+
interaction.setActive(false);
|
|
75
131
|
}
|
|
76
132
|
return interaction instanceof DragPan;
|
|
77
133
|
}) as DragPan;
|
|
78
134
|
|
|
79
|
-
bindEvent(this)
|
|
135
|
+
bindEvent(this);
|
|
80
136
|
}
|
|
81
137
|
|
|
82
138
|
createPoint<K>(option?: Partial<PointOption<K>>): Point<K> {
|
|
83
|
-
const e = new Point(this, option)
|
|
84
|
-
drawPoint(this, e)
|
|
85
|
-
return e
|
|
139
|
+
const e = new Point(this, option);
|
|
140
|
+
drawPoint(this, e);
|
|
141
|
+
return e;
|
|
86
142
|
}
|
|
87
143
|
|
|
88
144
|
createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K> {
|
|
89
|
-
const e = new Polyline(this, option)
|
|
90
|
-
drawPolyline(this, e)
|
|
91
|
-
return e
|
|
145
|
+
const e = new Polyline(this, option);
|
|
146
|
+
drawPolyline(this, e);
|
|
147
|
+
return e;
|
|
92
148
|
}
|
|
93
149
|
createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K> {
|
|
94
|
-
const e = new Polygon(this, option)
|
|
95
|
-
drawPolygon(this, e)
|
|
96
|
-
return e
|
|
150
|
+
const e = new Polygon(this, option);
|
|
151
|
+
drawPolygon(this, e);
|
|
152
|
+
return e;
|
|
97
153
|
}
|
|
98
154
|
|
|
99
155
|
// protected _onFrame(): void {
|
|
@@ -116,9 +172,8 @@ export class OpenlayerMap extends MapCombine {
|
|
|
116
172
|
if (pixel) {
|
|
117
173
|
return [pixel[0], pixel[1]];
|
|
118
174
|
} else {
|
|
119
|
-
return [0, 0]
|
|
175
|
+
return [0, 0];
|
|
120
176
|
}
|
|
121
|
-
|
|
122
177
|
}
|
|
123
178
|
spaceTgeography(p: number[]): number[] {
|
|
124
179
|
const { offset } = this;
|
|
@@ -144,6 +199,6 @@ export class OpenlayerMap extends MapCombine {
|
|
|
144
199
|
}
|
|
145
200
|
|
|
146
201
|
_onDestroy() {
|
|
147
|
-
this.viewer.dispose()
|
|
202
|
+
this.viewer.dispose();
|
|
148
203
|
}
|
|
149
|
-
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Projection, addProjection, addCoordinateTransforms } from "ol/proj";
|
|
2
|
+
|
|
3
|
+
let projzh = {};
|
|
4
|
+
projzh.ll2gmerc = function (input, opt_output, opt_dimension) {
|
|
5
|
+
let output = gcj02.fromWGS84(input, opt_output, opt_dimension);
|
|
6
|
+
return projzh.ll2smerc(output, output, opt_dimension);
|
|
7
|
+
};
|
|
8
|
+
projzh.gmerc2ll = function (input, opt_output, opt_dimension) {
|
|
9
|
+
let output = projzh.smerc2ll(input, input, opt_dimension);
|
|
10
|
+
return gcj02.toWGS84(output, opt_output, opt_dimension);
|
|
11
|
+
};
|
|
12
|
+
projzh.smerc2gmerc = function (input, opt_output, opt_dimension) {
|
|
13
|
+
let output = projzh.smerc2ll(input, input, opt_dimension);
|
|
14
|
+
output = gcj02.fromWGS84(output, output, opt_dimension);
|
|
15
|
+
return projzh.ll2smerc(output, output, opt_dimension);
|
|
16
|
+
};
|
|
17
|
+
projzh.gmerc2smerc = function (input, opt_output, opt_dimension) {
|
|
18
|
+
let output = projzh.smerc2ll(input, input, opt_dimension);
|
|
19
|
+
output = gcj02.toWGS84(output, output, opt_dimension);
|
|
20
|
+
return projzh.ll2smerc(output, output, opt_dimension);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function forEachPoint(func) {
|
|
24
|
+
return function (input, opt_output, opt_dimension) {
|
|
25
|
+
const len = input.length;
|
|
26
|
+
const dimension = opt_dimension ? opt_dimension : 2;
|
|
27
|
+
let output;
|
|
28
|
+
if (opt_output) {
|
|
29
|
+
output = opt_output;
|
|
30
|
+
} else {
|
|
31
|
+
if (dimension !== 2) {
|
|
32
|
+
output = input.slice();
|
|
33
|
+
} else {
|
|
34
|
+
output = new Array(len);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (let offset = 0; offset < len; offset += dimension) {
|
|
38
|
+
func(input, output, offset);
|
|
39
|
+
}
|
|
40
|
+
return output;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let RADIUS = 6378137;
|
|
45
|
+
let MAX_LATITUDE = 85.0511287798;
|
|
46
|
+
let RAD_PER_DEG = Math.PI / 180;
|
|
47
|
+
|
|
48
|
+
let sphericalMercator = {};
|
|
49
|
+
sphericalMercator.forward = forEachPoint(function (input, output, offset) {
|
|
50
|
+
let lat = Math.max(Math.min(MAX_LATITUDE, input[offset + 1]), -MAX_LATITUDE);
|
|
51
|
+
let sin = Math.sin(lat * RAD_PER_DEG);
|
|
52
|
+
|
|
53
|
+
output[offset] = RADIUS * input[offset] * RAD_PER_DEG;
|
|
54
|
+
output[offset + 1] = (RADIUS * Math.log((1 + sin) / (1 - sin))) / 2;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
sphericalMercator.inverse = forEachPoint(function (input, output, offset) {
|
|
58
|
+
output[offset] = input[offset] / RADIUS / RAD_PER_DEG;
|
|
59
|
+
output[offset + 1] = (2 * Math.atan(Math.exp(input[offset + 1] / RADIUS)) - Math.PI / 2) / RAD_PER_DEG;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
projzh.ll2smerc = sphericalMercator.forward;
|
|
63
|
+
projzh.smerc2ll = sphericalMercator.inverse;
|
|
64
|
+
|
|
65
|
+
const gcj02 = {};
|
|
66
|
+
const PI = Math.PI;
|
|
67
|
+
const AXIS = 6378245.0;
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
|
|
69
|
+
const OFFSET = 0.00669342162296594323; // (a^2 - b^2) / a^2
|
|
70
|
+
|
|
71
|
+
function delta(wgLon, wgLat) {
|
|
72
|
+
let dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
|
|
73
|
+
let dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
|
|
74
|
+
const radLat = (wgLat / 180.0) * PI;
|
|
75
|
+
let magic = Math.sin(radLat);
|
|
76
|
+
magic = 1 - OFFSET * magic * magic;
|
|
77
|
+
const sqrtMagic = Math.sqrt(magic);
|
|
78
|
+
dLat = (dLat * 180.0) / (((AXIS * (1 - OFFSET)) / (magic * sqrtMagic)) * PI);
|
|
79
|
+
dLon = (dLon * 180.0) / ((AXIS / sqrtMagic) * Math.cos(radLat) * PI);
|
|
80
|
+
return [dLon, dLat];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function outOfChina(lon, lat) {
|
|
84
|
+
if (lon < 72.004 || lon > 137.8347) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (lat < 0.8293 || lat > 55.8271) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function transformLat(x, y) {
|
|
94
|
+
let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
95
|
+
ret += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
|
|
96
|
+
ret += ((20.0 * Math.sin(y * PI) + 40.0 * Math.sin((y / 3.0) * PI)) * 2.0) / 3.0;
|
|
97
|
+
ret += ((160.0 * Math.sin((y / 12.0) * PI) + 320 * Math.sin((y * PI) / 30.0)) * 2.0) / 3.0;
|
|
98
|
+
return ret;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function transformLon(x, y) {
|
|
102
|
+
let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
103
|
+
ret += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
|
|
104
|
+
ret += ((20.0 * Math.sin(x * PI) + 40.0 * Math.sin((x / 3.0) * PI)) * 2.0) / 3.0;
|
|
105
|
+
ret += ((150.0 * Math.sin((x / 12.0) * PI) + 300.0 * Math.sin((x / 30.0) * PI)) * 2.0) / 3.0;
|
|
106
|
+
return ret;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
gcj02.toWGS84 = forEachPoint(function (input, output, offset) {
|
|
110
|
+
let lng = input[offset];
|
|
111
|
+
let lat = input[offset + 1];
|
|
112
|
+
if (!outOfChina(lng, lat)) {
|
|
113
|
+
let deltaD = delta(lng, lat);
|
|
114
|
+
lng = lng - deltaD[0];
|
|
115
|
+
lat = lat - deltaD[1];
|
|
116
|
+
}
|
|
117
|
+
output[offset] = lng;
|
|
118
|
+
output[offset + 1] = lat;
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
gcj02.fromWGS84 = forEachPoint(function (input, output, offset) {
|
|
122
|
+
let lng = input[offset];
|
|
123
|
+
let lat = input[offset + 1];
|
|
124
|
+
if (!outOfChina(lng, lat)) {
|
|
125
|
+
let deltaD = delta(lng, lat);
|
|
126
|
+
lng = lng + deltaD[0];
|
|
127
|
+
lat = lat + deltaD[1];
|
|
128
|
+
}
|
|
129
|
+
output[offset] = lng;
|
|
130
|
+
output[offset + 1] = lat;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const gcj02Extent = [-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244];
|
|
134
|
+
const gcjMecator = new Projection({
|
|
135
|
+
code: "GCJ-02",
|
|
136
|
+
extent: gcj02Extent,
|
|
137
|
+
units: "m",
|
|
138
|
+
});
|
|
139
|
+
addProjection(gcjMecator);
|
|
140
|
+
|
|
141
|
+
addCoordinateTransforms("EPSG:4326", gcjMecator, projzh.ll2gmerc, projzh.gmerc2ll);
|
|
142
|
+
addCoordinateTransforms("EPSG:3857", gcjMecator, projzh.smerc2gmerc, projzh.gmerc2smerc);
|
|
143
|
+
|
|
144
|
+
export { gcjMecator };
|