ShineBridge v1.9.1 — Fix: Finanzen-Chart bei langen Abrechnungsjahren unlesbar
'Kosten je Tag' quetschte alle Tage in eine feste Breite von 600px — bei 112 Tagen wurden die Balken zu ~1px-Haarlinien. Breite skaliert jetzt mit der Tagesanzahl (min. 10px Slot/Tag), Chart scrollt bei vielen Tagen horizontal statt gestaucht zu werden. X-Achsen-Labels richten sich an der tatsächlichen Balkenbreite aus statt an einer festen Label-Anzahl. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
name: ShineBridge
|
||||
version: "1.9.0"
|
||||
version: "1.9.1"
|
||||
slug: shinebridge
|
||||
description: Energiemanagement für Growatt/Goodwe-Wechselrichter — PV-Überschussladen, Wallbox-EMS, Tarifvergleich, Zigbee2MQTT-Überschussgeräte
|
||||
url: https://gitea.bitfire.work/retr0/shinebridge
|
||||
|
||||
@@ -797,11 +797,16 @@ async function loadFinance() {
|
||||
</div>`;
|
||||
|
||||
// ── SVG-Balkendiagramm ────────────────────────────────────────
|
||||
const W = 600, H = 180, PL = 44, PR = 12, PT = 10, PB = 28;
|
||||
// Breite skaliert mit der Anzahl Tage (Mindestplatz pro Tag), statt bei vielen
|
||||
// Tagen alles in eine feste Breite zu quetschen — sonst werden Balken bei
|
||||
// langen Abrechnungsjahren (>60 Tage) zu Haarlinien und unlesbar.
|
||||
const H = 180, PL = 44, PR = 12, PT = 10, PB = 28;
|
||||
const n = days.length;
|
||||
const MIN_SLOT = 10; // px pro Tag (Balkenpaar + Abstand), unterhalb dessen nichts mehr lesbar ist
|
||||
const W = Math.max(600, PL + PR + n * MIN_SLOT);
|
||||
const cW = W - PL - PR;
|
||||
const cH = H - PT - PB;
|
||||
const n = days.length;
|
||||
const barW = Math.max(2, Math.floor(cW / n) - 2);
|
||||
const barW = Math.max(3, Math.floor(cW / n) - 2);
|
||||
const gap = Math.max(1, Math.floor(cW / n) - barW);
|
||||
|
||||
const allVals = days.flatMap(d => [d.fixed_eur, d.spot_eur].filter(v => v != null));
|
||||
@@ -816,6 +821,9 @@ async function loadFinance() {
|
||||
yLabels += `<text x="${PL-4}" y="${(y+4).toFixed(1)}" text-anchor="end" font-size="9" fill="#8b949e">${fEur(v)}</text>`;
|
||||
}
|
||||
|
||||
// Label-Abstand an der tatsächlichen Balkenbreite ausrichten (~60px pro Label),
|
||||
// statt pauschal 8 Labels über die ganze — jetzt variable — Breite zu verteilen.
|
||||
const labelStep = Math.max(1, Math.round(60 / (barW + gap)));
|
||||
let bars = '', xLabels = '';
|
||||
days.forEach((d, i) => {
|
||||
const x0 = PL + i * (barW + gap);
|
||||
@@ -825,7 +833,7 @@ async function loadFinance() {
|
||||
const hSpot = cH * d.spot_eur / maxVal;
|
||||
bars += `<rect x="${x0 + barW/2}" y="${(PT + cH - hSpot).toFixed(1)}" width="${barW/2}" height="${hSpot.toFixed(1)}" fill="${C.spot}" opacity="0.85"/>`;
|
||||
}
|
||||
if (i % Math.max(1, Math.floor(n / 8)) === 0) {
|
||||
if (i % labelStep === 0) {
|
||||
const label = d.date.slice(5);
|
||||
xLabels += `<text x="${(x0 + barW/2).toFixed(1)}" y="${H - 4}" text-anchor="middle" font-size="9" fill="#8b949e">${label}</text>`;
|
||||
}
|
||||
@@ -838,10 +846,11 @@ async function loadFinance() {
|
||||
<div style="border-top:1px solid var(--border);padding-top:24px;margin-top:4px">
|
||||
<div style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin-bottom:14px">Kosten je Tag</div>
|
||||
<div style="overflow-x:auto">
|
||||
<svg viewBox="0 0 ${W} ${H+24}" style="width:100%;max-width:${W}px;display:block">
|
||||
<svg viewBox="0 0 ${W} ${H+24}" width="${W}" height="${H+24}" style="width:${W}px;max-width:none;display:block">
|
||||
${gridLines}${yLabels}${bars}${xLabels}${legend}
|
||||
</svg>
|
||||
</div>
|
||||
${n > 60 ? `<div style="font-size:11px;color:var(--text-dim);margin-top:6px">← Horizontal scrollbar, ${n} Tage</div>` : ''}
|
||||
</div>`;
|
||||
|
||||
el.innerHTML = `<div style="padding:4px 0">${empfehlung}${cards}${chartSection}</div>`;
|
||||
|
||||
Reference in New Issue
Block a user