webwallgl 1.0.0 → 1.3.5
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.en.md +238 -3
- package/README.md +237 -3
- package/package.json +1 -1
- package/types.d.ts +175 -18
- package/webwallgl.d.ts +37 -17
- package/webwallgl.global.js +2244 -217
- package/webwallgl.global.js.map +1 -1
- package/webwallgl.global.min.js +1241 -33
- package/webwallgl.global.min.js.map +1 -1
- package/webwallgl.min.mjs +1241 -33
- package/webwallgl.min.mjs.map +1 -1
- package/webwallgl.mjs +2245 -218
- package/webwallgl.mjs.map +1 -1
package/types.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type Source = {
|
|
|
11
11
|
/**
|
|
12
12
|
* 场景容器(scene.pkg)字节。实现方只管给字节,解析由库负责。
|
|
13
13
|
* 抛错即视为该场景不可用,会走 onError。
|
|
14
|
+
* 网页壁纸(project.type=web)不会调用本方法。
|
|
14
15
|
*/
|
|
15
16
|
scenePkg(signal?: AbortSignal): Promise<ArrayBuffer | Uint8Array>;
|
|
16
17
|
/**
|
|
@@ -18,15 +19,49 @@ export type Source = {
|
|
|
18
19
|
* 没有 project.json,此时场景字段一律用 scene.json 内的快照值。
|
|
19
20
|
*/
|
|
20
21
|
project?(signal?: AbortSignal): Promise<unknown | null>;
|
|
22
|
+
/**
|
|
23
|
+
* 网页壁纸入口 URL(index.html 等)。`project.type` 为 web 时由 mount 调用;
|
|
24
|
+
* 省略则回退到 `{httpSource 基址}/{project.file || "index.html"}`。
|
|
25
|
+
*/
|
|
26
|
+
webEntry?(signal?: AbortSignal): Promise<{
|
|
27
|
+
url: string;
|
|
28
|
+
} | null>;
|
|
29
|
+
/**
|
|
30
|
+
* 媒体壁纸(video / gif / image)的资源 URL。`project.type` 为这三者之一时
|
|
31
|
+
* 由 mount 调用;省略则回退到 `{httpSource 基址}/{project.file}`。
|
|
32
|
+
*
|
|
33
|
+
* 与 `webEntry` 分开而不是复用同一个方法:`webEntry` 的语义是「HTML 文档入口」
|
|
34
|
+
* (交给 iframe 加载并注入 shim),媒体是「一个可直接喂给 <video>/<img> 的资源」,
|
|
35
|
+
* 两者的消费方与失败模式都不同。`webEntry` 在 1.0.0 已公开,也不宜改语义。
|
|
36
|
+
*
|
|
37
|
+
* `type` 可选,用于纠正 project.json 里缺失或不准的类型;不给则以 project.type 为准。
|
|
38
|
+
*/
|
|
39
|
+
mediaEntry?(signal?: AbortSignal): Promise<{
|
|
40
|
+
url: string;
|
|
41
|
+
type?: string;
|
|
42
|
+
} | null>;
|
|
21
43
|
/**
|
|
22
44
|
* 缓存键。相同键的 scene.pkg 命中库内缓存,避免重复解析上百 MB 的包
|
|
23
45
|
* (暂停恢复、改属性都不该重新走一遍解析)。省略则不参与缓存。
|
|
24
46
|
*/
|
|
25
47
|
readonly key?: string;
|
|
48
|
+
/**
|
|
49
|
+
* 释放本来源占用的资源。实例 destroy() / 换源时调用一次。
|
|
50
|
+
*
|
|
51
|
+
* 目前只有 `mediaSource(File)` 需要:本地文件走 `URL.createObjectURL`,
|
|
52
|
+
* 不 revoke 就是每换一次壁纸泄漏一个几十 MB 的 blob。
|
|
53
|
+
*/
|
|
54
|
+
dispose?(): void;
|
|
26
55
|
};
|
|
27
56
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
57
|
+
* 指针状态提供者(**当前未接线**)。
|
|
58
|
+
*
|
|
59
|
+
* 默认指针来自 canvas 自身的 pointer 事件,由 mountScene 按 `cfg.canvas` 建立,
|
|
60
|
+
* 与本接口无关。要从外部喂指针(桌面壁纸窗口在 underlay 层收不到鼠标)请用
|
|
61
|
+
* `SceneInstance.pushPointer(u, v, buttons)` —— 那是引擎实际消费的推模式通道。
|
|
62
|
+
*
|
|
63
|
+
* 本接口保留是为了不破坏 1.0.0 已公开的类型;注意 `rightDown` 即便接线也不会
|
|
64
|
+
* 生效:引擎的指针状态只消费按键位掩码的 bit0(左键),全库无壁纸读右键。
|
|
30
65
|
*/
|
|
31
66
|
export type PointerSource = {
|
|
32
67
|
/** 归一化坐标 0..1,相对 canvas 左上角;y 向下 */
|
|
@@ -41,6 +76,17 @@ export type PointerSource = {
|
|
|
41
76
|
* 音频频谱提供者(音频响应壁纸用)。返回当前快照,不推进状态 ——
|
|
42
77
|
* 推进由库的渲染循环按场景时间驱动,保证同一时刻取到同一份数据。
|
|
43
78
|
* 默认是内置的确定性模拟源(无需麦克风权限,离线可复现)。
|
|
79
|
+
*
|
|
80
|
+
* **拉模式**:渲染循环每帧调一次 `snapshot()`。宿主每帧推 128 个浮点要走
|
|
81
|
+
* 跨语言桥的字符串拼接与 JS 解析,60fps 下开销可观;让渲染器主动拉,
|
|
82
|
+
* 宿主用同步原生桥直接返回即可。
|
|
83
|
+
*
|
|
84
|
+
* 契约:`left`/`right` 各 **64 段**、值域 **0..1**(已归一化)。段数不足 64
|
|
85
|
+
* 会补零,多于 64 会截断。32/16 段降采样与 level/silent 由库自行派生,
|
|
86
|
+
* 消费方(shader uniform、粒子、文字脚本)不区分数据来源。
|
|
87
|
+
*
|
|
88
|
+
* **scene 与 web 壁纸都生效**:网页壁纸经 iframe shim 的音频泵收到同一份数据
|
|
89
|
+
* (泵逐帧选源,所以 mount() 之后再 setAudio 也能生效)。
|
|
44
90
|
*/
|
|
45
91
|
export type AudioSource = {
|
|
46
92
|
/** 左右声道各 64 段频谱,值域 0..1 */
|
|
@@ -49,20 +95,80 @@ export type AudioSource = {
|
|
|
49
95
|
right: Float32Array | number[];
|
|
50
96
|
};
|
|
51
97
|
};
|
|
98
|
+
/** WE 播放态:0=停止 1=播放 2=暂停(与 MediaPlaybackEvent 枚举一致) */
|
|
99
|
+
export type MediaPlaybackState = 0 | 1 | 2;
|
|
100
|
+
/**
|
|
101
|
+
* 媒体配色的三元组。**必须是带链式方法的实例,不能是普通数组或对象**:
|
|
102
|
+
* 真实语料里的脚本会写 `event.primaryColor.subtract(old).multiply(t).add(old)`,
|
|
103
|
+
* 给数组会 TypeError 熔断整个脚本(症状是「换歌后整层不见了」)。
|
|
104
|
+
* 用 `createMediaSource()` 构造快照可自动保证类型正确。
|
|
105
|
+
*/
|
|
106
|
+
export type MediaColor = {
|
|
107
|
+
x: number;
|
|
108
|
+
y: number;
|
|
109
|
+
z: number;
|
|
110
|
+
add(o: MediaColor): MediaColor;
|
|
111
|
+
subtract(o: MediaColor): MediaColor;
|
|
112
|
+
multiply(k: number | MediaColor): MediaColor;
|
|
113
|
+
};
|
|
114
|
+
/** 系统媒体快照。字段名与 WE 的 media* 回调载荷一致 */
|
|
115
|
+
export type MediaSnapshot = {
|
|
116
|
+
/** 有没有正在播放的媒体会话;false 时其余字段无意义 */
|
|
117
|
+
hasMedia: boolean;
|
|
118
|
+
state: MediaPlaybackState;
|
|
119
|
+
title: string;
|
|
120
|
+
artist: string;
|
|
121
|
+
album: string;
|
|
122
|
+
albumArtist: string;
|
|
123
|
+
/** 播放进度与总时长,单位**秒**(不是 0..1 比例) */
|
|
124
|
+
position: number;
|
|
125
|
+
duration: number;
|
|
126
|
+
hasThumbnail: boolean;
|
|
127
|
+
/** 封面取色。见 MediaColor 的类型约束 */
|
|
128
|
+
primaryColor: MediaColor;
|
|
129
|
+
secondaryColor: MediaColor;
|
|
130
|
+
tertiaryColor: MediaColor;
|
|
131
|
+
textColor: MediaColor;
|
|
132
|
+
highContrastColor: MediaColor;
|
|
133
|
+
/** 播放列表内的曲目序号(换歌检测用) */
|
|
134
|
+
trackIndex: number;
|
|
135
|
+
/** 歌词行:[秒, 文本][],按时间升序 */
|
|
136
|
+
lyrics: Array<[number, string]>;
|
|
137
|
+
/** 当前歌词行与其下标(由 position 定位,库不重算) */
|
|
138
|
+
lyricLine: string;
|
|
139
|
+
lyricIndex: number;
|
|
140
|
+
};
|
|
52
141
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
142
|
+
* 系统媒体源("正在播放"类壁纸用)。默认是内置模拟源。
|
|
143
|
+
*
|
|
144
|
+
* **scene 与 web 壁纸共用同一个实例**:宿主装一次,两类壁纸看到同一份 Now Playing。
|
|
145
|
+
* 库每帧调 `update(tSec)` 推进、读 `snapshot` 取值,并自动 diff 出 WE 的
|
|
146
|
+
* mediaStatusChanged / mediaPropertiesChanged / mediaPlaybackChanged /
|
|
147
|
+
* mediaThumbnailChanged 四个回调派发给壁纸脚本。
|
|
148
|
+
*
|
|
149
|
+
* 五个控制方法是**反向控制**:壁纸里的"上一曲/下一曲/播放暂停"按钮会调到这里,
|
|
150
|
+
* 由你转发给真实播放器。库只负责调用并在之后立刻重新派发一次事件。
|
|
151
|
+
*
|
|
152
|
+
* 自己实现全部字段很繁琐,用 `createMediaSource(partial)` 只给已知字段即可。
|
|
55
153
|
*/
|
|
56
154
|
export type MediaSource = {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
155
|
+
/** 每帧由渲染循环推进(tSec 为场景时间,秒)。无状态的实现可留空函数 */
|
|
156
|
+
update?(tSec: number): void;
|
|
157
|
+
readonly snapshot: MediaSnapshot;
|
|
158
|
+
skipNext?(): void;
|
|
159
|
+
skipPrevious?(): void;
|
|
160
|
+
play?(): void;
|
|
161
|
+
pause?(): void;
|
|
162
|
+
playPause?(): void;
|
|
163
|
+
};
|
|
164
|
+
/** 壁纸侧可用的媒体控制面(SceneInstance.media) */
|
|
165
|
+
export type MediaControl = {
|
|
166
|
+
readonly snapshot: MediaSnapshot;
|
|
167
|
+
skipNext(): MediaSnapshot;
|
|
168
|
+
skipPrevious(): MediaSnapshot;
|
|
169
|
+
play(): MediaSnapshot;
|
|
170
|
+
pause(): MediaSnapshot;
|
|
171
|
+
playPause(): MediaSnapshot;
|
|
66
172
|
};
|
|
67
173
|
/** 渲染开关。调试用,默认全开;对应旧 types.ts 的 SKIP_* 常量取反 */
|
|
68
174
|
export type FeatureFlags = {
|
|
@@ -117,13 +223,19 @@ export type MountOptions = {
|
|
|
117
223
|
autoplay?: boolean;
|
|
118
224
|
/** 用户属性覆盖值(键为 project.json 里的属性名) */
|
|
119
225
|
properties?: Record<string, PropertyValue>;
|
|
120
|
-
/**
|
|
226
|
+
/** 指针源。**当前未接线**,见 PointerSource 说明;外部喂指针请用 pushPointer() */
|
|
121
227
|
pointer?: PointerSource | null;
|
|
122
|
-
/**
|
|
228
|
+
/**
|
|
229
|
+
* 音频频谱源。默认内置确定性模拟;null = 禁用(频谱恒为 0)。
|
|
230
|
+
* 挂载后可用 `SceneInstance.setAudio()` 再换(SSE 等异步数据源常在挂载后才就绪)。
|
|
231
|
+
*/
|
|
123
232
|
audio?: AudioSource | null;
|
|
124
|
-
/**
|
|
233
|
+
/**
|
|
234
|
+
* 系统媒体源(Now Playing)。默认内置模拟;null = 禁用。
|
|
235
|
+
* scene 与 web 壁纸共用同一个实例;挂载后可用 `setMedia()` 再换。
|
|
236
|
+
*/
|
|
125
237
|
media?: MediaSource | null;
|
|
126
|
-
/**
|
|
238
|
+
/** 渲染开关(调试用)。**当前未接线** */
|
|
127
239
|
features?: Partial<FeatureFlags>;
|
|
128
240
|
/** 诊断回调。替代旧的 GET /diag 上报 */
|
|
129
241
|
onDiagnostic?: SceneEvents["diagnostic"];
|
|
@@ -138,7 +250,7 @@ export type FrameStats = {
|
|
|
138
250
|
running: boolean;
|
|
139
251
|
};
|
|
140
252
|
export type SceneInstance = {
|
|
141
|
-
/**
|
|
253
|
+
/** 挂载目标(构造时传入;场景路径可能是内部自建的 canvas) */
|
|
142
254
|
readonly canvas: HTMLCanvasElement;
|
|
143
255
|
pause(): void;
|
|
144
256
|
resume(): void;
|
|
@@ -155,6 +267,51 @@ export type SceneInstance = {
|
|
|
155
267
|
setProperties(props: Record<string, PropertyValue>): void;
|
|
156
268
|
/** 当前生效的属性值(扁平化后的 name → value) */
|
|
157
269
|
getProperties(): Record<string, PropertyValue>;
|
|
270
|
+
/**
|
|
271
|
+
* 换音频频谱源。传 null 回落内置模拟源。
|
|
272
|
+
*
|
|
273
|
+
* 与挂载选项 `audio` 等价,但可在任何时刻调用 —— 宿主的频谱通道
|
|
274
|
+
* (SSE / 原生桥 / WebAudio)常常在 mount() 之后才就绪。
|
|
275
|
+
* **换场景不清空**:装一次对之后所有场景生效。
|
|
276
|
+
*
|
|
277
|
+
* scene 与 web 壁纸都生效(网页侧经 iframe shim 的音频泵拿到同一份数据)。
|
|
278
|
+
*/
|
|
279
|
+
setAudio(src: AudioSource | null): void;
|
|
280
|
+
/**
|
|
281
|
+
* 换系统媒体源(Now Playing)。传 null 回落内置模拟源。
|
|
282
|
+
*
|
|
283
|
+
* 与 `setAudio` 同纪律:**换场景不清空**,装一次对之后所有场景生效。
|
|
284
|
+
* scene 与 web 壁纸吃同一个实例。
|
|
285
|
+
*/
|
|
286
|
+
setMedia(src: MediaSource | null): void;
|
|
287
|
+
/**
|
|
288
|
+
* 媒体控制面:读当前快照,以及壁纸侧同款的播放控制。
|
|
289
|
+
*
|
|
290
|
+
* 调用控制方法会转发给当前 media 源并**立即重新派发一次事件**,
|
|
291
|
+
* 壁纸里的歌名/封面/进度会同帧更新,不必等下一轮 diff。
|
|
292
|
+
*/
|
|
293
|
+
readonly media: MediaControl;
|
|
294
|
+
/**
|
|
295
|
+
* 外部指针注入:把宿主轮询到的鼠标位置推进壁纸。
|
|
296
|
+
*
|
|
297
|
+
* 用于窗口收不到鼠标事件的场景 —— 桌面壁纸叠在桌面 underlay 层,
|
|
298
|
+
* macOS 下 Finder 的桌面窗口会吃掉事件,且没有「向下透传」的窗口属性。
|
|
299
|
+
*
|
|
300
|
+
* @param u 归一化横坐标 0..1(相对画布左缘)
|
|
301
|
+
* @param v 归一化纵坐标 0..1(相对画布上缘,y 向下)
|
|
302
|
+
* @param buttons 按键位掩码,同 MouseEvent.buttons;只有 bit0(左键)被消费
|
|
303
|
+
*
|
|
304
|
+
* 与 canvas 自身的 DOM 指针监听并存,谁后写谁赢。scene 与 web 壁纸都生效,
|
|
305
|
+
* 媒体壁纸(video/gif/image)没有指针概念,调用静默无效。
|
|
306
|
+
*/
|
|
307
|
+
pushPointer(u: number, v: number, buttons?: number): void;
|
|
308
|
+
/**
|
|
309
|
+
* 外部指针离开本窗口(鼠标移到了别的显示器)。
|
|
310
|
+
*
|
|
311
|
+
* **只清按键,保留最后位置** —— 清掉位置会让 xray 开窗跳到相机外、
|
|
312
|
+
* 视差弹回中心,画面明显抽一下。语义与 DOM 的 mouseleave 一致。
|
|
313
|
+
*/
|
|
314
|
+
pointerLeave(): void;
|
|
158
315
|
/** 换场景,复用同一 canvas 与 WebGL 上下文 */
|
|
159
316
|
load(source: Source): Promise<void>;
|
|
160
317
|
/** 释放 GL/视频/音频资源,保留配置(显示器睡眠等场景) */
|
package/webwallgl.d.ts
CHANGED
|
@@ -4,30 +4,50 @@
|
|
|
4
4
|
// (tsc 自动生成到 dist/lib/types,构建时由 build:lib 拷贝拼接)。
|
|
5
5
|
// 改 api/mount.ts / api/source.ts 的**函数签名**时必须同步本文件 ——
|
|
6
6
|
// 类型本体(MountOptions/SceneInstance/Source 等)改 api/types.ts 即可自动带出。
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
//
|
|
8
|
+
// ⚠️ 必须 import 后再 export,不能写成 `export { type X } from "./types"`:
|
|
9
|
+
// 后者只做转发导出,**不把名字引入本文件作用域**,下面的函数签名会引用到
|
|
10
|
+
// 未定义标识符(tsc 报 TS2304 × 7)。消费方普遍开着 skipLibCheck,报错被吞掉,
|
|
11
|
+
// 症状是所有导出静默退化成 any —— 库看起来"能用",实则零类型检查。
|
|
12
|
+
import type {
|
|
13
|
+
Fit,
|
|
14
|
+
Source,
|
|
15
|
+
MountOptions,
|
|
16
|
+
SceneInstance,
|
|
17
|
+
SceneInfo,
|
|
18
|
+
SceneEvents,
|
|
19
|
+
FrameStats,
|
|
20
|
+
PropertyValue,
|
|
21
|
+
FeatureFlags,
|
|
22
|
+
PointerSource,
|
|
23
|
+
AudioSource,
|
|
24
|
+
MediaSource,
|
|
25
|
+
DiagnosticLevel,
|
|
22
26
|
} from "./types";
|
|
23
27
|
|
|
28
|
+
export type {
|
|
29
|
+
Fit,
|
|
30
|
+
Source,
|
|
31
|
+
MountOptions,
|
|
32
|
+
SceneInstance,
|
|
33
|
+
SceneInfo,
|
|
34
|
+
SceneEvents,
|
|
35
|
+
FrameStats,
|
|
36
|
+
PropertyValue,
|
|
37
|
+
FeatureFlags,
|
|
38
|
+
PointerSource,
|
|
39
|
+
AudioSource,
|
|
40
|
+
MediaSource,
|
|
41
|
+
DiagnosticLevel,
|
|
42
|
+
};
|
|
43
|
+
|
|
24
44
|
export declare function mount(
|
|
25
|
-
|
|
45
|
+
el: HTMLElement,
|
|
26
46
|
options: MountOptions,
|
|
27
47
|
): Promise<SceneInstance>;
|
|
28
48
|
|
|
29
49
|
export declare function createScene(
|
|
30
|
-
|
|
50
|
+
el: HTMLElement,
|
|
31
51
|
options?: Partial<Omit<MountOptions, "source">>,
|
|
32
52
|
): SceneInstance;
|
|
33
53
|
|