@johnmorrisdotca/chikyu-earth 0.4.0 → 0.7.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/CHANGELOG.md +78 -0
- package/NOTICE.md +39 -1
- package/README.md +199 -24
- package/dist/countries.d.ts +11 -0
- package/dist/countries.js +11 -0
- package/dist/element.d.ts +24 -1
- package/dist/element.js +70 -5
- package/dist/globe.d.ts +15 -1
- package/dist/globe.js +15 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +12 -1
- package/dist/markers/cluster.d.ts +38 -0
- package/dist/markers/cluster.js +42 -0
- package/dist/markers/index.d.ts +5 -0
- package/dist/markers/index.js +6 -0
- package/dist/markers/labels.d.ts +64 -0
- package/dist/markers/labels.js +70 -0
- package/dist/markers/layer.d.ts +129 -0
- package/dist/markers/layer.js +455 -0
- package/dist/markers/project.d.ts +82 -0
- package/dist/markers/project.js +93 -0
- package/dist/markers/types.d.ts +83 -0
- package/dist/markers/types.js +1 -0
- package/dist/realistic/earth.d.ts +81 -0
- package/dist/realistic/earth.js +163 -0
- package/dist/realistic/element.d.ts +93 -0
- package/dist/realistic/element.js +284 -0
- package/dist/realistic/gate.d.ts +64 -0
- package/dist/realistic/gate.js +72 -0
- package/dist/realistic/index.d.ts +5 -0
- package/dist/realistic/index.js +6 -0
- package/dist/realistic/shaders.d.ts +10 -0
- package/dist/realistic/shaders.js +124 -0
- package/dist/realistic/shared.d.ts +23 -0
- package/dist/realistic/shared.js +51 -0
- package/dist/realistic/sun.d.ts +44 -0
- package/dist/realistic/sun.js +65 -0
- package/dist/realistic/textures.d.ts +40 -0
- package/dist/realistic/textures.js +141 -0
- package/dist/realistic/tiers.d.ts +94 -0
- package/dist/realistic/tiers.js +94 -0
- package/dist/rotate.d.ts +59 -4
- package/dist/rotate.js +59 -4
- package/dist/space/element.d.ts +134 -0
- package/dist/space/element.js +394 -0
- package/dist/space/ephemeris.d.ts +151 -0
- package/dist/space/ephemeris.js +162 -0
- package/dist/space/index.d.ts +3 -0
- package/dist/space/index.js +5 -0
- package/dist/space/scale.d.ts +124 -0
- package/dist/space/scale.js +141 -0
- package/dist/space/scene.d.ts +131 -0
- package/dist/space/scene.js +295 -0
- package/dist/styles.d.ts +65 -2
- package/dist/styles.js +43 -2
- package/dist/textures/clouds-1024.webp +0 -0
- package/dist/textures/clouds-2048.webp +0 -0
- package/dist/textures/day-1024.webp +0 -0
- package/dist/textures/day-2048.webp +0 -0
- package/dist/textures/day-4096.webp +0 -0
- package/dist/textures/moon-1024.webp +0 -0
- package/dist/textures/moon-2048.webp +0 -0
- package/dist/textures/night-1024.webp +0 -0
- package/dist/textures/night-2048.webp +0 -0
- package/dist/textures/water-1024.webp +0 -0
- package/dist/textures/water-2048.webp +0 -0
- package/dist/types.d.ts +55 -5
- package/dist/view.d.ts +64 -3
- package/dist/view.js +56 -3
- package/package.json +93 -8
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shapes a marker can be drawn as: `dot`, `ring`, `square` or `diamond`.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import type { MarkerIcon, MarkerInput } from "@johnmorrisdotca/chikyu-earth/markers";
|
|
7
|
+
*
|
|
8
|
+
* const icon: MarkerIcon = "diamond";
|
|
9
|
+
* const stadium: MarkerInput = { id: "camp-nou", lon: 2.12, lat: 41.38, icon, group: "Stadiums" };
|
|
10
|
+
* console.log(stadium.icon);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export type MarkerIcon = "dot" | "ring" | "square" | "diamond";
|
|
14
|
+
/**
|
|
15
|
+
* A place on the Earth. Chikyu ships none: the page brings its own.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import type { MarkerInput } from "@johnmorrisdotca/chikyu-earth/markers";
|
|
20
|
+
*
|
|
21
|
+
* const tokyo: MarkerInput = { id: "tokyo", lon: 139.69, lat: 35.69, label: "Tokyo", group: "Cities", priority: 5, data: { population: 14_000_000 } };
|
|
22
|
+
* console.log(tokyo.label);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export interface MarkerInput {
|
|
26
|
+
/** Your own unique name for it. */
|
|
27
|
+
id: string;
|
|
28
|
+
/** Degrees east and north. */
|
|
29
|
+
lon: number;
|
|
30
|
+
lat: number;
|
|
31
|
+
/** Shown beside the dot when there is room; also its name for a screen reader. */
|
|
32
|
+
label?: string;
|
|
33
|
+
/** What a screen reader says instead of the label (a sentence). */
|
|
34
|
+
description?: string;
|
|
35
|
+
/** Any CSS colour. Default the accent. */
|
|
36
|
+
color?: string;
|
|
37
|
+
icon?: MarkerIcon;
|
|
38
|
+
/** Diameter in CSS pixels, 4 to 32. Default 8. */
|
|
39
|
+
size?: number;
|
|
40
|
+
/** A name for a set of markers (cities, stadiums) that can be shown or hidden together. */
|
|
41
|
+
group?: string;
|
|
42
|
+
/** Higher keeps its label when labels crowd. Default 0. */
|
|
43
|
+
priority?: number;
|
|
44
|
+
/** Yours: given back in every event. */
|
|
45
|
+
data?: unknown;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* What the `chikyu-marker-hover`, `chikyu-marker-click` and `chikyu-marker-focus` events carry in `event.detail`. A cluster click has `marker: null` and `cluster` listing the ids in it.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import type { MarkerEventDetail } from "@johnmorrisdotca/chikyu-earth/markers";
|
|
53
|
+
*
|
|
54
|
+
* const on = (event: Event): void => {
|
|
55
|
+
* const detail = (event as CustomEvent<MarkerEventDetail>).detail;
|
|
56
|
+
* console.log(detail.marker?.label ?? `${detail.cluster?.length} places`, detail.x, detail.y);
|
|
57
|
+
* };
|
|
58
|
+
* console.log(typeof on);
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export interface MarkerEventDetail {
|
|
62
|
+
marker: MarkerInput | null;
|
|
63
|
+
cluster?: string[];
|
|
64
|
+
/** Where the pointer or the marker is, in CSS pixels inside the globe's box. */
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* One group of markers: its name, how many it holds and whether it is shown.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import type { GroupInfo } from "@johnmorrisdotca/chikyu-earth/markers";
|
|
74
|
+
*
|
|
75
|
+
* const show = (groups: GroupInfo[]): string => groups.map((group) => `${group.name}: ${group.count}${group.visible ? "" : " (hidden)"}`).join(", ");
|
|
76
|
+
* console.log(show([{ name: "Cities", count: 3, visible: true }]));
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export interface GroupInfo {
|
|
80
|
+
name: string;
|
|
81
|
+
count: number;
|
|
82
|
+
visible: boolean;
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type * as THREE from "three";
|
|
2
|
+
import type { AssetCache, Item3D } from "@johnmorrisdotca/kazoku-ui/renderer";
|
|
3
|
+
import type { GeoPoint, GlobeView } from "../types.ts";
|
|
4
|
+
import { lookAt } from "../view.ts";
|
|
5
|
+
import type { Layer } from "./tiers.ts";
|
|
6
|
+
import { type ThreeParts } from "./textures.ts";
|
|
7
|
+
export type { ThreeParts };
|
|
8
|
+
type Three = ThreeParts;
|
|
9
|
+
/**
|
|
10
|
+
* The glow reaches this many radii from the centre; the globe at 1x is drawn to fit inside it.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { ATMOSPHERE_OUTER } from "@johnmorrisdotca/chikyu-earth/realistic";
|
|
15
|
+
*
|
|
16
|
+
* console.log(ATMOSPHERE_OUTER);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare const ATMOSPHERE_OUTER = 1.08;
|
|
20
|
+
/** What the scene reads at each draw; the element changes it and asks for a draw. */
|
|
21
|
+
export interface EarthModel {
|
|
22
|
+
/** The home centre; the shared controls' yaw and tilt are added to it as in the flat globe. */
|
|
23
|
+
centre: GeoPoint;
|
|
24
|
+
view: GlobeView;
|
|
25
|
+
/** The moment shown, in milliseconds since the epoch: it fixes where the Sun is and how far the clouds have drifted. */
|
|
26
|
+
time: number;
|
|
27
|
+
clouds: boolean;
|
|
28
|
+
lights: boolean;
|
|
29
|
+
/** Where the camera looked at the last draw (the element decides from it whether a new draw is worth it). */
|
|
30
|
+
drawn: {
|
|
31
|
+
view: GlobeView;
|
|
32
|
+
time: number;
|
|
33
|
+
radius: number;
|
|
34
|
+
centre: GeoPoint;
|
|
35
|
+
} | null;
|
|
36
|
+
/** The pixel ratio the textures are chosen for. */
|
|
37
|
+
ratio(): number;
|
|
38
|
+
}
|
|
39
|
+
export interface EarthDeps {
|
|
40
|
+
assets: AssetCache;
|
|
41
|
+
/** Ends with a slash. */
|
|
42
|
+
textureBase: () => string;
|
|
43
|
+
/** The widest texture, 4096 at most. */
|
|
44
|
+
cap: () => number;
|
|
45
|
+
/** Clouds' eastward drift against the ground, degrees an hour. */
|
|
46
|
+
drift: number;
|
|
47
|
+
invalidate: () => void;
|
|
48
|
+
onError?: (error: unknown) => void;
|
|
49
|
+
onTier?: (layer: Layer, width: number) => void;
|
|
50
|
+
/** Told at every draw where the disc is, for what is laid over it (markers). */
|
|
51
|
+
onPose?: (pose: {
|
|
52
|
+
lon: number;
|
|
53
|
+
lat: number;
|
|
54
|
+
radius: number;
|
|
55
|
+
cx: number;
|
|
56
|
+
cy: number;
|
|
57
|
+
width: number;
|
|
58
|
+
height: number;
|
|
59
|
+
}) => void;
|
|
60
|
+
}
|
|
61
|
+
export declare const newModel: () => EarthModel;
|
|
62
|
+
/**
|
|
63
|
+
* The disc's radius in CSS pixels in a box of `width` x `height` at `zoom`: it fits the glow in the box at 1x.
|
|
64
|
+
*
|
|
65
|
+
* @param width - The box's width in CSS pixels.
|
|
66
|
+
* @param height - The box's height in CSS pixels.
|
|
67
|
+
* @param zoom - The view's zoom, 1 at Fit.
|
|
68
|
+
* @returns The radius in CSS pixels, at least 1.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { discRadius } from "@johnmorrisdotca/chikyu-earth/realistic";
|
|
73
|
+
*
|
|
74
|
+
* console.log(discRadius(400, 400, 1).toFixed(1));
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare const discRadius: (width: number, height: number, zoom: number) => number;
|
|
78
|
+
export { lookAt };
|
|
79
|
+
/** An equirectangular sphere: +z is longitude 0 on the equator, +x east, +y north; v is 0 at the north pole (the top row of the picture). */
|
|
80
|
+
export declare function sphere(three: Three, columns: number, rows: number): THREE.BufferGeometry;
|
|
81
|
+
export declare function createEarthItem(model: EarthModel, deps: EarthDeps): Item3D<Three>;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { HOME_VIEW, lookAt } from "../view.js";
|
|
2
|
+
import { ATMOSPHERE_FRAG, ATMOSPHERE_VERT, CLOUD_FRAG, SURFACE_FRAG, SURFACE_VERT } from "./shaders.js";
|
|
3
|
+
import { subsolarPoint, unitVector } from "./sun.js";
|
|
4
|
+
import { createTextureSet } from "./textures.js";
|
|
5
|
+
const RAD = Math.PI / 180;
|
|
6
|
+
/**
|
|
7
|
+
* The glow reaches this many radii from the centre; the globe at 1x is drawn to fit inside it.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { ATMOSPHERE_OUTER } from "@johnmorrisdotca/chikyu-earth/realistic";
|
|
12
|
+
*
|
|
13
|
+
* console.log(ATMOSPHERE_OUTER);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export const ATMOSPHERE_OUTER = 1.08;
|
|
17
|
+
const CLOUD_RADIUS = 1.006;
|
|
18
|
+
const LAYERS = ["day", "night", "clouds", "water"];
|
|
19
|
+
export const newModel = () => ({
|
|
20
|
+
centre: { lon: 0, lat: 0 },
|
|
21
|
+
view: { ...HOME_VIEW },
|
|
22
|
+
time: Date.now(),
|
|
23
|
+
clouds: true,
|
|
24
|
+
lights: true,
|
|
25
|
+
drawn: null,
|
|
26
|
+
ratio: () => Math.min(globalThis.devicePixelRatio || 1, 2),
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* The disc's radius in CSS pixels in a box of `width` x `height` at `zoom`: it fits the glow in the box at 1x.
|
|
30
|
+
*
|
|
31
|
+
* @param width - The box's width in CSS pixels.
|
|
32
|
+
* @param height - The box's height in CSS pixels.
|
|
33
|
+
* @param zoom - The view's zoom, 1 at Fit.
|
|
34
|
+
* @returns The radius in CSS pixels, at least 1.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { discRadius } from "@johnmorrisdotca/chikyu-earth/realistic";
|
|
39
|
+
*
|
|
40
|
+
* console.log(discRadius(400, 400, 1).toFixed(1));
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export const discRadius = (width, height, zoom) => Math.max(1, (Math.min(width, height) / 2 / ATMOSPHERE_OUTER - 1) * zoom);
|
|
44
|
+
export { lookAt };
|
|
45
|
+
/** An equirectangular sphere: +z is longitude 0 on the equator, +x east, +y north; v is 0 at the north pole (the top row of the picture). */
|
|
46
|
+
export function sphere(three, columns, rows) {
|
|
47
|
+
const positions = new Float32Array((columns + 1) * (rows + 1) * 3);
|
|
48
|
+
const uvs = new Float32Array((columns + 1) * (rows + 1) * 2);
|
|
49
|
+
let p = 0;
|
|
50
|
+
let q = 0;
|
|
51
|
+
for (let j = 0; j <= rows; j += 1) {
|
|
52
|
+
const lat = (0.5 - j / rows) * Math.PI;
|
|
53
|
+
for (let i = 0; i <= columns; i += 1) {
|
|
54
|
+
const lon = (i / columns - 0.5) * 2 * Math.PI;
|
|
55
|
+
positions[p++] = Math.cos(lat) * Math.sin(lon);
|
|
56
|
+
positions[p++] = Math.sin(lat);
|
|
57
|
+
positions[p++] = Math.cos(lat) * Math.cos(lon);
|
|
58
|
+
uvs[q++] = i / columns;
|
|
59
|
+
uvs[q++] = j / rows;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const index = [];
|
|
63
|
+
for (let j = 0; j < rows; j += 1) {
|
|
64
|
+
for (let i = 0; i < columns; i += 1) {
|
|
65
|
+
const a = j * (columns + 1) + i;
|
|
66
|
+
const b = a + columns + 1;
|
|
67
|
+
index.push(a, b, a + 1, b, b + 1, a + 1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const geometry = new three.BufferGeometry();
|
|
71
|
+
geometry.setAttribute("position", new three.BufferAttribute(positions, 3));
|
|
72
|
+
geometry.setAttribute("uv", new three.BufferAttribute(uvs, 2));
|
|
73
|
+
geometry.setIndex(index);
|
|
74
|
+
return geometry;
|
|
75
|
+
}
|
|
76
|
+
export function createEarthItem(model, deps) {
|
|
77
|
+
return {
|
|
78
|
+
key: "chikyu-earth:realistic",
|
|
79
|
+
async build({ three, width, height }) {
|
|
80
|
+
let size = { width, height };
|
|
81
|
+
const textures = await createTextureSet(three, LAYERS, {
|
|
82
|
+
assets: deps.assets,
|
|
83
|
+
textureBase: deps.textureBase,
|
|
84
|
+
cap: deps.cap,
|
|
85
|
+
invalidate: deps.invalidate,
|
|
86
|
+
...(deps.onError ? { onError: deps.onError } : {}),
|
|
87
|
+
...(deps.onTier ? { onTier: deps.onTier } : {}),
|
|
88
|
+
});
|
|
89
|
+
const uniform = textures.uniforms;
|
|
90
|
+
const sunDir = { value: new three.Vector3(1, 0, 0) };
|
|
91
|
+
const grid = sphere(three, 128, 64);
|
|
92
|
+
const surface = new three.ShaderMaterial({
|
|
93
|
+
vertexShader: SURFACE_VERT,
|
|
94
|
+
fragmentShader: SURFACE_FRAG,
|
|
95
|
+
uniforms: { dayMap: uniform.day, nightMap: uniform.night, waterMap: uniform.water, sunDir, lights: { value: 1 }, ortho: { value: 1 } },
|
|
96
|
+
});
|
|
97
|
+
const cloudShift = { value: 0 };
|
|
98
|
+
const cloudMaterial = new three.ShaderMaterial({
|
|
99
|
+
vertexShader: SURFACE_VERT,
|
|
100
|
+
fragmentShader: CLOUD_FRAG,
|
|
101
|
+
uniforms: { cloudMap: uniform.clouds, sunDir, shift: cloudShift, opacity: { value: 0.9 } },
|
|
102
|
+
transparent: true,
|
|
103
|
+
depthWrite: false,
|
|
104
|
+
});
|
|
105
|
+
const atmosphere = new three.ShaderMaterial({
|
|
106
|
+
vertexShader: ATMOSPHERE_VERT,
|
|
107
|
+
fragmentShader: ATMOSPHERE_FRAG,
|
|
108
|
+
uniforms: { sunView: sunDir, outer: { value: ATMOSPHERE_OUTER }, ortho: { value: 1 } },
|
|
109
|
+
transparent: true,
|
|
110
|
+
depthWrite: false,
|
|
111
|
+
side: three.BackSide,
|
|
112
|
+
});
|
|
113
|
+
const turned = new three.Group();
|
|
114
|
+
const earth = new three.Mesh(grid, surface);
|
|
115
|
+
const clouds = new three.Mesh(grid, cloudMaterial);
|
|
116
|
+
clouds.scale.setScalar(CLOUD_RADIUS);
|
|
117
|
+
clouds.renderOrder = 2;
|
|
118
|
+
turned.add(earth, clouds);
|
|
119
|
+
const glow = new three.Mesh(grid, atmosphere);
|
|
120
|
+
glow.scale.setScalar(ATMOSPHERE_OUTER);
|
|
121
|
+
glow.renderOrder = 1;
|
|
122
|
+
glow.frustumCulled = false;
|
|
123
|
+
const scene = new three.Scene();
|
|
124
|
+
scene.add(turned, glow);
|
|
125
|
+
const camera = new three.OrthographicCamera(-1, 1, 1, -1, 0.1, 20);
|
|
126
|
+
camera.position.set(0, 0, 5);
|
|
127
|
+
return {
|
|
128
|
+
scene,
|
|
129
|
+
camera,
|
|
130
|
+
update() {
|
|
131
|
+
const view = model.view;
|
|
132
|
+
const look = lookAt(model.centre, view);
|
|
133
|
+
turned.rotation.set(look.lat * RAD, -look.lon * RAD, 0, "XYZ");
|
|
134
|
+
const [sx, sy, sz] = unitVector(subsolarPoint(model.time));
|
|
135
|
+
sunDir.value.set(sx, sy, sz).applyEuler(turned.rotation);
|
|
136
|
+
cloudShift.value = -(((model.time / 3_600_000) * deps.drift) % 360) / 360;
|
|
137
|
+
clouds.visible = model.clouds;
|
|
138
|
+
surface.uniforms["lights"].value = model.lights ? 1 : 0;
|
|
139
|
+
const radius = discRadius(size.width, size.height, view.zoom);
|
|
140
|
+
camera.left = (-size.width / 2 - view.panX) / radius;
|
|
141
|
+
camera.right = (size.width / 2 - view.panX) / radius;
|
|
142
|
+
camera.top = (size.height / 2 + view.panY) / radius;
|
|
143
|
+
camera.bottom = (-size.height / 2 + view.panY) / radius;
|
|
144
|
+
camera.updateProjectionMatrix();
|
|
145
|
+
model.drawn = { view: { ...view }, time: model.time, radius, centre: { ...model.centre } };
|
|
146
|
+
textures.sync(radius * model.ratio());
|
|
147
|
+
deps.onPose?.({ lon: look.lon, lat: look.lat, radius, cx: size.width / 2 + view.panX, cy: size.height / 2 + view.panY, width: size.width, height: size.height });
|
|
148
|
+
return false;
|
|
149
|
+
},
|
|
150
|
+
resize(next, nextHeight) {
|
|
151
|
+
size = { width: next, height: nextHeight };
|
|
152
|
+
},
|
|
153
|
+
dispose() {
|
|
154
|
+
textures.dispose();
|
|
155
|
+
grid.dispose();
|
|
156
|
+
surface.dispose();
|
|
157
|
+
cloudMaterial.dispose();
|
|
158
|
+
atmosphere.dispose();
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { GeoPoint, GlobeView } from "../types.ts";
|
|
2
|
+
import { setThreeLoader } from "./shared.ts";
|
|
3
|
+
export { setThreeLoader };
|
|
4
|
+
import type { OverlayHost } from "../markers/layer.ts";
|
|
5
|
+
import { type Layer } from "./tiers.ts";
|
|
6
|
+
type EarthLayer = Extract<Layer, "day" | "night" | "clouds" | "water">;
|
|
7
|
+
/**
|
|
8
|
+
* What the realistic Earth is doing: `loading` its pictures, `live` and drawing, `unavailable` (no WebGL), `lost` (the GPU took the context; it comes back by itself) or `idle` (another view has the page's one WebGL context; press or focus it to take it).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts no-run
|
|
12
|
+
* import type { ChikyuEarthRealistic, EarthState } from "@johnmorrisdotca/chikyu-earth/realistic/element";
|
|
13
|
+
*
|
|
14
|
+
* const describe = (earth: ChikyuEarthRealistic): EarthState => earth.stats.state;
|
|
15
|
+
* console.log(typeof describe);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export type EarthState = "loading" | "live" | "unavailable" | "lost" | "idle";
|
|
19
|
+
/**
|
|
20
|
+
* A `time` attribute: "now" (or none) follows the clock, else an ISO date such as 2026-06-21T12:00:00Z.
|
|
21
|
+
*
|
|
22
|
+
* @param value - The attribute's text, or `null` when it is not there.
|
|
23
|
+
* @returns The moment in milliseconds since the Unix epoch, or `"now"` when the value is empty, `"now"` or not a date.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts no-run
|
|
27
|
+
* import { readTime } from "@johnmorrisdotca/chikyu-earth/realistic/element";
|
|
28
|
+
*
|
|
29
|
+
* console.log(readTime("2026-06-21T12:00:00Z"), readTime(null), readTime("tomorrow"));
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const readTime: (value: string | null) => number | "now";
|
|
33
|
+
/**
|
|
34
|
+
* The `<chikyu-earth-realistic>` custom element: the Earth from space, drawn with three.js through kazoku-ui's shared renderer (one WebGL context for the page). It takes `center` (`"lon,lat"`), `time` (`now` or an ISO date; the real Sun at that moment), `clouds="off"`, `lights="off"`, `live-seconds` and `texture-base` (where the pictures are served from), and a shared view controller's camera through `setView`. It draws only when something changes, at most 30 times a second, and nothing while it is out of sight or the tab is hidden.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts no-run
|
|
38
|
+
* import type { ChikyuEarthRealistic } from "@johnmorrisdotca/chikyu-earth/realistic/element";
|
|
39
|
+
*
|
|
40
|
+
* const earth = document.createElement("chikyu-earth-realistic") as ChikyuEarthRealistic;
|
|
41
|
+
* earth.setAttribute("center", "139.7,35.7");
|
|
42
|
+
* earth.setAttribute("time", "2026-06-21T03:00Z");
|
|
43
|
+
* earth.setAttribute("texture-base", "/textures/");
|
|
44
|
+
* document.body.append(earth);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare class ChikyuEarthRealistic extends HTMLElement {
|
|
48
|
+
#private;
|
|
49
|
+
static observedAttributes: string[];
|
|
50
|
+
connectedCallback(): void;
|
|
51
|
+
disconnectedCallback(): void;
|
|
52
|
+
attributeChangedCallback(name: string, _old: string | null, value: string | null): void;
|
|
53
|
+
/** A box laid over the Earth for markers (see `@johnmorrisdotca/chikyu-earth/markers`): where it is, the pose of the last draw, and a way to hear the next. */
|
|
54
|
+
get overlay(): OverlayHost;
|
|
55
|
+
/** Where the view starts: longitude and latitude; the shared controls' yaw and tilt turn it from there. */
|
|
56
|
+
get centre(): GeoPoint;
|
|
57
|
+
set centre(value: GeoPoint);
|
|
58
|
+
/** The moment shown: milliseconds since the epoch, or "now" to follow the clock. */
|
|
59
|
+
get time(): number | "now";
|
|
60
|
+
set time(value: number | Date | "now");
|
|
61
|
+
get clouds(): boolean;
|
|
62
|
+
set clouds(value: boolean);
|
|
63
|
+
get lights(): boolean;
|
|
64
|
+
set lights(value: boolean);
|
|
65
|
+
/** What the element is doing, for a page or a test: its state, the texture widths held, the draws made. */
|
|
66
|
+
get stats(): {
|
|
67
|
+
state: EarthState;
|
|
68
|
+
tiers: Record<EarthLayer, number>;
|
|
69
|
+
draws: number;
|
|
70
|
+
contexts: number;
|
|
71
|
+
canvas: {
|
|
72
|
+
width: number;
|
|
73
|
+
height: number;
|
|
74
|
+
pixels: number;
|
|
75
|
+
};
|
|
76
|
+
assets: {
|
|
77
|
+
entries: number;
|
|
78
|
+
refs: number;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Apply a shared view controller's camera (yaw, tilt, zoom, pan). A change under half a pixel is not drawn, a settled change always is,
|
|
83
|
+
* and draws are at most 30 a second.
|
|
84
|
+
*/
|
|
85
|
+
setView(view: GlobeView, final?: boolean): void;
|
|
86
|
+
/** The view as it is (for a page that wants to read it back). */
|
|
87
|
+
get view(): GlobeView;
|
|
88
|
+
}
|
|
89
|
+
declare global {
|
|
90
|
+
interface HTMLElementTagNameMap {
|
|
91
|
+
"chikyu-earth-realistic": ChikyuEarthRealistic;
|
|
92
|
+
}
|
|
93
|
+
}
|