Files
a2f-service/examples/3d/index.html
2025-12-25 15:36:35 +08:00

158 lines
7.5 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Digital Human - BlendShapes Demo</title>
<link rel="stylesheet" href="./styles.css">
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<script src="./blendshapeAnimator.js"></script>
<script src="./babylonAdapter.js"></script>
<script src="./babylonScene.js"></script>
<script src="./expressionLibrary.js"></script>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<div class="controls">
<h2>数字人形态键控制</h2>
<div class="input-group">
<label>文字输入</label>
<textarea id="textInput" placeholder="输入文字生成动画...">君不见,黄河之水天上来,奔流到海不复回,君不见,高堂明镜悲白发,朝如青丝暮成雪。</textarea>
</div>
<div class="input-group">
<label>API 地址</label>
<input type="text" id="apiUrl" value="http://localhost:5001/text-to-blendshapes">
</div>
<div class="input-group toggle-group">
<label>
<input type="checkbox" id="streamEnabled" checked>
启用流式传输
</label>
</div>
<div class="input-group">
<label>形态键强度: <span id="scaleValue">1.0</span></label>
<input type="range" id="scaleSlider" min="0" max="2" step="0.1" value="1.0"
oninput="updateScale(this.value)"
style="width: 100%; cursor: pointer;">
</div>
<div class="input-group">
<label>动画速度 (FPS): <span id="fpsValue">30</span></label>
<input type="range" id="fpsSlider" min="10" max="60" step="1" value="30"
oninput="updateFps(this.value)"
style="width: 100%; cursor: pointer;">
</div>
<button id="generateBtn" onclick="generateAnimation()">生成动画</button>
<button onclick="playAnimation()">播放动画</button>
<button onclick="stopAnimation()">停止动画</button>
<button onclick="testBlendShape()">测试形态键</button>
<button onclick="resetBlendShapes()">重置形态键</button>
<div class="status" id="status"></div>
</div>
<div class="idle-controls">
<h2>空闲动画控制</h2>
<!-- 随机眨眼 -->
<div class="checkbox-group">
<label>
<button class="collapse-btn" onclick="toggleCollapse(event, 'blinkParams')"></button>
<input type="checkbox" id="blinkEnabled" onchange="toggleBlink()">
<span>随机眨眼</span>
</label>
<div class="param-group" id="blinkParams">
<div class="param-item">
<label>频率间隔 (秒): <span class="param-value" id="blinkIntervalValue">1-2</span></label>
<input type="range" id="blinkIntervalMin" min="1" max="5" step="0.5" value="1"
oninput="updateBlinkInterval()">
<input type="range" id="blinkIntervalMax" min="2" max="10" step="0.5" value="2"
oninput="updateBlinkInterval()">
</div>
<div class="param-item">
<label>闭眼时长 (ms): <span class="param-value" id="blinkDurationValue">150</span></label>
<input type="range" id="blinkDuration" min="100" max="300" step="10" value="150"
oninput="updateBlinkDuration(this.value)">
</div>
<div class="param-item">
<label>动画速度 (ms): <span class="param-value" id="blinkSpeedValue">100</span></label>
<input type="range" id="blinkSpeed" min="50" max="200" step="10" value="100"
oninput="updateBlinkSpeed(this.value)">
</div>
</div>
</div>
<!-- 眼球移动 -->
<div class="checkbox-group">
<label>
<button class="collapse-btn" onclick="toggleCollapse(event, 'eyeLookParams')"></button>
<input type="checkbox" id="eyeLookEnabled" onchange="toggleEyeLook()">
<span>眼球移动</span>
</label>
<div class="param-group" id="eyeLookParams">
<div class="param-item">
<label>频率间隔 (秒): <span class="param-value" id="eyeLookIntervalValue">1-2</span></label>
<input type="range" id="eyeLookIntervalMin" min="1" max="5" step="0.5" value="1"
oninput="updateEyeLookInterval()">
<input type="range" id="eyeLookIntervalMax" min="2" max="10" step="0.5" value="2"
oninput="updateEyeLookInterval()">
</div>
<div class="param-item">
<label>停留时长 (ms): <span class="param-value" id="eyeLookDurationValue">1000-2500</span></label>
<input type="range" id="eyeLookDurationMin" min="500" max="2000" step="100" value="1000"
oninput="updateEyeLookDuration()">
<input type="range" id="eyeLookDurationMax" min="1000" max="4000" step="100" value="2500"
oninput="updateEyeLookDuration()">
</div>
<div class="param-item">
<label>移动速度 (ms): <span class="param-value" id="eyeLookSpeedValue">250</span></label>
<input type="range" id="eyeLookSpeed" min="100" max="500" step="25" value="250"
oninput="updateEyeLookSpeed(this.value)">
</div>
</div>
</div>
<!-- 随机表情 -->
<div class="checkbox-group">
<label>
<button class="collapse-btn" onclick="toggleCollapse(event, 'expressionParams')"></button>
<input type="checkbox" id="expressionEnabled" onchange="toggleRandomExpression()">
<span>随机表情</span>
</label>
<div class="param-group" id="expressionParams">
<div class="param-item">
<label>选择表情:</label>
<div class="expression-list" id="expressionList">
<!-- 动态生成 -->
</div>
</div>
<div class="param-item">
<label>频率间隔 (秒): <span class="param-value" id="expressionIntervalValue">1-1</span></label>
<input type="range" id="expressionIntervalMin" min="1" max="8" step="0.5" value="1"
oninput="updateExpressionInterval()">
<input type="range" id="expressionIntervalMax" min="1" max="15" step="0.5" value="1"
oninput="updateExpressionInterval()">
</div>
<div class="param-item">
<label>动画速度 (ms): <span class="param-value" id="expressionSpeedValue">400</span></label>
<input type="range" id="expressionSpeed" min="200" max="800" step="50" value="400"
oninput="updateExpressionSpeed(this.value)">
</div>
</div>
</div>
</div>
<script src="./main.js"></script>
</body>
</html>