# wallpaper-engine-web-dev-kit
[English](../README.md) | 简体中文
---
非官方 Wallpaper Engine **网页壁纸** 运行时模拟层 — 在浏览器中完整模拟 WE 注入的 API 行为。
## 用途
在浏览器开发 Wallpaper Engine 网页壁纸时,无需在 WE 编辑器中反复加载壁纸即可:
- 查看属性配置面板
- 调试音频可视化(模拟 128 元素频谱)
- 测试媒体集成(预置曲库 + 自定义曲目/封面)
- 预览 RGB LED 灯效(截获并解码 `setAllDevicesByImageData`)
- 模拟生命周期事件(pause/resume/FPS 变化)
- 从 `project.json` 读取属性定义,支持语言切换
## 使用方式
> 💡 **推荐方式:构建时注入** — 无需修改项目源码,自动将 dev-kit 注入已有壁纸项目。
### 构建时注入 ★ 推荐
将 we-dev-kit 注入现有壁纸项目的构建产物中,**无需修改项目源码**。适用于 CI/CD、一次性调试或为第三方项目添加开发工具。
> **前置条件:** 请先构建你的项目(例如 `vite build`、`webpack` 或 `tsc`)。`inputDir` 必须包含最终的构建产物(`index.html` + 资源文件)——`prepareDevBuild` 和 `injectIntoHtml` 操作的是**已经构建好的**产物。
**参数说明:**
- `inputDir` — **你的项目的构建产物目录**(如 `dist/`),即你的项目经过构建工具打包后生成的文件夹,里面必须有 `index.html`、JS/CSS、图片等资源文件
- `outputDir` — **开发用输出目录**(如 `dev/`)。`prepareDevBuild` 会把 `inputDir` 完整复制到这里,然后往 HTML 注入 dev-kit 脚本并复制 dev-kit 的 JS 文件。完成后直接打开此目录下的 `index.html` 即可调试,**不会修改你的原始构建产物**
> 流程:`inputDir` → 复制到 → `outputDir` → 注入 dev-kit → 打开 `outputDir/index.html` 调试
使用内置的 `inject` 模块,无需手写脚本:
```javascript
// scripts/build-dev.mjs
import { execSync } from 'node:child_process';
import { prepareDevBuild } from 'wallpaper-engine-web-dev-kit/inject';
// 1. 先构建项目(产物输出到 dist/)
execSync('vite build', { stdio: 'inherit' });
// inputDir('dist')此时必须包含构建好的 index.html 等文件
// 2. 一键注入:复制构建产物 + 注入 dev-kit 脚本
prepareDevBuild({
inputDir: 'dist', // ← 你的项目构建产物目录
outputDir: 'dev', // ← 注入 dev-kit 后的开发目录
config: { panel: true, audio: true, media: true, rgb: true, lifecycle: true },
});
```
或使用低阶 `injectIntoHtml` 自定义工作流——请确保先构建项目:
```javascript
import fs from 'node:fs';
import { injectIntoHtml } from 'wallpaper-engine-web-dev-kit/inject';
// 请确保 dist/index.html 存在(项目必须先构建)
const html = fs.readFileSync('dist/index.html', 'utf8');
fs.writeFileSync(
'dev/index.html',
injectIntoHtml(html, { config: { panel: true } }),
);
```
然后在 `package.json` 中添加脚本:
```json
"scripts": {
"build:dev": "node scripts/build-dev.mjs"
}
```
执行:
```bash
npm run build:dev
```
生成的 `dev/` 目录完全自包含 — 在浏览器中打开 `dev/index.html` 即可获得所有 WE API 的模拟环境,无需修改任何源文件。
---
### 模块导入(npm / TypeScript 项目)
```bash
npm install -D wallpaper-engine-web-dev-kit
```
```typescript
import { createWeDevKit } from 'wallpaper-engine-web-dev-kit';
const kit = createWeDevKit({
panel: { position: { x: 100, y: 50 } },
audio: { amplitude: 0.6, bassBoost: 1.2 },
media: { autoCycle: true, cycleIntervalMs: 8000 },
rgb: true,
lifecycle: true,
});
// 控制面板
kit.togglePanel();
// 媒体控制
kit.media.play();
kit.media.nextTrack();
// RGB 数据
kit.rgb.onFrame((frame) => console.log('RGB frame:', frame));
// 清理
kit.destroy();
```
### 浏览器直接引用(IIFE)
```html
```
### 构建产物引用
```bash
# 构建 dev-kit
npm run build
# 产物位于 dist/
# dist/index.global.js — IIFE(浏览器 script 标签)
# dist/index.js — ESM
# dist/index.cjs — CommonJS
# dist/index.d.ts — 类型定义
```
## 文档
- **[API.md](API.md)** — API 参考文档
包含完整 API 参考、类型定义、子控制器说明、构建时注入 API、Mp3Player 频谱播放器及 agent 使用示例。
## 功能特性
### 音频频谱模拟
128 元素频谱生成器,匹配 WE 规范(0-63 左声道、64-127 右声道),支持三种模式:
- **Beats** — 低频脉冲为主,带 bass boost 增益
- **Melody** — 更平滑的正弦波组合
- **Mixed** — 混合模式
支持振幅调节、帧率控制、渐进淡入淡出、帧间平滑过渡。
### 媒体集成模拟
完整模拟 WE Media Integration 全部 5 个 listener,预置 5 首曲库:
- 播放控制:播放/暂停/停止/切曲/进度控制
- 自定义元数据:覆盖曲目信息、上传封面图片
- 自动轮播:可配置轮换间隔
- 曲目切换时智能过滤(不发送 STOPPED 避免 UI 闪烁)
### RGB LED 数据
模拟 LED/CUE 插件加载机制,截获 `setAllDevicesByImageData` 调用:
- 解码原始像素数据为 `ImageData`(可用于 canvas 绘制)
- 自动提取调色板(网格量化,最多 8 色)
- 注册帧回调实时监听
- 手动模拟帧数据(无需依赖插件加载)
### 生命周期事件模拟
模拟 WE 暂停/恢复/FPS 变化等生命周期行为:
- 调用 `wallpaperPropertyListener.setPaused` 通知壁纸暂停状态
- 劫持 `requestAnimationFrame` / `setTimeout` / `setInterval`,暂停时积累队列,恢复时依次执行
- `destroy()` 时**自动恢复**所有被劫持的原始定时器函数
- FPS 变化通过 `applyGeneralProperties` 推送
- 暂停时自动注入 CSS 规则暂停动画(`animation-play-state: paused`)
### 属性配置控制
从 `project.json` 读取 `general.properties` 定义,通过 `kit.properties.*` API 提供:
- 属性定义查询:类型、值范围、选项列表
- 可见性条件求值:解析 `.value == X` / `&&` / `||` 等表达式(返回 `blockedBy`/`blockedValue`)
- 翻译键丢失检查:定位未翻译的 UI 文本
- 属性增删改:`addProperty()` / `updateProperty()` / `removeProperty()`
- 多语言匹配:按浏览器语言精确匹配 → 语言前缀 → 回退到 en-us
### 控制面板
可视化调试面板,Shadow DOM 隔离宿主页面 CSS 污染:
- **音频模拟控制** — 振幅/低频增益/速度/模式切换(Beats/Melody/Mixed),音频输入开关
- **媒体播放控制** — 播放/暂停/切曲/自定义曲目/上传封面
- **RGB 数据实时监控** — 等待状态显示
- **生命周期控制** — 暂停/恢复/FPS 限制设置
- **属性查看器** — 搜索、类型筛选(Bool/Slider/Color 等)、可见性筛选(全部/可见/隐藏)、翻译状态筛选(全部/缺失/正常)、键名/名称切换显示
- **属性编辑器弹窗 V2** — 浮动可拖拽窗口,支持添加/编辑/删除属性:
- 键名自动生成 i18n 翻译键(驼峰 → 蛇形)
- 翻译编辑器:批量编辑所有语言的翻译文本
- 类型切换时 confirm 提示防误操作
- Bool 用 checkbox 组,Slider 用 [range + number] 联动
- Color 用 picker + WE hex 同步
- Combo 选项表格(Label/Value 编辑,增删行)
- 翻译键状态提示(是否在 localization 字典中存在)
- **语言管理** — 语言切换下拉、新增语言下拉(支持 35+ WE 语言代码)、翻译缺失标记
- **Localization 面板** — 查看当前语言翻译字典的所有条目
- **时钟显示**、**最小化**、拖拽标题栏移动
#### 控制面板属性编辑弹窗
属性编辑弹窗 V2 实现了完整的 project.json 属性编辑体验:
- **基础**:键名(编辑模式锁定)、类型选择(9 种 WE 类型)
- **i18n**:自动翻译键生成、翻译编辑器(多语言批量编辑)、翻译状态提示
- **值控件**:Bool 双选 / Slider [range+number] / Color picker+WE hex / Combo 下拉预览 / Text/File/Directory/Group 文本输入
- **类型专属**:Slider 范围 (Min/Max/Step/Precision/Fraction)、File 视频模式、Directory 点播模式
- **Combo 选项**:Label + Value 表格编辑,增删行
- **元数据**:Order / Index / Condition
### 国际化 (i18n)
控制面板内置 en-US / zh-CN 双语界面,基于 `navigator.language` 自动选择。所有 UI 文本通过 `PanelMessages` 接口管理:
```typescript
import { getPanelMessages } from './panel/i18n';
// 自动根据浏览器语言返回对应翻译
console.log(getPanelMessages().amplitude); // "Amplitude" / "振幅"
```
属性编辑弹窗支持 **翻译编辑器**,可从 project.json 的 `general.localization` 中读取所有语言的翻译,并在编辑属性时批量修改多语言文本。
**语言策略**(project.json 读取时):
1. 精确匹配 `navigator.language`(如 `zh-CN`)
2. 语言前缀匹配(如 `zh`)
3. 回退到 `en-us`
4. 第一个可用语言
### 条件表达式求值器
`conditionEvaluator.ts` 完整支持 project.json 属性可见性条件语法:
- 比较:`.value == X`、`.value != X`
- 布尔值:`true`、`false`
- 数字:整数和浮点数
- 字符串:`'单引号'` 或 `"双引号"`
- 组合:`&&` (AND)、`||` (OR)
- 括号:`(expr)` 分组
```typescript
import { evaluateCondition } from './panel/conditionEvaluator';
// 检查 "showDate" 属性是否可见
const visible = evaluateCondition(
'showDate.value == true',
(key) => properties.find(p => p.key === key)?.value
);
```
### 环境自动检测
启动时自动判断运行环境,3 种检测策略:
1. CEF userAgent 特征
2. `wallpaperPropertyListener` 是否已被 WE 注入(区分 real WE 和 dev-kit mock)
3. 加载协议 + dev-kit 标志位
检测为真实 WE 环境时自动跳过模拟,不干扰正常壁纸运行。
### MP3 频谱播放器
Web Audio API 真实 MP3 播放与频谱提取,内置 DSP 处理流水线:
- 高斯平滑 + bin 级 EMA 时间计权消除突刺和闪烁
- 对数频带 RMS 合并(64 band,等比频率宽度)
- 频带间水平平滑 + band 级 EMA
- 峰值保持归一化,输出 Float32Array[128]
- 支持灵敏度/输出上限/循环播放等参数调节
### 音频数据传入开关
支持动态控制音频帧分发,启用时频谱数据推送到 `wallpaperRegisterAudioListener` 注册的回调,关闭时停止推送,不影响其他模块运行。
### wallpaperPropertyListener 补齐
自动补充 `setPaused`、`applyGeneralProperties`、`userDirectoryFilesAddedOrChanged`、`userDirectoryFilesRemoved` 方法,确保项目代码在浏览器中不会因缺少 WE API 而报错。使用 `Object.defineProperty` setter 拦截后续赋值,始终补齐缺失方法。
### 属性序列化
支持将当前属性列表序列化为 project.json 格式并导出下载。
## 项目结构
```
src/
index.ts # 主入口 createWeDevKit()
types.ts # 全部类型定义
inject.ts # 构建时注入工具(prepareDevBuild / injectIntoHtml)
environment.ts # 真实 WE 环境检测
propertyMock.ts # wallpaperPropertyListener 补充
audioSimulator.ts # 128 元素频谱生成器
audioBridge.ts # 音频状态机中枢(收敛 listener/帧分发/零帧归零/源切换)
mp3Player.ts # MP3 播放器 + 真实频谱提取(DSP 流水线)
mediaMock.ts # 媒体集成模拟(5 listener + 预置曲库)
rgbMock.ts # RGB LED 插件模拟
lifecycleMock.ts # 生命周期事件(含暂停 CSS 注入 + JS 定时器恢复)
panel/
index.ts # 控制面板控制器
renderer.ts # DOM 渲染(Shadow DOM 隔离)
styles.ts # 内联样式(含 V2 弹窗、翻译编辑器 CSS)
projectJsonReader.ts # project.json 属性解析 + 语言匹配 + 序列化导出
conditionEvaluator.ts# 条件表达式求值器(lexer + parser)
i18n.ts # 国际化字典(en-US / zh-CN)
callbacks.ts # 面板回调契约 + 类型定义
layout.ts # DOM 布局工具函数
sections/
audio.ts # 音频模拟控制 UI
media.ts # 媒体集成控制 UI
lifecycle.ts # 生命周期控制 UI
properties.ts # 属性查看器 UI(搜索/筛选/翻译/语言管理)
rgb.ts # RGB 数据监控 UI
modal/
propertyEditor.ts # 属性编辑弹窗 V2(拖拽/翻译编辑器/类型控件)
utils/
color.ts # 颜色工具(hex 转换、调色板提取)
dom.ts # DOM 工具(可拖拽宿主、Shadow DOM 容器)
imageData.ts # 像素 ↔ ImageData 互转 + SVG 封面生成
time.ts # 时间格式化 + debounce
windowPatching.ts # 通用 window 注入/还原工具
```
## 构建
```bash
npm install
npm run build # → dist/index.global.js + index.js + index.cjs + .d.ts
npm run dev # → watch 模式
```
## 许可证
GPL-3.0