Files
Blizzard 15ff59e6db feat(fe): 新增 seg-tabs 与 stat-ring 组件
seg-tabs 合并三套长得像但尺寸各不同的横向切换:plan 的 .inline-tabs
(灰槽白块)、community 的 .feed-tab(白药丸+阴影)、record 的 .rf-chip
(白药丸无阴影,高度还差 10rpx)。variant="solid|pill" 二选一,items
同时支持字符串数组和 {key,label} 数组。

stat-ring 是首页门面用的完成度环。用 SVG data-uri 画,和 record 页的
体重折线图同一套路——canvas 在 scroll-view 里的层级、滚动跟随和截图
行为全是坑。中心内容走 slot。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:36:35 +08:00

42 lines
1.6 KiB
JavaScript

// 完成度环。用 SVG data-uri 画(和 record 页的体重折线图同一套路),不用 canvas:
// canvas 在 scroll-view 里的层级、滚动跟随和截图行为全是坑。
const TAU = 2 * Math.PI;
const R = 42; // viewBox 100 下的半径,留出描边宽度
function ringSvg(percent, stroke, track, fill) {
const c = TAU * R;
const p = Math.max(0, Math.min(100, Number(percent) || 0));
const off = c * (1 - p / 100);
const circle = (color, dash) =>
'<circle cx="50" cy="50" r="' + R + '" fill="none" stroke="' + color +
'" stroke-width="' + stroke + '" stroke-linecap="round"' + dash + '/>';
return (
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">' +
circle(track, '') +
'<g transform="rotate(-90 50 50)">' +
circle(fill, ' stroke-dasharray="' + c.toFixed(1) + '" stroke-dashoffset="' + off.toFixed(1) + '"') +
'</g></svg>'
);
}
Component({
options: { addGlobalClass: true },
properties: {
percent: { type: Number, value: 0 },
size: { type: Number, value: 180 }, // rpx
stroke: { type: Number, value: 8 }, // viewBox 单位,即直径的百分比
track: { type: String, value: '#FFE6BA' },
fill: { type: String, value: '#F5A947' },
},
data: { src: '', boxStyle: '' },
observers: {
'percent,size,stroke,track,fill': function (percent, size, stroke, track, fill) {
const svg = ringSvg(percent, stroke, track, fill);
this.setData({
src: 'data:image/svg+xml,' + encodeURIComponent(svg),
boxStyle: 'width:' + size + 'rpx;height:' + size + 'rpx',
});
},
},
});