@more-than-software/mapkit 0.1.0
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/README.md +306 -0
- package/dist/README.md +306 -0
- package/dist/components/MapEffectComposer.d.ts +5 -0
- package/dist/components/MapEffectComposer.d.ts.map +1 -0
- package/dist/components/MapEntity.d.ts +10 -0
- package/dist/components/MapEntity.d.ts.map +1 -0
- package/dist/components/MapScene.d.ts +15 -0
- package/dist/components/MapScene.d.ts.map +1 -0
- package/dist/components/MapViewport.d.ts +10 -0
- package/dist/components/MapViewport.d.ts.map +1 -0
- package/dist/hooks/useMapEvents.d.ts +44 -0
- package/dist/hooks/useMapEvents.d.ts.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43381 -0
- package/dist/index.js.map +1 -0
- package/dist/package.json +48 -0
- package/dist/plugins/TileCreasedNormalsPlugin.d.ts +11 -0
- package/dist/plugins/TileCreasedNormalsPlugin.d.ts.map +1 -0
- package/dist/src/components/MapEffectComposer.tsx +39 -0
- package/dist/src/components/MapEntity.tsx +98 -0
- package/dist/src/components/MapScene.tsx +138 -0
- package/dist/src/components/MapViewport.tsx +82 -0
- package/dist/src/hooks/useMapEvents.ts +211 -0
- package/dist/src/index.ts +55 -0
- package/dist/src/plugins/TileCreasedNormalsPlugin.ts +64 -0
- package/dist/src/utils/camera.ts +60 -0
- package/dist/src/utils/flyTo.ts +118 -0
- package/dist/src/utils/presets.ts +63 -0
- package/dist/utils/camera.d.ts +12 -0
- package/dist/utils/camera.d.ts.map +1 -0
- package/dist/utils/flyTo.d.ts +13 -0
- package/dist/utils/flyTo.d.ts.map +1 -0
- package/dist/utils/presets.d.ts +14 -0
- package/dist/utils/presets.d.ts.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Vector3 } from 'three'
|
|
2
|
+
import { toCreasedNormals as toCreasedNormalsImpl } from 'three/addons/utils/BufferGeometryUtils.js'
|
|
3
|
+
import type { Tile } from '3d-tiles-renderer'
|
|
4
|
+
import { BufferGeometry, Mesh, type Object3D } from 'three'
|
|
5
|
+
|
|
6
|
+
export interface TileCreasedNormalsPluginOptions {
|
|
7
|
+
creaseAngle?: number
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function toCreasedNormalsAsync(
|
|
11
|
+
geometry: BufferGeometry,
|
|
12
|
+
creaseAngle?: number
|
|
13
|
+
): Promise<BufferGeometry> {
|
|
14
|
+
const result = toCreasedNormalsImpl(geometry, creaseAngle)
|
|
15
|
+
|
|
16
|
+
// Triangles can be degenerate lines, producing zero normals and eventually
|
|
17
|
+
// causing NaN values under SH. Fix this by replacing them with a non-zero
|
|
18
|
+
// normal (they are hardly visible because they are degenerate).
|
|
19
|
+
// See: https://github.com/takram-design-engineering/three-geospatial/issues/13
|
|
20
|
+
const normal = result.getAttribute('normal')
|
|
21
|
+
if (normal) {
|
|
22
|
+
const v0 = new Vector3()
|
|
23
|
+
const v1 = new Vector3()
|
|
24
|
+
const v2 = new Vector3()
|
|
25
|
+
for (let i = 0; i < normal.count; i += 3) {
|
|
26
|
+
v0.fromBufferAttribute(normal, i + 0)
|
|
27
|
+
v1.fromBufferAttribute(normal, i + 1)
|
|
28
|
+
v2.fromBufferAttribute(normal, i + 2)
|
|
29
|
+
if (v0.length() < 0.5 || v1.length() < 0.5 || v2.length() < 0.5) {
|
|
30
|
+
normal.setXYZ(i + 0, 0, 0, 1)
|
|
31
|
+
normal.setXYZ(i + 1, 0, 0, 1)
|
|
32
|
+
normal.setXYZ(i + 2, 0, 0, 1)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return result
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class TileCreasedNormalsPlugin {
|
|
41
|
+
readonly options: TileCreasedNormalsPluginOptions
|
|
42
|
+
|
|
43
|
+
constructor(options?: TileCreasedNormalsPluginOptions) {
|
|
44
|
+
this.options = { ...options }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Plugin method
|
|
48
|
+
async processTileModel(scene: Object3D, tile: Tile): Promise<void> {
|
|
49
|
+
const meshes: Mesh[] = []
|
|
50
|
+
scene.traverse(object => {
|
|
51
|
+
if (object instanceof Mesh && object.geometry instanceof BufferGeometry) {
|
|
52
|
+
meshes.push(object)
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
await Promise.all(
|
|
56
|
+
meshes.map(async mesh => {
|
|
57
|
+
mesh.geometry = await toCreasedNormalsAsync(
|
|
58
|
+
mesh.geometry,
|
|
59
|
+
this.options.creaseAngle
|
|
60
|
+
)
|
|
61
|
+
})
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type Camera } from 'three'
|
|
2
|
+
import { Geodetic, PointOfView, radians, degrees, Ellipsoid } from '@takram/three-geospatial'
|
|
3
|
+
|
|
4
|
+
import type { CameraView } from '../index'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Set camera position and orientation from a CameraView
|
|
8
|
+
*/
|
|
9
|
+
export function setCameraView(
|
|
10
|
+
camera: Camera,
|
|
11
|
+
view: CameraView,
|
|
12
|
+
ellipsoid: Ellipsoid = Ellipsoid.WGS84
|
|
13
|
+
): void {
|
|
14
|
+
new PointOfView(
|
|
15
|
+
view.distance,
|
|
16
|
+
radians(view.heading),
|
|
17
|
+
radians(view.pitch)
|
|
18
|
+
).decompose(
|
|
19
|
+
new Geodetic(radians(view.longitude), radians(view.latitude)).toECEF(
|
|
20
|
+
undefined,
|
|
21
|
+
{ ellipsoid }
|
|
22
|
+
),
|
|
23
|
+
camera.position,
|
|
24
|
+
camera.quaternion,
|
|
25
|
+
camera.up
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
if (view.fov != null && 'fov' in camera && typeof camera.fov === 'number') {
|
|
29
|
+
camera.fov = view.fov
|
|
30
|
+
if ('updateProjectionMatrix' in camera && typeof camera.updateProjectionMatrix === 'function') {
|
|
31
|
+
camera.updateProjectionMatrix()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get current camera view
|
|
38
|
+
*/
|
|
39
|
+
export function getCameraView(
|
|
40
|
+
camera: Camera,
|
|
41
|
+
ellipsoid: Ellipsoid = Ellipsoid.WGS84
|
|
42
|
+
): CameraView | null {
|
|
43
|
+
const pov = new PointOfView()
|
|
44
|
+
const result = pov.setFromCamera(camera, ellipsoid)
|
|
45
|
+
if (result == null) {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const geodetic = new Geodetic()
|
|
50
|
+
geodetic.setFromECEF(camera.position, { ellipsoid })
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
latitude: degrees(geodetic.latitude),
|
|
54
|
+
longitude: degrees(geodetic.longitude),
|
|
55
|
+
heading: degrees(pov.heading),
|
|
56
|
+
pitch: degrees(pov.pitch),
|
|
57
|
+
distance: pov.distance,
|
|
58
|
+
fov: 'fov' in camera && typeof camera.fov === 'number' ? camera.fov : undefined
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Camera } from 'three'
|
|
2
|
+
import type { GlobeControls } from '3d-tiles-renderer'
|
|
3
|
+
|
|
4
|
+
import { setCameraView, getCameraView } from './camera'
|
|
5
|
+
import type { CameraView } from '../index'
|
|
6
|
+
|
|
7
|
+
export interface FlyToOptions {
|
|
8
|
+
duration?: number
|
|
9
|
+
easing?: (t: number) => number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Interpolate angle using shortest path (handles wrapping at 360°)
|
|
14
|
+
* Returns the interpolated angle in degrees
|
|
15
|
+
*/
|
|
16
|
+
function interpolateAngle(start: number, end: number, t: number): number {
|
|
17
|
+
// Normalize angles to [0, 360)
|
|
18
|
+
const normalize = (angle: number) => {
|
|
19
|
+
angle = angle % 360
|
|
20
|
+
return angle < 0 ? angle + 360 : angle
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const startNorm = normalize(start)
|
|
24
|
+
const endNorm = normalize(end)
|
|
25
|
+
|
|
26
|
+
// Calculate the difference
|
|
27
|
+
let diff = endNorm - startNorm
|
|
28
|
+
|
|
29
|
+
// Find shortest path: if difference > 180°, go the other way
|
|
30
|
+
if (diff > 180) {
|
|
31
|
+
diff -= 360
|
|
32
|
+
} else if (diff < -180) {
|
|
33
|
+
diff += 360
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Interpolate and normalize result
|
|
37
|
+
const result = normalize(startNorm + diff * t)
|
|
38
|
+
return result
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Interpolate longitude using shortest path (handles wrapping at ±180°)
|
|
43
|
+
* Returns the interpolated longitude in degrees
|
|
44
|
+
*/
|
|
45
|
+
function interpolateLongitude(start: number, end: number, t: number): number {
|
|
46
|
+
// Normalize longitudes to [-180, 180)
|
|
47
|
+
const normalize = (lon: number) => {
|
|
48
|
+
lon = lon % 360
|
|
49
|
+
if (lon > 180) lon -= 360
|
|
50
|
+
if (lon < -180) lon += 360
|
|
51
|
+
return lon
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const startNorm = normalize(start)
|
|
55
|
+
const endNorm = normalize(end)
|
|
56
|
+
|
|
57
|
+
// Calculate the difference
|
|
58
|
+
let diff = endNorm - startNorm
|
|
59
|
+
|
|
60
|
+
// Find shortest path: if difference > 180°, go the other way
|
|
61
|
+
if (diff > 180) {
|
|
62
|
+
diff -= 360
|
|
63
|
+
} else if (diff < -180) {
|
|
64
|
+
diff += 360
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Interpolate and normalize result
|
|
68
|
+
return normalize(startNorm + diff * t)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Imperative flyTo function for animating camera to a target view
|
|
73
|
+
* Returns a promise that resolves when animation completes
|
|
74
|
+
*/
|
|
75
|
+
export async function flyTo(
|
|
76
|
+
camera: Camera,
|
|
77
|
+
controls: GlobeControls | null,
|
|
78
|
+
targetView: CameraView,
|
|
79
|
+
options?: FlyToOptions
|
|
80
|
+
): Promise<void> {
|
|
81
|
+
const duration = options?.duration ?? 2000
|
|
82
|
+
const easing = options?.easing ?? ((t: number) => t * (2 - t)) // ease-out
|
|
83
|
+
const startTime = Date.now()
|
|
84
|
+
|
|
85
|
+
const startView = getCameraView(camera)
|
|
86
|
+
if (startView == null) {
|
|
87
|
+
setCameraView(camera, targetView)
|
|
88
|
+
return Promise.resolve()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return new Promise(resolve => {
|
|
92
|
+
const animate = () => {
|
|
93
|
+
const elapsed = Date.now() - startTime
|
|
94
|
+
const progress = Math.min(elapsed / duration, 1)
|
|
95
|
+
const eased = easing(progress)
|
|
96
|
+
|
|
97
|
+
const currentView: CameraView = {
|
|
98
|
+
latitude: startView.latitude + (targetView.latitude - startView.latitude) * eased,
|
|
99
|
+
longitude: interpolateLongitude(startView.longitude, targetView.longitude, eased),
|
|
100
|
+
heading: interpolateAngle(startView.heading, targetView.heading, eased),
|
|
101
|
+
pitch: startView.pitch + (targetView.pitch - startView.pitch) * eased,
|
|
102
|
+
distance: startView.distance + (targetView.distance - startView.distance) * eased,
|
|
103
|
+
fov: targetView.fov != null
|
|
104
|
+
? (startView.fov ?? 50) + (targetView.fov - (startView.fov ?? 50)) * eased
|
|
105
|
+
: undefined
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
setCameraView(camera, currentView)
|
|
109
|
+
|
|
110
|
+
if (progress < 1) {
|
|
111
|
+
requestAnimationFrame(animate)
|
|
112
|
+
} else {
|
|
113
|
+
resolve()
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
animate()
|
|
117
|
+
})
|
|
118
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { CameraView } from '../index'
|
|
2
|
+
|
|
3
|
+
const presets = new Map<string, CameraView>()
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Create a named camera preset
|
|
7
|
+
*/
|
|
8
|
+
export function createPreset(name: string, view: CameraView): void {
|
|
9
|
+
presets.set(name, { ...view })
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get a preset by name
|
|
14
|
+
*/
|
|
15
|
+
export function getPreset(name: string): CameraView | undefined {
|
|
16
|
+
return presets.get(name)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Common location presets
|
|
21
|
+
*/
|
|
22
|
+
export const commonPresets: Record<string, CameraView> = {
|
|
23
|
+
tokyo: {
|
|
24
|
+
latitude: 35.6812,
|
|
25
|
+
longitude: 139.7671,
|
|
26
|
+
heading: 180,
|
|
27
|
+
pitch: -30,
|
|
28
|
+
distance: 4500
|
|
29
|
+
},
|
|
30
|
+
london: {
|
|
31
|
+
latitude: 51.5074,
|
|
32
|
+
longitude: -0.1278,
|
|
33
|
+
heading: 0,
|
|
34
|
+
pitch: -30,
|
|
35
|
+
distance: 5000
|
|
36
|
+
},
|
|
37
|
+
'new-york': {
|
|
38
|
+
latitude: 40.7128,
|
|
39
|
+
longitude: -74.0060,
|
|
40
|
+
heading: 0,
|
|
41
|
+
pitch: -30,
|
|
42
|
+
distance: 5000
|
|
43
|
+
},
|
|
44
|
+
paris: {
|
|
45
|
+
latitude: 48.8566,
|
|
46
|
+
longitude: 2.3522,
|
|
47
|
+
heading: 0,
|
|
48
|
+
pitch: -30,
|
|
49
|
+
distance: 5000
|
|
50
|
+
},
|
|
51
|
+
sydney: {
|
|
52
|
+
latitude: -33.8688,
|
|
53
|
+
longitude: 151.2093,
|
|
54
|
+
heading: 0,
|
|
55
|
+
pitch: -30,
|
|
56
|
+
distance: 5000
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Initialize common presets
|
|
61
|
+
Object.entries(commonPresets).forEach(([name, view]) => {
|
|
62
|
+
createPreset(name, view)
|
|
63
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Camera } from 'three';
|
|
2
|
+
import { Ellipsoid } from '@takram/three-geospatial';
|
|
3
|
+
import { CameraView } from '../index';
|
|
4
|
+
/**
|
|
5
|
+
* Set camera position and orientation from a CameraView
|
|
6
|
+
*/
|
|
7
|
+
export declare function setCameraView(camera: Camera, view: CameraView, ellipsoid?: Ellipsoid): void;
|
|
8
|
+
/**
|
|
9
|
+
* Get current camera view
|
|
10
|
+
*/
|
|
11
|
+
export declare function getCameraView(camera: Camera, ellipsoid?: Ellipsoid): CameraView | null;
|
|
12
|
+
//# sourceMappingURL=camera.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../src/utils/camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,OAAO,CAAA;AACnC,OAAO,EAA2C,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAE7F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,UAAU,EAChB,SAAS,GAAE,SAA2B,GACrC,IAAI,CAqBN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,SAA2B,GACrC,UAAU,GAAG,IAAI,CAkBnB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Camera } from 'three';
|
|
2
|
+
import { GlobeControls } from '3d-tiles-renderer';
|
|
3
|
+
import { CameraView } from '../index';
|
|
4
|
+
export interface FlyToOptions {
|
|
5
|
+
duration?: number;
|
|
6
|
+
easing?: (t: number) => number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Imperative flyTo function for animating camera to a target view
|
|
10
|
+
* Returns a promise that resolves when animation completes
|
|
11
|
+
*/
|
|
12
|
+
export declare function flyTo(camera: Camera, controls: GlobeControls | null, targetView: CameraView, options?: FlyToOptions): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=flyTo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flyTo.d.ts","sourceRoot":"","sources":["../../src/utils/flyTo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC/B;AA6DD;;;GAGG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,aAAa,GAAG,IAAI,EAC9B,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,IAAI,CAAC,CAsCf"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CameraView } from '../index';
|
|
2
|
+
/**
|
|
3
|
+
* Create a named camera preset
|
|
4
|
+
*/
|
|
5
|
+
export declare function createPreset(name: string, view: CameraView): void;
|
|
6
|
+
/**
|
|
7
|
+
* Get a preset by name
|
|
8
|
+
*/
|
|
9
|
+
export declare function getPreset(name: string): CameraView | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Common location presets
|
|
12
|
+
*/
|
|
13
|
+
export declare const commonPresets: Record<string, CameraView>;
|
|
14
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/utils/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAI1C;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAEjE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE9D;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAoCpD,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@more-than-software/mapkit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/more-than-software/citykit.git",
|
|
22
|
+
"directory": "packages/mapkit"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"react",
|
|
26
|
+
"three.js",
|
|
27
|
+
"3d-tiles",
|
|
28
|
+
"google-maps",
|
|
29
|
+
"geospatial",
|
|
30
|
+
"globe",
|
|
31
|
+
"map",
|
|
32
|
+
"react-three-fiber"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"3d-tiles-renderer": "0.4.21",
|
|
36
|
+
"@takram/three-atmosphere": "^0.16.0",
|
|
37
|
+
"@takram/three-clouds": "^0.16.0",
|
|
38
|
+
"@takram/three-geospatial": "^0.6.0",
|
|
39
|
+
"@takram/three-geospatial-effects": "^0.6.0",
|
|
40
|
+
"motion": "^12.34.2",
|
|
41
|
+
"postprocessing": "^6.38.2",
|
|
42
|
+
"react-merge-refs": "^3.0.2",
|
|
43
|
+
"tiny-invariant": "^1.3.3"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@react-three/drei": "^10.0.0",
|
|
47
|
+
"@react-three/fiber": "^9.0.0",
|
|
48
|
+
"@react-three/postprocessing": "^3.0.0",
|
|
49
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
50
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
51
|
+
"three": "^0.180.0"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "vite build"
|
|
58
|
+
}
|
|
59
|
+
}
|