Files
36-character-flower/docs/settlement-gold-border-animation.md
JiaJun 5768632313 feat(game): 添加动物精灵图像变体支持并优化揭示动画
- 引入 light-animal-sprite 图像资源和 variant 属性支持
- 在动物组件中实现正常和浅色精灵图像切换功能
- 重构桌面和移动版动物组件的揭示动画逻辑
- 移除冗余的运动偏好检测和布局效果钩子
- 调整揭示动画的时间参数和平滑度曲线
- 更新资源预加载配置以包含浅色动物图像
- 修改控制组件中的投注数量调整状态管理
- 优化脚本生成精灵图像的复用性
2026-06-11 15:50:22 +08:00

269 lines
7.6 KiB
Markdown
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.
# 结算过程金色旋转边框样式与动画
本文档保存当前 PC 端与移动端在开奖/结算过程里使用的金色边框、旋转描边和发光动画,便于后续下载、复用或对接设计标注。
## 源码位置
- PC 端挂载位置:`src/features/game/components/desktop/desktop-animal.tsx`
- 移动端挂载位置:`src/features/game/components/mobile/mobile-animal.tsx`
- 样式定义位置:`src/style/index.css`
PC 端在 `revealFrame` 存在时渲染:
```tsx
<div className="gold-reveal-glow rounded-[calc(var(--design-unit)*16)]" />
<div className="gold-reveal-static-border rounded-[calc(var(--design-unit)*16)]" />
<div className="gold-reveal-shell rounded-[calc(var(--design-unit)*16)]" />
```
移动端在 `revealFrame` 存在时渲染:
```tsx
<div className="mobile-gold-reveal-glow z-10 rounded-[calc(var(--design-unit)*7)]" />
<div className="mobile-gold-reveal-static-border z-20 rounded-[calc(var(--design-unit)*7)]" />
<div className="mobile-gold-reveal-shell z-20 rounded-[calc(var(--design-unit)*7)]" />
```
## 动画机制
- `--gold-angle`:注册为 CSS angle 自定义属性,用于驱动 `conic-gradient` 旋转。
- `rotating-gold-border`:把 `--gold-angle``0deg` 推到 `360deg`,形成边框旋转。
- `gold-border-pulse`:让外层金色光晕做轻微透明度和缩放呼吸。
- `::before`主金色旋转边框8 秒一圈。
- `::after`高光扫光边框2.1 秒一圈,并从反向角度偏移 `180deg` 开始。
- `static-border`:静态金色实体边框,保证边框厚度和底色稳定。
- `glow`:外部径向金色光晕,增强结算聚焦感。
## PC 端样式
```css
@property --gold-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@keyframes rotating-gold-border {
to {
--gold-angle: 360deg;
}
}
@keyframes gold-border-pulse {
0%,
100% {
opacity: 0.34;
transform: scale(0.992);
}
50% {
opacity: 0.54;
transform: scale(1.008);
}
}
.gold-reveal-shell {
--gold-angle: 0deg;
position: absolute;
inset: calc(var(--design-unit) * 2.6);
border-radius: calc(var(--design-unit) * 16);
overflow: hidden;
clip-path: inset(0 round calc(var(--design-unit) * 16));
pointer-events: none;
}
.gold-reveal-shell::before {
content: "";
position: absolute;
inset: 0;
border-radius: calc(var(--design-unit) * 16);
padding: calc(var(--design-unit) * 5.6);
background: conic-gradient(
from var(--gold-angle),
#534217 10%,
#534217 20%,
#ffe226 45%,
#534217 60%,
#534217 85%,
#ffe226 95%,
#534217 100%
);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: rotating-gold-border 8s linear infinite;
}
.gold-reveal-shell::after {
content: "";
position: absolute;
inset: calc(var(--design-unit) * 1);
border-radius: calc(var(--design-unit) * 15);
padding: calc(var(--design-unit) * 4);
background: conic-gradient(
from calc(var(--gold-angle) + 180deg),
rgba(255, 247, 210, 0) 0%,
rgba(255, 247, 210, 0) 66%,
rgba(255, 252, 232, 0.14) 71%,
rgba(255, 254, 244, 0.98) 75%,
rgba(255, 230, 130, 0.96) 79%,
rgba(255, 247, 210, 0.18) 84%,
rgba(255, 247, 210, 0) 90%,
rgba(255, 247, 210, 0) 100%
);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: rotating-gold-border 2.1s linear infinite;
}
.gold-reveal-static-border {
position: absolute;
inset: calc(var(--design-unit) * 2.8);
border-radius: calc(var(--design-unit) * 16);
border: calc(var(--design-unit) * 7.4) solid rgba(181, 138, 40, 0.98);
box-shadow:
inset 0 0 calc(var(--design-unit) * 14) rgba(255, 241, 181, 0.38),
0 0 calc(var(--design-unit) * 18) rgba(255, 210, 102, 0.32);
pointer-events: none;
}
.gold-reveal-glow {
position: absolute;
inset: calc(var(--design-unit) * 1.4);
border-radius: calc(var(--design-unit) * 18);
background: radial-gradient(
circle at center,
rgba(255, 226, 92, 0.18) 0%,
rgba(219, 161, 42, 0.14) 42%,
rgba(127, 86, 13, 0.08) 62%,
transparent 82%
);
filter: blur(calc(var(--design-unit) * 2.8));
opacity: 0.36;
pointer-events: none;
animation: gold-border-pulse 1.9s ease-in-out infinite;
}
```
## 移动端样式
```css
.mobile-gold-reveal-shell {
--gold-angle: 0deg;
position: absolute;
inset: calc(var(--design-unit) * 2.2);
border-radius: calc(var(--design-unit) * 7);
overflow: hidden;
clip-path: inset(0 round calc(var(--design-unit) * 7));
pointer-events: none;
}
.mobile-gold-reveal-shell::before {
content: "";
position: absolute;
inset: 0;
border-radius: calc(var(--design-unit) * 7);
padding: calc(var(--design-unit) * 2.5);
background: conic-gradient(
from var(--gold-angle),
#534217 10%,
#534217 20%,
#ffe226 45%,
#534217 60%,
#534217 85%,
#ffe226 95%,
#534217 100%
);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: rotating-gold-border 8s linear infinite;
}
.mobile-gold-reveal-shell::after {
content: "";
position: absolute;
inset: calc(var(--design-unit) * 0.5);
border-radius: calc(var(--design-unit) * 6.5);
padding: calc(var(--design-unit) * 1.7);
background: conic-gradient(
from calc(var(--gold-angle) + 180deg),
rgba(255, 247, 210, 0) 0%,
rgba(255, 247, 210, 0) 66%,
rgba(255, 247, 210, 0.14) 71%,
rgba(255, 254, 244, 0.98) 75%,
rgba(255, 230, 130, 0.96) 79%,
rgba(255, 247, 210, 0.18) 84%,
rgba(255, 247, 210, 0) 90%,
rgba(255, 247, 210, 0) 100%
);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: rotating-gold-border 2.1s linear infinite;
}
.mobile-gold-reveal-static-border {
position: absolute;
inset: calc(var(--design-unit) * 2.7);
border-radius: calc(var(--design-unit) * 7);
border: calc(var(--design-unit) * 2.8) solid rgba(181, 138, 40, 0.98);
box-shadow:
inset 0 0 calc(var(--design-unit) * 7) rgba(255, 241, 181, 0.38),
0 0 calc(var(--design-unit) * 9) rgba(255, 210, 102, 0.32);
pointer-events: none;
}
.mobile-gold-reveal-glow {
position: absolute;
inset: calc(var(--design-unit) * 1.4);
border-radius: calc(var(--design-unit) * 8);
background: radial-gradient(
circle at center,
rgba(255, 226, 92, 0.2) 0%,
rgba(219, 161, 42, 0.16) 42%,
rgba(127, 86, 13, 0.08) 62%,
transparent 82%
);
filter: blur(calc(var(--design-unit) * 1.4));
opacity: 0.42;
pointer-events: none;
animation: gold-border-pulse 1.9s ease-in-out infinite;
}
```
## 减少动画模式
组件中已经接入 `useReducedMotion()`。当用户系统设置减少动态效果时PC 与移动端都会把旋转和呼吸动画关闭:
```tsx
style={prefersReducedMotion ? { animation: 'none' } : undefined}
```
光晕层在减少动画模式下固定为:
```tsx
style={{
animation: 'none',
opacity: 0.36,
transform: 'scale(1)',
}}
```
## 复用注意事项
- 父容器必须是 `position: relative`,三层边框节点必须是绝对定位。
- 需要提供 `--design-unit`,当前项目用它控制 PC 与移动端等比缩放。
- `@property --gold-angle` 是旋转效果的关键;如果目标浏览器不支持 `@property`,可改用 `transform: rotate()` 方案,但需要额外包一层元素。
- 移动端额外叠加了 `animalBorderImage` 图片边框CSS 金色旋转边框位于图片边框下方,增强结算选中效果。