feat(stats): 近 30 天折线补纵轴刻度
原来这条折线只有横轴日期,纵轴没有任何参照:读者看到峰谷不知道自己 在看 3 次还是 300 次的起伏。现在补上三条刻度(上限 / 一半 / 0)加对应 的横向虚线。 纵轴上限取 niceMax(峰值),不是峰值本身。峰值正好压在顶格里时,读者 分不清那到底是确切的数还是被裁掉的数;向上取整到 1/2/1.5/3/4/6/8×10^n 之后顶部留白固定,三条刻度又都是整数和好读的数(1.5 倍只在量级≥100 时参与,否则算出来是 7.5 这种半格)。上限恒为偶数,中间刻度必然是整数。 刻度文字不放进 SVG:viewBox 用 preserveAspectRatio="none" 横向拉伸填满 卡片,里面的文字会跟着被拉扁,窄屏尤其明显。改成左边一列 HTML 标签 + 横向虚线仍在 SVG 里(描边锁 non-scaling-stroke)。列宽靠一份看不见的 「最宽刻度」占位撑开,不写死 em。 同时把 Polyline/AreaPath 收敛成单个 NewLineChart:坐标、面积、刻度必须 共用同一个上限,分两次算就会各按自己看到的峰值归一化,出现刻度和线错开 的图。面积路径改为沿基线闭合,不再漏进轴标签的留白区。 新增 chart_test.go 锁住三条不变式:中间刻度必为整数、上限不离开峰值一倍、 刻度/折线/面积共用上限;另有 0..2000 的穷举检查。
This commit is contained in:
+65
-12
@@ -126,11 +126,51 @@
|
||||
}
|
||||
|
||||
/* 折线图 */
|
||||
.tb-line-wrap { margin-top: 4px; }
|
||||
/* 左边一列纵轴刻度 + 右边画布:刻度文字不能放进 SVG ——
|
||||
viewBox 用了 preserveAspectRatio="none" 横向拉伸填满卡片,
|
||||
放在里面的文字会跟着被拉扁(窄屏上尤其明显)。 */
|
||||
.tb-line-wrap {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
column-gap: 6px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.tb-line-y {
|
||||
position: relative;
|
||||
height: 148px;
|
||||
font-size: var(--tb-fs-xs);
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
/* 刻度全是绝对定位的,撑不开这一列;用一份看不见的「最宽刻度」占位,
|
||||
让列宽自己贴合数字长度(上限那个数位数最多),不用写死 em。 */
|
||||
.tb-line-ruler {
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
}
|
||||
.tb-line-tick {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
white-space: nowrap;
|
||||
/* 刻度值以刻度线为中心对齐,而不是以格子顶部对齐 */
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.tb-line {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 148px;
|
||||
/* 折线只占上边 148px,刻度标签可能略高于画布,别被裁掉 */
|
||||
overflow: visible;
|
||||
}
|
||||
.tb-line .tb-grid {
|
||||
stroke: var(--tb-border);
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: 3 5;
|
||||
/* 同折线:viewBox 被拉伸,描边宽度必须锁像素,否则横向会被算成几倍粗 */
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
.tb-line .tb-grid.is-base {
|
||||
stroke-dasharray: none;
|
||||
}
|
||||
.tb-line .tb-line-area {
|
||||
/* 比 --tb-primary-weak(0.10)略深一档:折线下方的面积要能看出「有」,但不能抢走线条本身 */
|
||||
@@ -429,19 +469,32 @@
|
||||
<div class="tb-card">
|
||||
<h3 class="tb-card-title">{{t $.LangCode "stats.trend.dailyTitle"}}</h3>
|
||||
<p class="tb-card-note">{{t $.LangCode "stats.trend.dailyNote"}}</p>
|
||||
{{ $line := LineChart .DailyValues 640 148 12 10 }}
|
||||
<div class="tb-line-wrap">
|
||||
<svg class="tb-line" viewBox="0 0 640 148" preserveAspectRatio="none" role="img"
|
||||
aria-label="{{t $.LangCode "stats.trend.dailyTitle"}}">
|
||||
<path class="tb-line-area" d="{{ AreaPath .DailyValues 640 148 12 10 }}"></path>
|
||||
<polyline class="tb-line-path" points="{{ Polyline .DailyValues 640 148 12 10 }}"></polyline>
|
||||
</svg>
|
||||
{{ if eq (len .Daily) 30 }}
|
||||
<div class="tb-axis">
|
||||
<span>{{ (index .Daily 0).Label }}</span>
|
||||
<span>{{ (index .Daily 15).Label }}</span>
|
||||
<span>{{ (index .Daily 29).Label }}</span>
|
||||
<!-- 纵轴刻度:SVG 横向被拉伸,文字只能留在外面用 HTML 定位 -->
|
||||
<div class="tb-line-y" aria-hidden="true">
|
||||
<span class="tb-line-ruler">{{ (index $line.Ticks 0).Label }}</span>
|
||||
{{ range $line.Ticks }}<span class="tb-line-tick" style="top:{{ .TopPct }}%">{{ .Label }}</span>{{ end }}
|
||||
</div>
|
||||
<div class="tb-line-plot">
|
||||
<svg class="tb-line" viewBox="0 0 640 148" preserveAspectRatio="none" role="img"
|
||||
aria-label="{{t $.LangCode "stats.trend.dailyTitle"}}">
|
||||
{{ range $line.Ticks }}
|
||||
<line class="tb-grid{{ if .Base }} is-base{{ end }}" x1="0" x2="640" y1="{{ .Y }}" y2="{{ .Y }}"></line>
|
||||
{{ end }}
|
||||
{{ if $line.HasData }}
|
||||
<path class="tb-line-area" d="{{ $line.Area }}"></path>
|
||||
<polyline class="tb-line-path" points="{{ $line.Points }}"></polyline>
|
||||
{{ end }}
|
||||
</svg>
|
||||
{{ if eq (len .Daily) 30 }}
|
||||
<div class="tb-axis">
|
||||
<span>{{ (index .Daily 0).Label }}</span>
|
||||
<span>{{ (index .Daily 15).Label }}</span>
|
||||
<span>{{ (index .Daily 29).Label }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user