Skip to content

Commit 58ceb0d

Browse files
committed
修复模型猫过渡审查问题
- 过渡 Promise 失败时记录警告并清理 return ball transition 标记。\n- 抽取模型容器 transition CSS 变量,并补齐 VRM 缩放 transform-origin。\n- 补充 VRM goodbye 统一链路断言和 CSS helper 说明。
1 parent 520d0ac commit 58ceb0d

4 files changed

Lines changed: 32 additions & 6 deletions

File tree

static/avatar-ui-buttons.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3883,7 +3883,10 @@ const AvatarButtonMixin = {
38833883
anchorRect: rect,
38843884
coverRect: window._savedGoodbyeRect || null,
38853885
container: returnButtonContainer
3886-
}).catch(() => {});
3886+
}).catch((error) => {
3887+
console.warn('[AvatarButtonMixin] model/cat return transition failed:', error);
3888+
returnButtonContainer.removeAttribute('data-neko-model-cat-transitioning');
3889+
});
38873890
dispatchReturnEvent();
38883891
return;
38893892
}

static/css/index.css

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
@import url('base.css');
22

3+
:root {
4+
--neko-model-opacity-transition: opacity 280ms ease-in;
5+
--neko-model-transform-transition: transform 400ms cubic-bezier(0.22, 1, 0.36, 1);
6+
--neko-model-visibility-delay: 400ms;
7+
}
8+
39
html,
410
body {
511
height: 100%;
@@ -233,7 +239,7 @@ button * {
233239
opacity: 1;
234240
overflow: hidden;
235241
visibility: visible;
236-
transition: opacity 280ms ease-in, transform 400ms cubic-bezier(0.22, 1, 0.36, 1), height 0ms 400ms, width 0ms 400ms, visibility 0ms 400ms;
242+
transition: var(--neko-model-opacity-transition), var(--neko-model-transform-transition), height 0ms var(--neko-model-visibility-delay), width 0ms var(--neko-model-visibility-delay), visibility 0ms var(--neko-model-visibility-delay);
237243
/* GPU 合成层隔离:减少窗口级重绘对 canvas 的影响 */
238244
will-change: transform;
239245
transform: translateZ(0);
@@ -293,10 +299,11 @@ button * {
293299
/* 【修复】仅过渡 opacity 和 transform,排除 visibility 的过渡影响,
294300
* 避免 MMD 模式下隐藏 VRM 容器时因 transition: all 导致约 1s 的视觉
295301
* 残留窗口,使 VRM canvas 中缓存的旧模型(如 sister1.0)短暂可见。 */
296-
transition: opacity 280ms ease-in, transform 400ms cubic-bezier(0.22, 1, 0.36, 1);
302+
transition: var(--neko-model-opacity-transition), var(--neko-model-transform-transition);
297303
/* GPU 合成层隔离:减少窗口级重绘对 canvas 的影响 */
298304
will-change: transform;
299305
transform: translateZ(0);
306+
transform-origin: var(--neko-model-exit-origin-x, 50%) var(--neko-model-exit-origin-y, 50%);
300307
}
301308

302309
/* 看板娘MMD模型判定框-容器 */
@@ -314,7 +321,7 @@ button * {
314321
opacity: 1;
315322
overflow: hidden;
316323
visibility: visible;
317-
transition: opacity 280ms ease-in, transform 400ms cubic-bezier(0.22, 1, 0.36, 1);
324+
transition: var(--neko-model-opacity-transition), var(--neko-model-transform-transition);
318325
/* GPU 合成层隔离 */
319326
will-change: transform;
320327
transform: translateZ(0);

tests/unit/test_auto_goodbye_goodbye_return_contract.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def test_auto_goodbye_reuses_existing_goodbye_base_chain():
2626
assert "function playModelGoodbyeExit(container, rect)" in ui_source
2727
assert "playModelGoodbyeExit(live2dContainerForGoodbye, savedGoodbyeRect)" in ui_source
2828
assert "playModelGoodbyeExit(mmdContainer, savedGoodbyeRect)" in ui_source
29+
assert "playModelGoodbyeExit(vrmContainer, savedGoodbyeRect)" in ui_source
2930
assert "container.classList.add('minimized');" in ui_source
3031
assert "resetSessionButton.disabled = false;\n resetSessionButton.click();" in ui_source
3132

tests/unit/test_avatar_return_button_idle_tiers_static.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,13 @@ def test_model_goodbye_exit_shrinks_in_place_instead_of_sliding_right():
167167
assert "#vrm-container.minimized" in source
168168
assert "#mmd-container.minimized" in source
169169
assert "transform: scale(0.38) translateZ(0);" in source
170-
assert "opacity 280ms ease-in, transform 400ms cubic-bezier(0.22, 1, 0.36, 1)" in source
171-
assert "height 0ms 400ms" in source
170+
assert "--neko-model-opacity-transition: opacity 280ms ease-in;" in source
171+
assert "--neko-model-transform-transition: transform 400ms cubic-bezier(0.22, 1, 0.36, 1);" in source
172+
assert "--neko-model-visibility-delay: 400ms;" in source
173+
assert "transition: var(--neko-model-opacity-transition), var(--neko-model-transform-transition)" in source
174+
assert "height 0ms var(--neko-model-visibility-delay)" in source
172175
assert "transform-origin: var(--neko-model-exit-origin-x, 50%) var(--neko-model-exit-origin-y, 50%);" in source
176+
assert source.count("transform-origin: var(--neko-model-exit-origin-x, 50%) var(--neko-model-exit-origin-y, 50%);") >= 3
173177
assert "function setModelExitTransformOrigin(container, rect)" in app_ui_source
174178
assert "function playModelGoodbyeExit(container, rect)" in app_ui_source
175179
assert "function applyModelGoodbyeVisualFade(container, options = {})" in app_ui_source
@@ -521,6 +525,17 @@ def test_no_box_shadow_or_border_in_base_return_btn_css():
521525

522526

523527
def _extract_css_block(source, selector):
528+
"""Extract a selector's CSS block body from source.
529+
530+
Args:
531+
source: CSS source string to search.
532+
selector: Selector text whose following brace-delimited block is read.
533+
534+
Returns:
535+
The string inside the matched braces, or '' when the selector/opening
536+
brace/closing brace is not found. Nested braces are handled with
537+
brace-depth tracking.
538+
"""
524539
start = source.find(selector)
525540
if start == -1:
526541
return ''

0 commit comments

Comments
 (0)