From e56f47076c66a5bd55d163a8df726565a54e08cd Mon Sep 17 00:00:00 2001 From: yinsx Date: Thu, 25 Dec 2025 09:46:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/3d/blendshapeAnimator.js | 18 +++++++++++++++--- examples/3d/expressionLibrary.js | 17 ++++++++++------- examples/3d/index.html | 18 +++++++++--------- examples/3d/main.js | 2 ++ 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/examples/3d/blendshapeAnimator.js b/examples/3d/blendshapeAnimator.js index 94da996..6c6d25e 100644 --- a/examples/3d/blendshapeAnimator.js +++ b/examples/3d/blendshapeAnimator.js @@ -231,7 +231,12 @@ class BlendShapeAnimator { this.blinkInterval = setTimeout(() => { if (this.isBlinkEnabled) { this._doBlink(); - scheduleNext(); + const holdDuration = Math.max(0, this.blinkParams.duration || 0); + this.blinkInterval = setTimeout(() => { + if (this.isBlinkEnabled) { + scheduleNext(); + } + }, holdDuration); } }, delay); }; @@ -281,8 +286,13 @@ class BlendShapeAnimator { const delay = this.eyeLookParams.intervalMin + Math.random() * (this.eyeLookParams.intervalMax - this.eyeLookParams.intervalMin); this.eyeLookInterval = setTimeout(() => { if (this.isEyeLookEnabled) { - this._doRandomEyeLook(); - scheduleNext(); + const holdDuration = this._doRandomEyeLook(); + const waitDuration = Math.max(0, holdDuration || 0); + this.eyeLookInterval = setTimeout(() => { + if (this.isEyeLookEnabled) { + scheduleNext(); + } + }, waitDuration); } }, delay); }; @@ -330,6 +340,8 @@ class BlendShapeAnimator { }); } }, holdDuration); + + return holdDuration; } _resetEyeLook() { diff --git a/examples/3d/expressionLibrary.js b/examples/3d/expressionLibrary.js index 1df9e4a..c3791cb 100644 --- a/examples/3d/expressionLibrary.js +++ b/examples/3d/expressionLibrary.js @@ -131,6 +131,7 @@ const ExpressionLibrary = { enabled: false, timeout: null, currentExpression: null, + lastExpressionKey: null, intervalMin: 3000, intervalMax: 8000, @@ -170,7 +171,10 @@ const ExpressionLibrary = { 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]; this.play(expression); @@ -178,6 +182,9 @@ const ExpressionLibrary = { play: function(expression) { this.currentExpression = expression; + this.lastExpressionKey = Object.keys(ExpressionLibrary.expressions).find( + key => ExpressionLibrary.expressions[key] === expression + ); // 从主页面获取动画速度参数 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; setTimeout(() => { this.reset(); + if (!this.enabled) return; this.scheduleNext(); }, duration); }, diff --git a/examples/3d/index.html b/examples/3d/index.html index 051f729..bc59670 100644 --- a/examples/3d/index.html +++ b/examples/3d/index.html @@ -65,10 +65,10 @@
- - 频率间隔 (秒): 1-2 + -
@@ -93,10 +93,10 @@
- - 频率间隔 (秒): 1-2 + -
@@ -129,10 +129,10 @@
- - 频率间隔 (秒): 1-1 + -
diff --git a/examples/3d/main.js b/examples/3d/main.js index 88bcea4..278badc 100644 --- a/examples/3d/main.js +++ b/examples/3d/main.js @@ -36,6 +36,8 @@ function init() { window.enabledExpressions = enabledExpressions; window.expressionDurations = expressionDurations; + updateExpressionInterval(); + // 加载3D模型 sceneManager.loadModel('head_a01.glb', (meshes) => {