This commit is contained in:
yinsx
2025-12-25 09:46:16 +08:00
parent 48d587c1ff
commit e56f47076c
4 changed files with 36 additions and 19 deletions

View File

@ -231,7 +231,12 @@ class BlendShapeAnimator {
this.blinkInterval = setTimeout(() => { this.blinkInterval = setTimeout(() => {
if (this.isBlinkEnabled) { if (this.isBlinkEnabled) {
this._doBlink(); this._doBlink();
scheduleNext(); const holdDuration = Math.max(0, this.blinkParams.duration || 0);
this.blinkInterval = setTimeout(() => {
if (this.isBlinkEnabled) {
scheduleNext();
}
}, holdDuration);
} }
}, delay); }, delay);
}; };
@ -281,8 +286,13 @@ class BlendShapeAnimator {
const delay = this.eyeLookParams.intervalMin + Math.random() * (this.eyeLookParams.intervalMax - this.eyeLookParams.intervalMin); const delay = this.eyeLookParams.intervalMin + Math.random() * (this.eyeLookParams.intervalMax - this.eyeLookParams.intervalMin);
this.eyeLookInterval = setTimeout(() => { this.eyeLookInterval = setTimeout(() => {
if (this.isEyeLookEnabled) { if (this.isEyeLookEnabled) {
this._doRandomEyeLook(); const holdDuration = this._doRandomEyeLook();
scheduleNext(); const waitDuration = Math.max(0, holdDuration || 0);
this.eyeLookInterval = setTimeout(() => {
if (this.isEyeLookEnabled) {
scheduleNext();
}
}, waitDuration);
} }
}, delay); }, delay);
}; };
@ -330,6 +340,8 @@ class BlendShapeAnimator {
}); });
} }
}, holdDuration); }, holdDuration);
return holdDuration;
} }
_resetEyeLook() { _resetEyeLook() {

View File

@ -131,6 +131,7 @@ const ExpressionLibrary = {
enabled: false, enabled: false,
timeout: null, timeout: null,
currentExpression: null, currentExpression: null,
lastExpressionKey: null,
intervalMin: 3000, intervalMin: 3000,
intervalMax: 8000, intervalMax: 8000,
@ -170,7 +171,10 @@ const ExpressionLibrary = {
return; return;
} }
const randomKey = enabledKeys[Math.floor(Math.random() * enabledKeys.length)]; const availableKeys = enabledKeys.length > 1 && this.lastExpressionKey
? enabledKeys.filter(key => key !== this.lastExpressionKey)
: enabledKeys;
const randomKey = availableKeys[Math.floor(Math.random() * availableKeys.length)];
const expression = ExpressionLibrary.expressions[randomKey]; const expression = ExpressionLibrary.expressions[randomKey];
this.play(expression); this.play(expression);
@ -178,6 +182,9 @@ const ExpressionLibrary = {
play: function(expression) { play: function(expression) {
this.currentExpression = expression; this.currentExpression = expression;
this.lastExpressionKey = Object.keys(ExpressionLibrary.expressions).find(
key => ExpressionLibrary.expressions[key] === expression
);
// 从主页面获取动画速度参数 // 从主页面获取动画速度参数
const speed = window.expressionParams?.speed || 400; const speed = window.expressionParams?.speed || 400;
@ -189,17 +196,13 @@ const ExpressionLibrary = {
} }
} }
// 获取表情的key
const expressionKey = Object.keys(ExpressionLibrary.expressions).find(
key => ExpressionLibrary.expressions[key] === expression
);
// 使用用户设置的持续时间,如果没有则使用表情默认时间 // 使用用户设置的持续时间,如果没有则使用表情默认时间
const duration = (window.expressionDurations && window.expressionDurations[expressionKey]) const duration = (window.expressionDurations && window.expressionDurations[this.lastExpressionKey])
|| expression.duration; || expression.duration;
setTimeout(() => { setTimeout(() => {
this.reset(); this.reset();
if (!this.enabled) return;
this.scheduleNext(); this.scheduleNext();
}, duration); }, duration);
}, },

View File

@ -65,10 +65,10 @@
</label> </label>
<div class="param-group" id="blinkParams"> <div class="param-group" id="blinkParams">
<div class="param-item"> <div class="param-item">
<label>频率间隔 (秒): <span class="param-value" id="blinkIntervalValue">2-5</span></label> <label>频率间隔 (秒): <span class="param-value" id="blinkIntervalValue">1-2</span></label>
<input type="range" id="blinkIntervalMin" min="1" max="5" step="0.5" value="2" <input type="range" id="blinkIntervalMin" min="1" max="5" step="0.5" value="1"
oninput="updateBlinkInterval()"> oninput="updateBlinkInterval()">
<input type="range" id="blinkIntervalMax" min="3" max="10" step="0.5" value="5" <input type="range" id="blinkIntervalMax" min="2" max="10" step="0.5" value="2"
oninput="updateBlinkInterval()"> oninput="updateBlinkInterval()">
</div> </div>
<div class="param-item"> <div class="param-item">
@ -93,10 +93,10 @@
</label> </label>
<div class="param-group" id="eyeLookParams"> <div class="param-group" id="eyeLookParams">
<div class="param-item"> <div class="param-item">
<label>频率间隔 (秒): <span class="param-value" id="eyeLookIntervalValue">2-6</span></label> <label>频率间隔 (秒): <span class="param-value" id="eyeLookIntervalValue">1-2</span></label>
<input type="range" id="eyeLookIntervalMin" min="1" max="5" step="0.5" value="2" <input type="range" id="eyeLookIntervalMin" min="1" max="5" step="0.5" value="1"
oninput="updateEyeLookInterval()"> oninput="updateEyeLookInterval()">
<input type="range" id="eyeLookIntervalMax" min="3" max="10" step="0.5" value="6" <input type="range" id="eyeLookIntervalMax" min="2" max="10" step="0.5" value="2"
oninput="updateEyeLookInterval()"> oninput="updateEyeLookInterval()">
</div> </div>
<div class="param-item"> <div class="param-item">
@ -129,10 +129,10 @@
</div> </div>
</div> </div>
<div class="param-item"> <div class="param-item">
<label>频率间隔 (秒): <span class="param-value" id="expressionIntervalValue">3-8</span></label> <label>频率间隔 (秒): <span class="param-value" id="expressionIntervalValue">1-1</span></label>
<input type="range" id="expressionIntervalMin" min="2" max="8" step="0.5" value="3" <input type="range" id="expressionIntervalMin" min="1" max="8" step="0.5" value="1"
oninput="updateExpressionInterval()"> oninput="updateExpressionInterval()">
<input type="range" id="expressionIntervalMax" min="5" max="15" step="0.5" value="8" <input type="range" id="expressionIntervalMax" min="1" max="15" step="0.5" value="1"
oninput="updateExpressionInterval()"> oninput="updateExpressionInterval()">
</div> </div>
<div class="param-item"> <div class="param-item">

View File

@ -36,6 +36,8 @@ function init() {
window.enabledExpressions = enabledExpressions; window.enabledExpressions = enabledExpressions;
window.expressionDurations = expressionDurations; window.expressionDurations = expressionDurations;
updateExpressionInterval();
// 加载3D模型 // 加载3D模型
sceneManager.loadModel('head_a01.glb', sceneManager.loadModel('head_a01.glb',
(meshes) => { (meshes) => {