Files
ChowBox/miniapp/components/box-animation/box-animation.wxss
王鹏 802b4ba229 fix: 修复 VoiceController Map.of 兼容性 + ExploreController 参数不匹配
- VoiceController: Map.of() -> Collections.singletonMap() 兼容 Java 8
- ExploreController: 补齐 takeoutService.roll() 缺失的 taste/priceRange/allergies 参数

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-08 20:02:27 +08:00

305 lines
7.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 开盒动效 · 三幕分镜
* 参考 doc/box.md
*
* Act 1 (0400ms): 光晕扩散 + 盒子震动 + 背景变暗
* Act 2 (4001000ms): 盒盖飞起 + 金色光芒 + 粒子溅射 + 白色闪屏
* Act 3 (10001800ms): 内容弹性弹出 + 彩带纸屑
*
* 总时长约 1.82.0s
*/
/* ═══ 覆盖层 ═══ */
.animation-overlay {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}
.animation-overlay.visible {
pointer-events: auto;
}
/* ═══ 背景变暗 ═══ */
.bg-dimmer {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0, 0, 0, 0.55);
opacity: 0;
transition: opacity 0.4s ease-out;
}
.bg-dimmer.active {
opacity: 1;
}
/* ════════════════════════
Act 1 · 光晕扩散 (0400ms)
════════════════════════ */
.act1-glow-ring {
position: absolute;
width: 320rpx;
height: 320rpx;
border-radius: 50%;
opacity: 0;
transform: scale(0.15);
}
.act1-glow-ring.active {
animation: glowExpand 0.5s ease-out forwards;
}
.glow-inner {
width: 100%;
height: 100%;
border-radius: 50%;
}
/* 模式颜色 */
.box-takeout .glow-inner {
background: radial-gradient(circle, #E8693B 0%, rgba(232,105,59,0.4) 35%, transparent 70%);
}
.box-fridge .glow-inner {
background: radial-gradient(circle, #4CAF50 0%, rgba(76,175,80,0.4) 35%, transparent 70%);
}
.box-explore .glow-inner {
background: radial-gradient(circle, #7C3AED 0%, rgba(124,58,237,0.4) 35%, transparent 70%);
}
@keyframes glowExpand {
0% { opacity: 0.9; transform: scale(0.15); }
50% { opacity: 0.6; transform: scale(1.5); }
100% { opacity: 0; transform: scale(3.2); }
}
/* ════════════════════════
Act 1 · 盒子震动
════════════════════════ */
.box-stage {
position: relative;
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
opacity: 0;
transform: scale(0.85);
transition: opacity 0.15s ease, transform 0.15s ease;
}
.box-stage.active {
opacity: 1;
transform: scale(1);
}
/* ── 盒盖 ── */
.box-lid {
position: relative;
z-index: 3;
margin-bottom: -12rpx;
transition: transform 0.35s ease-in, opacity 0.35s ease-in;
transition-delay: 0.05s;
}
.lid-top {
width: 120rpx;
height: 40rpx;
background: linear-gradient(180deg, #F5A623 0%, #E8961A 100%);
border-radius: 20rpx 20rpx 4rpx 4rpx;
box-shadow: 0 4rpx 16rpx rgba(200, 120, 20, 0.4);
}
.box-lid.active {
transform: translateY(-80rpx) rotate(-8deg);
opacity: 0;
}
/* ── 金色光芒 ── */
.golden-light {
position: absolute;
z-index: 1;
width: 200rpx;
height: 200rpx;
border-radius: 50%;
opacity: 0;
transform: scale(0.3);
}
.box-takeout .golden-light {
background: radial-gradient(circle, #FFD54F 0%, rgba(255, 180, 50, 0.6) 30%, transparent 65%);
}
.box-fridge .golden-light {
background: radial-gradient(circle, #A5D6A7 0%, rgba(76, 175, 80, 0.5) 30%, transparent 65%);
}
.box-explore .golden-light {
background: radial-gradient(circle, #CE93D8 0%, rgba(124, 58, 237, 0.5) 30%, transparent 65%);
}
.golden-light.active {
animation: goldenBurst 0.6s ease-out forwards;
}
@keyframes goldenBurst {
0% { opacity: 0; transform: scale(0.3); }
30% { opacity: 1; transform: scale(1.8); }
100% { opacity: 0; transform: scale(3.5); }
}
/* ── 盒体Act2 压缩反弹) ── */
.box-body {
position: relative;
z-index: 2;
transition: transform 0.25s ease-out;
}
.box-body.compressed {
animation: bodyCompress 0.3s ease-out;
}
.box-emoji {
font-size: 160rpx;
display: block;
}
@keyframes bodyCompress {
0% { transform: scaleY(1); }
40% { transform: scaleY(0.85); }
100% { transform: scaleY(1); }
}
/* ── 粒子溅射Act2 ── */
.spark-particles {
position: absolute;
z-index: 0;
top: 50%; left: 50%;
width: 0; height: 0;
pointer-events: none;
}
.spark-particles.active .spark {
animation: sparkBurst 0.7s ease-out forwards;
}
.spark {
position: absolute;
font-size: 32rpx;
opacity: 0;
}
.spark.s1 { animation-delay: 0s !important; }
.spark.s2 { animation-delay: 0.06s !important; }
.spark.s3 { animation-delay: 0.12s !important; }
.spark.s4 { animation-delay: 0.18s !important; }
@keyframes sparkBurst {
0% { opacity: 1; transform: translate(0, 0) scale(0.5); }
100% { opacity: 0; transform: translate(var(--sx, 60rpx), var(--sy, -80rpx)) scale(1.2); }
}
.box-takeout .spark { --sx: 70rpx; --sy: -90rpx; }
.box-takeout .spark.s2 { --sx: -60rpx; --sy: -70rpx; }
.box-takeout .spark.s3 { --sx: 50rpx; --sy: -100rpx; }
.box-takeout .spark.s4 { --sx: -80rpx; --sy: -80rpx; }
.box-fridge .spark { --sx: 70rpx; --sy: -90rpx; }
.box-fridge .spark.s2 { --sx: -60rpx; --sy: -70rpx; }
.box-fridge .spark.s3 { --sx: 50rpx; --sy: -100rpx; }
.box-fridge .spark.s4 { --sx: -80rpx; --sy: -80rpx; }
.box-explore .spark { --sx: 70rpx; --sy: -90rpx; }
.box-explore .spark.s2 { --sx: -60rpx; --sy: -70rpx; }
.box-explore .spark.s3 { --sx: 50rpx; --sy: -100rpx; }
.box-explore .spark.s4 { --sx: -80rpx; --sy: -80rpx; }
/* ════════════════════════
Act 2 · 白色闪屏 (6001000ms)
════════════════════════ */
.act2-mask {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: #FFFFFF;
opacity: 0;
pointer-events: none;
}
.act2-mask.active {
animation: maskFlash 0.5s ease-in-out forwards;
animation-delay: 0.2s;
}
@keyframes maskFlash {
0% { opacity: 0; }
45% { opacity: 0.92; }
100% { opacity: 0; }
}
/* ════════════════════════
Act 3 · 内容弹性弹出 (10001800ms)
════════════════════════ */
.act3-content {
position: relative;
z-index: 20;
opacity: 0;
transform: scale(0.85) translateY(30rpx);
}
.act3-content.active {
animation: contentReveal 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
.content-inner {
display: flex;
flex-direction: column;
align-items: center;
}
@keyframes contentReveal {
0% { opacity: 0; transform: scale(0.85) translateY(30rpx); }
100% { opacity: 1; transform: scale(1) translateY(0); }
}
/* ════════════════════════
Act 3 · 彩带纸屑 (1600ms+)
════════════════════════ */
.confetti-stage {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
pointer-events: none;
overflow: hidden;
}
.confetti-stage.active .confetti {
animation: confettiDrop 1.4s ease-in forwards;
}
.confetti {
position: absolute;
top: -20rpx;
left: var(--x, 20%);
width: 14rpx;
height: 14rpx;
border-radius: 3rpx;
background: var(--c, #E8693B);
opacity: 0;
animation-delay: var(--d, 0s);
}
@keyframes confettiDrop {
0% { opacity: 1; transform: translateY(0) rotate(0deg) scale(1); }
30% { opacity: 0.9; transform: translateY(280rpx) rotate(180deg) scale(0.7); }
60% { opacity: 0.5; transform: translateY(600rpx) rotate(400deg) scale(0.4); }
100% { opacity: 0; transform: translateY(1000rpx) rotate(720deg) scale(0.1); }
}