feat(timer): 训练页改版 hero 风格 + 进度环刻度 + 醒目姿态提示气泡
- progress-ring: canvas 新增秒刻度层(四分位加粗), 环内加 subText, 移除组件内 statusText - timer.wxml: 环下方状态词 + 目标信息卡(今日目标·第N天›静态箭头) + 运行提示; 进度环传 ticks/subText - timer.js: 派生 ringTicks/ringSubText/statusText/goalLine/runningTip/tipType/tipIcon, 各生命周期计算下发 - timer.wxss: 按钮贴底(flex-start+margin-top:auto), 新增 .timer-status/.goal-card/.timer-tip 气泡卡片(主色左边框+小三角+tipPulse 呼吸), 文字放大加粗 - 姿态提示分语义: posture/phase(主色) / done(成功色), 图标用 peopleFill/successFill - 状态机/计时/循环FSM/呼吸环/彩带/弹窗/语音震动常亮全部保留 - 另含 index 进度地图右上角奖杯图标删除(quest-trophy 样式清理)
This commit is contained in:
@@ -14,26 +14,28 @@ Component({
|
||||
trackColor: { type: String, value: '#EEEEEE' },
|
||||
// Total elapsed seconds (since start). Shown in the ring center once the
|
||||
// countdown hits 0 (overtime mode) - replaces the old +Xs badge.
|
||||
elapsed: { type: Number, value: 0 }
|
||||
elapsed: { type: Number, value: 0 },
|
||||
// Tick count. Caller passes the duration (one tick per second, capped at
|
||||
// 60 to avoid clutter). 0 = no ticks drawn. Quarter ticks are emphasized.
|
||||
ticks: { type: Number, value: 0 },
|
||||
// Small secondary label under the big time (e.g. "目标 30 秒"). Empty = hidden.
|
||||
subText: { type: String, value: '' }
|
||||
},
|
||||
|
||||
data: {
|
||||
displayTime: '00:00',
|
||||
statusText: '准备开始'
|
||||
displayTime: '00:00'
|
||||
},
|
||||
|
||||
observers: {
|
||||
'remaining, status, duration, elapsed'() {
|
||||
const texts = { idle: '准备开始', running: '坚持住', paused: '已暂停', completed: '完成!' }
|
||||
// 倒计时阶段显示剩余;达标后 remaining 归零,改显总训练时长(overtime 模式)
|
||||
const shown = this.data.remaining > 0 ? this.data.remaining : (this.data.elapsed || 0)
|
||||
this.setData({
|
||||
displayTime: util.formatTime(shown),
|
||||
statusText: texts[this.data.status] || ''
|
||||
displayTime: util.formatTime(shown)
|
||||
})
|
||||
},
|
||||
|
||||
'remaining, duration, size, ringWidth, primaryColor, primaryLightColor, trackColor'() {
|
||||
'remaining, duration, size, ringWidth, primaryColor, primaryLightColor, trackColor, ticks'() {
|
||||
this._draw()
|
||||
}
|
||||
},
|
||||
@@ -70,7 +72,7 @@ Component({
|
||||
const ctx = this._ctx
|
||||
if (!ctx) return
|
||||
|
||||
const { size, ringWidth, duration, remaining, primaryColor, primaryLightColor, trackColor } = this.data
|
||||
const { size, ringWidth, duration, remaining, primaryColor, primaryLightColor, trackColor, ticks } = this.data
|
||||
const dpr = this._dpr
|
||||
|
||||
const w = size * dpr
|
||||
@@ -92,6 +94,28 @@ Component({
|
||||
ctx.lineCap = 'round'
|
||||
ctx.stroke()
|
||||
|
||||
// ---- tick marks (inside the band) ----
|
||||
if (ticks > 0) {
|
||||
const innerR = radius - lw / 2 - (4 * dpr) // just inside the band
|
||||
const q = Math.max(1, Math.round(ticks / 4)) // quarter emphasis step
|
||||
const shortLen = 6 * dpr
|
||||
const longLen = 12 * dpr
|
||||
for (let i = 0; i < ticks; i++) {
|
||||
const ang = -Math.PI / 2 + (i / ticks) * Math.PI * 2
|
||||
const isLong = (i % q === 0)
|
||||
const len = isLong ? longLen : shortLen
|
||||
const cos = Math.cos(ang)
|
||||
const sin = Math.sin(ang)
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(cx + innerR * cos, cy + innerR * sin)
|
||||
ctx.lineTo(cx + (innerR - len) * cos, cy + (innerR - len) * sin)
|
||||
ctx.lineWidth = (isLong ? 3 : 1.5) * dpr
|
||||
ctx.lineCap = 'round'
|
||||
ctx.strokeStyle = isLong ? 'rgba(0,0,0,0.28)' : 'rgba(0,0,0,0.12)'
|
||||
ctx.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
// progress arc (clockwise from 12 o'clock)
|
||||
const ratio = duration > 0 ? Math.max(0, Math.min(1, remaining / duration)) : 0
|
||||
if (ratio > 0.001) {
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<canvas type="2d" id="ringCanvas" class="ring-canvas" style="width: {{size}}rpx; height: {{size}}rpx;"></canvas>
|
||||
<view class="ring-center">
|
||||
<text class="time-text">{{displayTime}}</text>
|
||||
<text class="status-text">{{statusText}}</text>
|
||||
<text class="sub-text" wx:if="{{subText}}">{{subText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
|
||||
.time-text {
|
||||
font-size: 88rpx;
|
||||
font-size: 96rpx;
|
||||
font-weight: 800;
|
||||
color: var(--text);
|
||||
font-variant-numeric: tabular-nums;
|
||||
@@ -29,9 +29,9 @@
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 28rpx;
|
||||
.sub-text {
|
||||
font-size: 26rpx;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 10rpx;
|
||||
margin-top: 14rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user