@cn-map/gaode-extra-shared 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +76 -2
- package/dist/index.d.ts +68 -0
- package/dist/index.js +116 -0
- package/package.json +59 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-present Jungzl.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,77 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @cn-map/gaode-extra-shared
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
高德地图 Three.js 扩展包(`@cn-map/gaode-*-extra`)共用的底层工具。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @cn-map/gaode-extra-shared
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
yarn add @cn-map/gaode-extra-shared
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @cn-map/gaode-extra-shared
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bun add @cn-map/gaode-extra-shared
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 模块
|
|
24
|
+
|
|
25
|
+
### Canvas 占用
|
|
26
|
+
|
|
27
|
+
同一张地图的 GL canvas 只允许一个 3D 图层占用,避免多个 Three.js 渲染器争用同一 WebGL 上下文。
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { releaseCanvas, tryAcquireCanvas } from '@cn-map/gaode-extra-shared'
|
|
31
|
+
|
|
32
|
+
const owner = Symbol('layer')
|
|
33
|
+
|
|
34
|
+
if (tryAcquireCanvas(map.getGL().canvas, owner)) {
|
|
35
|
+
// 挂载渲染器
|
|
36
|
+
releaseCanvas(map.getGL().canvas, owner)
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 地图坐标转换
|
|
41
|
+
|
|
42
|
+
把经纬度转换为 Three.js 场景坐标,转换使用的 origin 与图层相机保持一致。
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { createMapCoordinates } from '@cn-map/gaode-extra-shared'
|
|
46
|
+
|
|
47
|
+
const coordinates = createMapCoordinates(map, map.getCenter())
|
|
48
|
+
|
|
49
|
+
const position = coordinates.lngLatToScene([120.1, 30.1], 12)
|
|
50
|
+
const positions = coordinates.lngLatsToScene([
|
|
51
|
+
[120.1, 30.1],
|
|
52
|
+
[120.2, 30.2, 20],
|
|
53
|
+
])
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 相机同步
|
|
57
|
+
|
|
58
|
+
把 AMap 当前帧的相机参数同步到 Three.js 相机。`2D` 视图必须使用 `OrthographicCamera`,`3D` 视图必须使用 `PerspectiveCamera`;类型不匹配时不写入参数,由调用方决定如何提示。
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { syncMapCamera } from '@cn-map/gaode-extra-shared'
|
|
62
|
+
|
|
63
|
+
const result = syncMapCamera({
|
|
64
|
+
map,
|
|
65
|
+
camera: activeCamera,
|
|
66
|
+
viewMode: '2D',
|
|
67
|
+
origin: map.getCenter(),
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
if (!result.synced) {
|
|
71
|
+
console.warn(`${result.viewMode} view requires a ${result.expected}`)
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 许可证
|
|
76
|
+
|
|
77
|
+
[MIT](https://github.com/Jungzl/amap/blob/main/LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Camera, OrthographicCamera, PerspectiveCamera } from "three";
|
|
2
|
+
/**
|
|
3
|
+
* 尝试占用一个共享 canvas(通常是一个 map 的 GL canvas)。
|
|
4
|
+
* 同一 canvas 只允许一个 3D 图层占用;同一 owner 可以重复占用(例如 HMR)。
|
|
5
|
+
*/
|
|
6
|
+
export declare function tryAcquireCanvas(canvas: object, owner: symbol): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* 释放 canvas 占用;只有当前 owner 才能释放,避免误删其他图层的占用。
|
|
9
|
+
*/
|
|
10
|
+
export declare function releaseCanvas(canvas: object, owner: symbol): void;
|
|
11
|
+
export declare function getCanvasOwner(canvas: object): symbol | undefined;
|
|
12
|
+
export declare function isPerspectiveCamera(camera: Camera): camera is PerspectiveCamera;
|
|
13
|
+
export declare function isOrthographicCamera(camera: Camera): camera is OrthographicCamera;
|
|
14
|
+
type MapCameraSyncResult = {
|
|
15
|
+
synced: true;
|
|
16
|
+
} | {
|
|
17
|
+
synced: false;
|
|
18
|
+
viewMode: AMap.ViewMode;
|
|
19
|
+
expected: "PerspectiveCamera" | "OrthographicCamera";
|
|
20
|
+
};
|
|
21
|
+
interface SyncMapCameraOptions {
|
|
22
|
+
map: AMap.Map;
|
|
23
|
+
camera: Camera;
|
|
24
|
+
viewMode: AMap.ViewMode;
|
|
25
|
+
/**
|
|
26
|
+
* 图层坐标原点。
|
|
27
|
+
*/
|
|
28
|
+
origin: AMap.LngLatLike;
|
|
29
|
+
/**
|
|
30
|
+
* 默认使用 `map.customCoords`。
|
|
31
|
+
*/
|
|
32
|
+
customCoords?: AMap.CustomCoords;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 把 AMap 当前帧的相机参数同步到 Three.js 相机。
|
|
36
|
+
*
|
|
37
|
+
* 相机类型必须和 viewMode 匹配:`2D` 使用 `OrthographicCamera`,`3D` 使用 `PerspectiveCamera`。
|
|
38
|
+
* 类型不匹配时不写入任何参数,返回 `synced: false`,由调用方决定是否提示。
|
|
39
|
+
*/
|
|
40
|
+
export declare function syncMapCamera({ map, camera, viewMode, origin, customCoords }: SyncMapCameraOptions): MapCameraSyncResult;
|
|
41
|
+
type ScenePosition = [number, number, number];
|
|
42
|
+
interface MapCoordinates {
|
|
43
|
+
/**
|
|
44
|
+
* The geographic origin used by all conversions.
|
|
45
|
+
*/
|
|
46
|
+
readonly origin: AMap.LngLatLike;
|
|
47
|
+
/**
|
|
48
|
+
* Convert a geographic coordinate to a Three.js scene position.
|
|
49
|
+
*
|
|
50
|
+
* `altitude` is mapped to the scene's Z axis. When omitted, a third tuple
|
|
51
|
+
* element such as `[lng, lat, altitude]` is used.
|
|
52
|
+
*/
|
|
53
|
+
lngLatToScene: (lnglat: AMap.LngLatLike, altitude?: number) => ScenePosition;
|
|
54
|
+
/**
|
|
55
|
+
* Batch convert geographic coordinates to Three.js scene positions.
|
|
56
|
+
*
|
|
57
|
+
* When `altitude` is omitted, each tuple's third element is used.
|
|
58
|
+
*/
|
|
59
|
+
lngLatsToScene: (lnglats: AMap.LngLatLike[], altitude?: number) => ScenePosition[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a coordinate converter backed by AMap's custom coordinates.
|
|
63
|
+
*
|
|
64
|
+
* The converter keeps the same origin as the layer renderer, so scene objects
|
|
65
|
+
* stay aligned with the map across 2D/3D views, pan, zoom and rotation.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createMapCoordinates(map: AMap.Map, origin: AMap.LngLatLike): MapCoordinates;
|
|
68
|
+
export type { MapCameraSyncResult, MapCoordinates, ScenePosition, SyncMapCameraOptions };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { MathUtils } from "three";
|
|
2
|
+
// src/canvas-ownership.ts
|
|
3
|
+
const canvasOwners = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
/**
|
|
5
|
+
* 尝试占用一个共享 canvas(通常是一个 map 的 GL canvas)。
|
|
6
|
+
* 同一 canvas 只允许一个 3D 图层占用;同一 owner 可以重复占用(例如 HMR)。
|
|
7
|
+
*/
|
|
8
|
+
function tryAcquireCanvas(canvas, owner) {
|
|
9
|
+
const currentOwner = canvasOwners.get(canvas);
|
|
10
|
+
if (currentOwner !== void 0 && currentOwner !== owner) return false;
|
|
11
|
+
canvasOwners.set(canvas, owner);
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 释放 canvas 占用;只有当前 owner 才能释放,避免误删其他图层的占用。
|
|
16
|
+
*/
|
|
17
|
+
function releaseCanvas(canvas, owner) {
|
|
18
|
+
if (canvasOwners.get(canvas) === owner) canvasOwners.delete(canvas);
|
|
19
|
+
}
|
|
20
|
+
function getCanvasOwner(canvas) {
|
|
21
|
+
return canvasOwners.get(canvas);
|
|
22
|
+
}
|
|
23
|
+
// src/map-camera.ts
|
|
24
|
+
function isPerspectiveCamera(camera) {
|
|
25
|
+
return camera.isPerspectiveCamera === true;
|
|
26
|
+
}
|
|
27
|
+
function isOrthographicCamera(camera) {
|
|
28
|
+
return camera.isOrthographicCamera === true;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 把 AMap 当前帧的相机参数同步到 Three.js 相机。
|
|
32
|
+
*
|
|
33
|
+
* 相机类型必须和 viewMode 匹配:`2D` 使用 `OrthographicCamera`,`3D` 使用 `PerspectiveCamera`。
|
|
34
|
+
* 类型不匹配时不写入任何参数,返回 `synced: false`,由调用方决定是否提示。
|
|
35
|
+
*/
|
|
36
|
+
function syncMapCamera({ map, camera, viewMode, origin, customCoords = map.customCoords }) {
|
|
37
|
+
customCoords.setCenter(origin);
|
|
38
|
+
if (viewMode === "3D") {
|
|
39
|
+
if (!isPerspectiveCamera(camera)) return {
|
|
40
|
+
synced: false,
|
|
41
|
+
viewMode,
|
|
42
|
+
expected: "PerspectiveCamera"
|
|
43
|
+
};
|
|
44
|
+
const { near, far, fov, up, lookAt, position } = customCoords.getCameraParams();
|
|
45
|
+
camera.near = near;
|
|
46
|
+
camera.far = far;
|
|
47
|
+
camera.fov = fov;
|
|
48
|
+
camera.position.set(...position);
|
|
49
|
+
camera.up.set(up[0], up[1], up[2]);
|
|
50
|
+
camera.lookAt(...lookAt);
|
|
51
|
+
camera.updateProjectionMatrix();
|
|
52
|
+
camera.updateMatrixWorld();
|
|
53
|
+
return { synced: true };
|
|
54
|
+
}
|
|
55
|
+
if (!isOrthographicCamera(camera)) return {
|
|
56
|
+
synced: false,
|
|
57
|
+
viewMode,
|
|
58
|
+
expected: "OrthographicCamera"
|
|
59
|
+
};
|
|
60
|
+
const { near, far, top, bottom, left, right, position, rotation } = customCoords.getCameraParams();
|
|
61
|
+
camera.near = near;
|
|
62
|
+
camera.far = far;
|
|
63
|
+
camera.top = top;
|
|
64
|
+
camera.bottom = bottom;
|
|
65
|
+
camera.left = left;
|
|
66
|
+
camera.right = right;
|
|
67
|
+
const [centerX, centerY] = customCoords.lngLatToCoord(map.getCenter());
|
|
68
|
+
camera.position.set(centerX, centerY, position[2]);
|
|
69
|
+
camera.up.set(0, 1, 0);
|
|
70
|
+
camera.lookAt(centerX, centerY, 0);
|
|
71
|
+
camera.rotation.z = MathUtils.degToRad(rotation);
|
|
72
|
+
camera.updateProjectionMatrix();
|
|
73
|
+
camera.updateMatrixWorld();
|
|
74
|
+
return { synced: true };
|
|
75
|
+
}
|
|
76
|
+
// src/map-coordinates.ts
|
|
77
|
+
function tupleAltitude(lnglat) {
|
|
78
|
+
if (!Array.isArray(lnglat) || lnglat.length < 3) return void 0;
|
|
79
|
+
return lnglat[2];
|
|
80
|
+
}
|
|
81
|
+
function resolveAltitude(lnglat, altitude) {
|
|
82
|
+
return altitude ?? tupleAltitude(lnglat) ?? 0;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Create a coordinate converter backed by AMap's custom coordinates.
|
|
86
|
+
*
|
|
87
|
+
* The converter keeps the same origin as the layer renderer, so scene objects
|
|
88
|
+
* stay aligned with the map across 2D/3D views, pan, zoom and rotation.
|
|
89
|
+
*/
|
|
90
|
+
function createMapCoordinates(map, origin) {
|
|
91
|
+
const customCoords = map.customCoords;
|
|
92
|
+
const applyOrigin = () => customCoords.setCenter(origin);
|
|
93
|
+
return {
|
|
94
|
+
origin,
|
|
95
|
+
lngLatToScene(lnglat, altitude) {
|
|
96
|
+
applyOrigin();
|
|
97
|
+
const [x, y] = customCoords.lngLatToCoord(lnglat);
|
|
98
|
+
return [
|
|
99
|
+
x,
|
|
100
|
+
y,
|
|
101
|
+
resolveAltitude(lnglat, altitude)
|
|
102
|
+
];
|
|
103
|
+
},
|
|
104
|
+
lngLatsToScene(lnglats, altitude) {
|
|
105
|
+
applyOrigin();
|
|
106
|
+
return customCoords.lngLatsToCoords(lnglats).map(([x, y], index) => {
|
|
107
|
+
return [
|
|
108
|
+
x,
|
|
109
|
+
y,
|
|
110
|
+
resolveAltitude(lnglats[index], altitude)
|
|
111
|
+
];
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export { createMapCoordinates, getCanvasOwner, isOrthographicCamera, isPerspectiveCamera, releaseCanvas, syncMapCamera, tryAcquireCanvas };
|
package/package.json
CHANGED
|
@@ -1,6 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cn-map/gaode-extra-shared",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "高德地图 Three.js 扩展包共享代码",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"amap",
|
|
7
|
+
"three",
|
|
8
|
+
"高德",
|
|
9
|
+
"高德地图"
|
|
10
|
+
],
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://gtihub.com/Jungzl/amap/issues"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/Jungzl/amap.git",
|
|
18
|
+
"directory": "packages/extra-shared"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"module": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@cn-map/gaode-types": "^2.1.0",
|
|
37
|
+
"@types/three": "0.162.0",
|
|
38
|
+
"three": "0.162.0",
|
|
39
|
+
"vitest": "^5.1.0"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@cn-map/gaode-types": "^2.0.0",
|
|
43
|
+
"@types/three": "<=0.162.0",
|
|
44
|
+
"three": "<=0.162.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"@cn-map/gaode-types": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"@types/three": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsdown",
|
|
56
|
+
"dev": "tsdown --watch",
|
|
57
|
+
"check:type": "tsc",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"test:unit": "vitest run -p unit",
|
|
60
|
+
"test:coverage": "vitest run --coverage --bail=1"
|
|
61
|
+
}
|
|
6
62
|
}
|