From 6e61fd81b3b9e5a96e6ae4bcab9e24a2d4d41155 Mon Sep 17 00:00:00 2001 From: yinsx Date: Sat, 27 Dec 2025 09:22:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=A1=A8=E6=83=85=E5=B9=85=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/3d/blendshapeAnimator.js | 19 +++++++++++++++---- examples/3d/expressionLibrary.js | 4 ++-- examples/3d/index.html | 9 +++++++-- examples/3d/main.js | 5 +++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/examples/3d/blendshapeAnimator.js b/examples/3d/blendshapeAnimator.js index 3bbb1c2..ba48496 100644 --- a/examples/3d/blendshapeAnimator.js +++ b/examples/3d/blendshapeAnimator.js @@ -36,7 +36,8 @@ class BlendShapeAnimator { this.expressionParams = config.expressionParams || { intervalMin: 3000, intervalMax: 8000, - speed: 400 + speed: 400, + strength: 1.0 }; this.enabledExpressions = new Set(); @@ -269,12 +270,20 @@ class BlendShapeAnimator { // 设置空闲动画 setIdleAnimation(name, target, duration = 200, easing = 'easeOutQuad') { + const currentValue = this.morphTargetAdapter + ? this.morphTargetAdapter.getInfluence(name) || 0 + : (this.idleAnimations[name]?.target || 0); + + const anim = this.idleAnimations[name] || {}; + const unchanged = Math.abs(currentValue - target) < 1e-4 && Math.abs((anim.target ?? 0) - target) < 1e-4; + this.idleAnimations[name] = { target: target, duration: duration, easing: easing, - startTime: null, - startValue: this.idleAnimations[name]?.target || 0 + // 如果目标基本不变,保持当前起点,避免反复重新插值导致抖动 + startTime: unchanged ? performance.now() : null, + startValue: currentValue }; } @@ -305,7 +314,9 @@ class BlendShapeAnimator { if (anim.target === 0) { delete this.idleAnimations[name]; } else { - anim.startTime = null; + // 目标保持不变,锁定在当前值,避免反复重新插值造成抖动 + anim.startValue = anim.target; + anim.startTime = now; } } } diff --git a/examples/3d/expressionLibrary.js b/examples/3d/expressionLibrary.js index ae9d9de..7691087 100644 --- a/examples/3d/expressionLibrary.js +++ b/examples/3d/expressionLibrary.js @@ -203,11 +203,11 @@ const ExpressionLibrary = { // 从主页面获取动画速度参数 const speed = window.expressionParams?.speed || 400; - + const strength = window.expressionParams?.strength ?? 1; // 应用表情 for (const [name, value] of Object.entries(expression.blendShapes)) { if (window.setIdleAnimation) { - window.setIdleAnimation(name, value, speed, 'easeInOutCubic'); + window.setIdleAnimation(name, value * strength, speed, 'easeInOutCubic'); } } diff --git a/examples/3d/index.html b/examples/3d/index.html index f48e110..7ecd1c2 100644 --- a/examples/3d/index.html +++ b/examples/3d/index.html @@ -142,11 +142,16 @@
- -
+
+ + +