mirror of
https://github.com/wahyd4/links.git
synced 2026-08-08 21:04:53 +10:00
fix(invest): mobile chart — fixed height, sane scales, horizontal x labels, compact legend/points, Chinese help
Root cause of the squashed chart: canvas had a fixed height=90 attr and no container, so on narrow viewports Chart.js compressed everything — legend overlapped the plot, x labels tilted 45deg, y ticks degenerated (-1000% scale). Fix: relative h-72/h-80 container + maintainAspectRatio:false, grace 5%, maxTicksLimit, maxRotation:0, smaller points (r2/1.5), compact legend/tooltip, Chinese help text.
This commit is contained in:
+2
-2
@@ -746,8 +746,8 @@ def _line_dataset(label: str, data: list, color: str, dashed: bool = False, widt
|
||||
'borderColor': color,
|
||||
'backgroundColor': color,
|
||||
'borderWidth': width,
|
||||
'pointRadius': 4 if not dashed else 3,
|
||||
'pointHoverRadius': 7 if not dashed else 5,
|
||||
'pointRadius': 2 if not dashed else 1.5,
|
||||
'pointHoverRadius': 4 if not dashed else 3,
|
||||
'tension': 0.3,
|
||||
'borderDash': [5, 5] if dashed else [],
|
||||
'fill': False,
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
<div class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between mb-4">
|
||||
<div>
|
||||
<p class="text-xs font-semibold tracking-widest text-stone-500 uppercase">{{ fy_label }} Performance vs Benchmarks</p>
|
||||
<p id="performanceChartHelp" class="text-xs text-stone-400 mt-1">Toggle between percentage return and dollar-value growth from the baseline date.</p>
|
||||
<p id="performanceChartHelp" class="text-xs text-stone-400 mt-1">切换涨跌幅百分比与金额两种视图。</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<div class="inline-flex rounded-lg border border-stone-200 bg-stone-50 p-1 text-xs font-semibold" role="group" aria-label="Chart period">
|
||||
@@ -142,7 +142,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<canvas id="performanceChart" height="90"></canvas>
|
||||
<div class="relative h-72 md:h-80">
|
||||
<canvas id="performanceChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -363,14 +365,32 @@
|
||||
const unit = currentData().unit;
|
||||
return {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { mode: 'index', intersect: false },
|
||||
plugins: {
|
||||
legend: { position: 'top', align: 'start', labels: { usePointStyle: true, pointStyle: 'rect', pointStyleWidth: 14, padding: 20, font: { size: 12, weight: '600' } } },
|
||||
tooltip: { callbacks: { label: function (ctx) { const v = ctx.parsed.y; if (v === null || v === undefined) return ctx.dataset.label + ': —'; return ctx.dataset.label + ': ' + (unit === 'currency' ? formatCurrency(v) : formatPercent(v)); } } },
|
||||
legend: {
|
||||
position: 'top',
|
||||
align: 'start',
|
||||
labels: { usePointStyle: true, pointStyle: 'rect', pointStyleWidth: 10, padding: 10, boxWidth: 10, font: { size: 11, weight: '600' } },
|
||||
},
|
||||
tooltip: {
|
||||
position: 'nearest',
|
||||
padding: 8,
|
||||
titleFont: { size: 11 },
|
||||
bodyFont: { size: 10 },
|
||||
callbacks: { label: function (ctx) { const v = ctx.parsed.y; if (v === null || v === undefined) return ctx.dataset.label + ': —'; return ctx.dataset.label + ': ' + (unit === 'currency' ? formatCurrency(v) : formatPercent(v)); } },
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
y: { ticks: { callback: function (v) { return unit === 'currency' ? formatCurrency(Number(v)) : formatPercent(Number(v)); }, font: { size: 11 } }, grid: { color: '#f5f5f4' } },
|
||||
x: { grid: { display: false }, ticks: { font: { size: 11 } } },
|
||||
y: {
|
||||
grace: '5%',
|
||||
ticks: { maxTicksLimit: 6, callback: function (v) { return unit === 'currency' ? formatCurrency(Number(v)) : formatPercent(Number(v)); }, font: { size: 10 } },
|
||||
grid: { color: '#f5f5f4' },
|
||||
},
|
||||
x: {
|
||||
grid: { display: false },
|
||||
ticks: { autoSkip: true, maxRotation: 0, maxTicksLimit: 8, font: { size: 10 } },
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -386,10 +406,10 @@
|
||||
chart.options = chartOptions();
|
||||
chart.update();
|
||||
if (help) {
|
||||
const baseline = currentData().baseline || 'the baseline date';
|
||||
const baseline = currentData().baseline || '基准日';
|
||||
help.textContent = currentMode === 'value'
|
||||
? `Dollar mode: actual total portfolio value vs SPY/QQQ benchmark value from ${baseline}.`
|
||||
: `Percentage mode: growth/decline since ${baseline}; cash-flow-adjusted metrics are shown in the cards above.`;
|
||||
? `金额视图:组合总市值 vs SPY/QQQ 基准(自 ${baseline})`
|
||||
: `涨跌幅视图:自 ${baseline} 以来的涨跌幅;卡片上方为现金流调整指标`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user