包含三个子项目: - avatar-h5-renderer: Live2D Cubism 4 H5 渲染器 (Vite + TS) - avatar_flutter_app: Flutter 容器 App (打包 H5 进 WebView) - gif-export: puppeteer 导出 32 个动作的透明 GIF (供 ESP32 圆屏播放) 模型资源: Haru, Natori (含贴图、moc3、motions, expressions) 设计文档: AI驱动虚拟形象渲染方案_v5.1.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
190 lines
5.0 KiB
HTML
190 lines
5.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
|
<title>Avatar H5 Renderer (PoC)</title>
|
|
<style>
|
|
html, body {
|
|
overflow: hidden;
|
|
margin: 0;
|
|
height: 100%;
|
|
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
background: #1a1a1f;
|
|
}
|
|
body {
|
|
background-image: url('/back_class_normal.png');
|
|
background-size: cover;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
}
|
|
html {
|
|
overscroll-behavior-x: none;
|
|
touch-action: none;
|
|
}
|
|
body {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
body > canvas {
|
|
width: 100vw;
|
|
height: 100vh;
|
|
display: block;
|
|
}
|
|
|
|
/* 调试面板 */
|
|
#debug-panel {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0;
|
|
width: 320px;
|
|
max-height: 100vh;
|
|
overflow-y: auto;
|
|
padding: 16px;
|
|
box-sizing: border-box;
|
|
background: rgba(15, 15, 20, 0.85);
|
|
backdrop-filter: blur(10px);
|
|
color: #e5e5e5;
|
|
font-size: 13px;
|
|
line-height: 1.5;
|
|
border-left: 1px solid #333;
|
|
z-index: 999;
|
|
}
|
|
#debug-panel h3 {
|
|
margin: 0 0 8px;
|
|
font-size: 14px;
|
|
color: #80c0ff;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
#debug-panel section {
|
|
margin-bottom: 14px;
|
|
padding-bottom: 12px;
|
|
border-bottom: 1px solid #2a2a2f;
|
|
}
|
|
#debug-panel section:last-child { border-bottom: none; }
|
|
#debug-panel .row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 6px;
|
|
}
|
|
#debug-panel button {
|
|
padding: 6px 10px;
|
|
border: 1px solid #444;
|
|
background: #222;
|
|
color: #ddd;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
transition: all 0.12s;
|
|
}
|
|
#debug-panel button:hover {
|
|
background: #2d4a6b;
|
|
border-color: #5588cc;
|
|
color: #fff;
|
|
}
|
|
#debug-panel button.primary {
|
|
background: #2766b6;
|
|
border-color: #4488dd;
|
|
color: #fff;
|
|
}
|
|
#debug-panel button.primary:hover {
|
|
background: #3a85d6;
|
|
}
|
|
#debug-panel input[type=range] {
|
|
width: 100%;
|
|
margin-top: 6px;
|
|
}
|
|
#debug-panel .value {
|
|
color: #80c0ff;
|
|
font-family: ui-monospace, Menlo, monospace;
|
|
}
|
|
.hint {
|
|
font-size: 11px;
|
|
color: #888;
|
|
margin-top: 6px;
|
|
}
|
|
code {
|
|
color: #80c0ff;
|
|
font-family: ui-monospace, Menlo, monospace;
|
|
}
|
|
</style>
|
|
<!-- Live2D Cubism Core -->
|
|
<script src="/Core/live2dcubismcore.js"></script>
|
|
<!-- App entry -->
|
|
<script type="module" crossorigin src="/assets/index-BuJ0Zx2X.js"></script>
|
|
</head>
|
|
<body>
|
|
<div id="debug-panel">
|
|
<section>
|
|
<h3>角色状态</h3>
|
|
<div class="row">
|
|
<button data-act="state" data-arg="idle">idle 待机</button>
|
|
<button data-act="state" data-arg="listening">listening 倾听</button>
|
|
<button data-act="state" data-arg="thinking">thinking 思考</button>
|
|
<button data-act="state" data-arg="speaking">speaking 说话</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>表情切换</h3>
|
|
<div class="row" id="expression-buttons">
|
|
<span class="hint">加载中...</span>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>动作播放</h3>
|
|
<div class="row" id="motion-buttons">
|
|
<span class="hint">加载中...</span>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>嘴型驱动 <span class="value" id="mouth-value">0.00</span></h3>
|
|
<input type="range" id="mouth-slider" min="0" max="100" value="0">
|
|
<div class="row" style="margin-top:6px">
|
|
<button data-act="mouth" data-arg="0">闭</button>
|
|
<button data-act="mouth" data-arg="0.5">半开</button>
|
|
<button data-act="mouth" data-arg="1">全开</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>语义动作</h3>
|
|
<div class="row" id="action-buttons"></div>
|
|
<div class="hint">对应未来 LLM Function Call 触发</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>跳舞</h3>
|
|
<div class="row">
|
|
<button class="primary" data-act="dance-start">💃 开始跳舞</button>
|
|
<button data-act="dance-stop">停止</button>
|
|
</div>
|
|
<div class="hint">程序化驱动身体参数 + 循环切 Dance motion</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>事件模拟</h3>
|
|
<div class="row">
|
|
<button class="primary" data-act="mock-conversation">▶ 播放模拟对话</button>
|
|
</div>
|
|
<div class="hint">listening → thinking → 微笑+说话 → idle</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Console API</h3>
|
|
<div class="hint">
|
|
浏览器控制台可直接调:<br>
|
|
<code>avatar.setExpression("Smile")</code><br>
|
|
<code>avatar.playMotion("Idle", 0)</code><br>
|
|
<code>avatar.setMouthOpen(0.8)</code><br>
|
|
<code>avatar.listExpressions()</code><br>
|
|
<code>avatar.listMotions()</code>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|