@@ -0,0 +1,260 @@
/* perf-progress-bar 组件样式
* 所有 class 以 ppb- 为前缀,避免与页面样式冲突
*/
/* ── 外层容器:为刻度留出底部空间 ── */
.ppb-wrap {
position: relative;
padding-bottom: 10rpx; /* 为刻度行留空间 */
}
/* ── 进度条轨道 ── */
.ppb-track {
position: relative;
width: 100%;
height: 14rpx;
border-radius: 9rpx;
overflow: visible;
}
/* 底轨背景 */
.ppb-track-bg {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
border-radius: 9rpx;
background: var(--ppb-track-bg-color, rgba(255, 255, 255, 0.15));
}
/* 填充条:控制裁剪宽度 */
.ppb-fill {
position: absolute;
top: 0; left: 0; bottom: 0;
border-radius: 9rpx;
overflow: hidden;
transition: width 0.4s cubic-bezier(0.34, 1.2, 0.64, 1);
box-shadow: 0 0 14rpx rgba(239, 68, 68, 0.45);
}
/* 全宽渐变层 */
.ppb-gradient-bar {
position: absolute;
top: 0; left: 0; bottom: 0;
width: 100vw;
background: linear-gradient(
90deg,
#fde68a 0%,
#fbbf24 20%,
#f97316 45%,
#ef4444 70%,
#910a0a 100%
);
}
/* 分隔竖线 */
.ppb-divider {
position: absolute;
top: 0;
width: 8rpx;
height: 100%;
background: var(--ppb-divider-color, #5381D9);
transform: translateX(-50%);
pointer-events: none;
z-index: 2;
}
/* ══════════════════════════════════════════════════════
* 高光动画
* ★ 外观旋钮:
* --ppb-shine-width : 光束宽度(固定 rpx, 不随进度变化)
* --ppb-shine-opacity: 峰值亮度 0~1
* --ppb-shine-color : RGB颜色, 如 255,220,100=暖黄
* ══════════════════════════════════════════════════════ */
.ppb-shine {
--ppb-shine-width: 120rpx;
--ppb-shine-opacity: 1.0;
--ppb-shine-color: 255, 255, 255;
position: absolute;
top: 0;
left: -130rpx;
width: var(--ppb-shine-width);
height: 100%;
background: linear-gradient(
90deg,
transparent 0%,
rgba(var(--ppb-shine-color), 0.08) 20%,
rgba(var(--ppb-shine-color), var(--ppb-shine-opacity)) 50%,
rgba(var(--ppb-shine-color), 0.08) 80%,
transparent 100%
);
animation: none;
pointer-events: none;
}
.ppb-shine--active {
animation: ppbShine 1s linear 1 forwards;
}
@keyframes ppbShine {
0% { left: -130rpx; opacity: 0; }
5% { opacity: 1; }
95% { opacity: 1; }
100% { left: calc(100% + 10rpx); opacity: 0; }
}
/* ══════════════════════════════════════════════════════
* 导火索效果
* ★ 外观旋钮:
* --ppb-spark-scale : 整体缩放
* --ppb-spark-pole-h: 光柱高度
* ══════════════════════════════════════════════════════ */
.ppb-edge-glow {
--ppb-spark-scale: 0.7;
--ppb-spark-pole-h: 30rpx;
position: absolute;
top: 50%;
transform: translate(-50%, -50%) scale(var(--ppb-spark-scale));
transform-origin: center center;
width: calc(var(--ppb-spark-pole-h) / 2);
height: var(--ppb-spark-pole-h);
border-radius: 999rpx;
background: rgba(255, 255, 255, 1);
opacity: 0.25;
box-shadow: 0 0 4rpx 2rpx rgba(255, 200, 80, 0.35);
animation: none;
pointer-events: none;
overflow: visible;
z-index: 10;
transition: opacity 0.1s, box-shadow 0.1s;
}
.ppb-edge-glow--active {
animation: ppbEdgePulse 1s ease-out 1 forwards;
}
@keyframes ppbEdgePulse {
0% { opacity: 1; box-shadow: 0 0 22rpx 12rpx rgba(255, 255, 255, 0.95); }
15% { opacity: 1; box-shadow: 0 0 26rpx 14rpx rgba(255, 220, 80, 0.90); }
55% { opacity: 0.6; box-shadow: 0 0 12rpx 6rpx rgba(255, 160, 40, 0.60); }
85% { opacity: 0.25; box-shadow: 0 0 4rpx 2rpx rgba(255, 200, 80, 0.35); }
100% { opacity: 0.25; box-shadow: 0 0 4rpx 2rpx rgba(255, 200, 80, 0.35); }
}
/* 火星粒子基础 */
.ppb-spark {
position: absolute;
border-radius: 999rpx;
pointer-events: none;
opacity: 0;
top: 50%;
left: 50%;
animation: none;
}
.ppb-spark--active {
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
/* 粒子1: 右上, 亮白 */
.ppb-spark-1 { width: 10rpx; height: 10rpx; background: #ffffff; }
.ppb-spark-1.ppb-spark--active { animation-name: ppbSpark1; animation-timing-function: linear; }
@keyframes ppbSpark1 {
0% { opacity: 0; transform: translate( 0rpx, 0rpx) scale(0.0); }
8% { opacity: 1; transform: translate( 8rpx, -16rpx) scale(1.6); }
25% { opacity: 0.9; transform: translate( 16rpx, -30rpx) scale(1.2); }
45% { opacity: 0.7; transform: translate( 22rpx, -40rpx) scale(0.9); }
62% { opacity: 0.5; transform: translate( 27rpx, -48rpx) scale(0.7); }
76% { opacity: 0.3; transform: translate( 31rpx, -53rpx) scale(0.5); }
87% { opacity: 0.15; transform: translate( 34rpx, -57rpx) scale(0.3); }
100% { opacity: 0; transform: translate( 36rpx, -60rpx) scale(0.1); }
}
/* 粒子2: 右下, 橙色 */
.ppb-spark-2 { width: 12rpx; height: 12rpx; background: #fb923c; }
.ppb-spark-2.ppb-spark--active { animation-name: ppbSpark2; animation-timing-function: linear; }
@keyframes ppbSpark2 {
0% { opacity: 0; transform: translate( 0rpx, 0rpx) scale(0.0); }
12% { opacity: 1; transform: translate( 10rpx, 14rpx) scale(1.5); }
28% { opacity: 0.8; transform: translate( 19rpx, 24rpx) scale(1.1); }
46% { opacity: 0.6; transform: translate( 26rpx, 32rpx) scale(0.8); }
62% { opacity: 0.4; transform: translate( 31rpx, 38rpx) scale(0.6); }
76% { opacity: 0.25; transform: translate( 35rpx, 43rpx) scale(0.4); }
88% { opacity: 0.1; transform: translate( 38rpx, 47rpx) scale(0.25); }
100% { opacity: 0; transform: translate( 42rpx, 56rpx) scale(0.1); }
}
/* 粒子3: 正上, 黄色 */
.ppb-spark-3 { width: 8rpx; height: 8rpx; background: #fde68a; }
.ppb-spark-3.ppb-spark--active { animation-name: ppbSpark3; animation-timing-function: linear; }
@keyframes ppbSpark3 {
0% { opacity: 0; transform: translate( 0rpx, 0rpx) scale(0.0); }
6% { opacity: 1; transform: translate( 4rpx, -22rpx) scale(1.8); }
20% { opacity: 0.9; transform: translate( 7rpx, -36rpx) scale(1.3); }
38% { opacity: 0.7; transform: translate( 9rpx, -48rpx) scale(1.0); }
55% { opacity: 0.5; transform: translate( 10rpx, -57rpx) scale(0.7); }
70% { opacity: 0.3; transform: translate( 11rpx, -63rpx) scale(0.5); }
84% { opacity: 0.15; transform: translate( 11rpx, -68rpx) scale(0.3); }
100% { opacity: 0; transform: translate( 12rpx, -74rpx) scale(0.1); }
}
/* 粒子4: 右斜上, 红橙, 拖尾 */
.ppb-spark-4 { width: 16rpx; height: 6rpx; background: #ef4444; }
.ppb-spark-4.ppb-spark--active { animation-name: ppbSpark4; animation-timing-function: linear; }
@keyframes ppbSpark4 {
0% { opacity: 0; transform: translate( 0rpx, 0rpx) rotate( 0deg) scale(0.0); }
10% { opacity: 1; transform: translate( 14rpx, -10rpx) rotate(-20deg) scale(1.4); }
26% { opacity: 0.8; transform: translate( 24rpx, -16rpx) rotate(-30deg) scale(1.0); }
44% { opacity: 0.6; transform: translate( 32rpx, -21rpx) rotate(-38deg) scale(0.75); }
60% { opacity: 0.4; transform: translate( 39rpx, -26rpx) rotate(-45deg) scale(0.55); }
74% { opacity: 0.25; transform: translate( 44rpx, -30rpx) rotate(-50deg) scale(0.4); }
87% { opacity: 0.1; transform: translate( 48rpx, -33rpx) rotate(-53deg) scale(0.25); }
100% { opacity: 0; transform: translate( 58rpx, -40rpx) rotate(-55deg) scale(0.1); }
}
/* 粒子5: 正右, 黄白 */
.ppb-spark-5 { width: 10rpx; height: 10rpx; background: #fbbf24; }
.ppb-spark-5.ppb-spark--active { animation-name: ppbSpark5; animation-timing-function: linear; }
@keyframes ppbSpark5 {
0% { opacity: 0; transform: translate( 0rpx, 0rpx) scale(0.0); }
5% { opacity: 1; transform: translate( 18rpx, 2rpx) scale(1.7); }
20% { opacity: 0.85; transform: translate( 30rpx, 3rpx) scale(1.2); }
38% { opacity: 0.65; transform: translate( 40rpx, 4rpx) scale(0.9); }
55% { opacity: 0.45; transform: translate( 47rpx, 5rpx) scale(0.7); }
70% { opacity: 0.3; transform: translate( 52rpx, 6rpx) scale(0.5); }
84% { opacity: 0.15; transform: translate( 56rpx, 7rpx) scale(0.3); }
100% { opacity: 0; transform: translate( 60rpx, 8rpx) scale(0.1); }
}
/* 粒子6: 右下斜, 淡橙 */
.ppb-spark-6 { width: 14rpx; height: 14rpx; background: #fed7aa; }
.ppb-spark-6.ppb-spark--active { animation-name: ppbSpark6; animation-timing-function: linear; }
@keyframes ppbSpark6 {
0% { opacity: 0; transform: translate( 0rpx, 0rpx) scale(0.0); }
15% { opacity: 0.9; transform: translate( 6rpx, 18rpx) scale(1.5); }
30% { opacity: 0.75; transform: translate( 10rpx, 28rpx) scale(1.1); }
47% { opacity: 0.55; transform: translate( 14rpx, 36rpx) scale(0.85); }
62% { opacity: 0.4; transform: translate( 17rpx, 43rpx) scale(0.65); }
75% { opacity: 0.25; transform: translate( 19rpx, 48rpx) scale(0.5); }
87% { opacity: 0.1; transform: translate( 21rpx, 53rpx) scale(0.35); }
100% { opacity: 0; transform: translate( 24rpx, 64rpx) scale(0.1); }
}
/* ── 刻度 ── */
.ppb-ticks {
position: absolute;
width: 100%;
top: 100%;
margin-top: 6rpx;
height: 24rpx;
}
.ppb-tick {
position: absolute;
font-size: 16rpx;
color: var(--ppb-tick-color, rgba(255, 255, 255, 0.55));
transition: color 0.3s ease, font-weight 0.3s ease;
}
.ppb-tick--done {
color: var(--ppb-tick-done-color, rgba(255, 255, 255, 0.95));
font-weight: 600;
}
.ppb-tick--highlight {
color: rgba(255, 255, 255, 0.85);
font-weight: 500;
}