Handy-Darstellung: Diagramme, Meteogramm und Abstaende
Auf dem Handy war die Seite bisher nur mit der Desktopversion des Browsers brauchbar. Drei Ursachen, alle nachgemessen bei 375 px: Die Diagramme standen im Hochformat, 301 x 400 px - die Zeitachse lag auf der kurzen Seite. Die Hoehe kam nicht aus dem Container: .chart-container hatte inline height:100% in einem Elternelement ohne Hoehe, und die Canvas trugen height="400px;", was kein gueltiger Zahlenwert ist. Die Hoehe steht jetzt im Stylesheet, 400 px am Rechner und 250 px unter 768 px Breite, die Beschriftung dort 8 statt 10 px. Das Meteogramm hat sich nicht angepasst, sondern gequetscht. meteoblue legt sein Bild einmal beim Laden fest und zeichnet es bei einer Breitenaenderung nicht neu; unter etwa 600 px ueberlagern sich Wochentage und Stundenachse. Es wird jetzt in mindestens 640 px Breite geladen - auf breiten Karten gleich in Kartenbreite, dort aendert sich nichts - und, wenn die Karte schmaler ist, als Ganzes verkleinert. Zuschnitt und Skalierung setzt das Skript direkt am Element, nicht ueber das Stylesheet: sonst haengt die Darstellung an einer womoeglich veralteten solar.css im Browser-Cache, und der breit geladene Rahmen ragt ungeschnitten aus der Karte. Passend dazu bekommt solar.css eine Versionskennung aus filemtime(), wie sie die Skripte in footer.php und adminlte.min.css laengst tragen. Ohne sie kam auf schon einmal besuchten Geraeten die alte Datei aus dem Cache. Die Statistik-Kacheln lagen in nackten .col ohne Breitenangabe; Bootstrap laesst sie dann nach Textlaenge umbrechen, mal zwei, mal drei je Zeile und unterschiedlich breit. Die Breite kommt jetzt aus row-cols-2/row-cols-md-4, und die Karte fuellt die Zeilenhoehe, damit die Werte trotz ein- oder zweizeiliger Titel auf einer Linie stehen. Zuletzt sind die Abstaende unter 768 px enger gefasst - auf .app-content beschraenkt, damit Seitenleiste, Kopfzeile und Modals unberuehrt bleiben: Spaltenabstand 24 -> 8 px, Kartenabstand 24 -> 12 px, Polsterung 16 -> 8 px. Die nutzbare Breite steigt damit von 301 auf 317 px. Geprueft bei 375 und 1200 px auf Solar, Historie, Heizung, Home und Wetter: kein Querlauf, am Rechner unveraenderte Werte. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -66,7 +66,7 @@ function array_insert($array,$values,$offset) {
|
|||||||
|
|
||||||
if (checkLogin()) {
|
if (checkLogin()) {
|
||||||
|
|
||||||
$html = "<div class='row row-info'>";
|
$html = "<div class='row row-cols-2 row-cols-md-4 g-2 row-info'>";
|
||||||
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
|
$mysql = new mysqli($mysql_server, $mysql_solarUser, $mysql_solarPass, $mysql_solarDB);
|
||||||
$Res = mysqli_query($mysql,$Query);
|
$Res = mysqli_query($mysql,$Query);
|
||||||
$ResPrev = mysqli_query($mysql,$PrevQuery);
|
$ResPrev = mysqli_query($mysql,$PrevQuery);
|
||||||
@@ -84,7 +84,7 @@ if (checkLogin()) {
|
|||||||
foreach ($row as $name => $value) {
|
foreach ($row as $name => $value) {
|
||||||
if(str_starts_with($name,"Autoladung ges.")){
|
if(str_starts_with($name,"Autoladung ges.")){
|
||||||
$html .= "</div><hr class='mt-2 mb-3 border-light' />";
|
$html .= "</div><hr class='mt-2 mb-3 border-light' />";
|
||||||
$html .= "<div class='row row-info'>";
|
$html .= "<div class='row row-cols-2 row-cols-md-4 g-2 row-info'>";
|
||||||
}
|
}
|
||||||
/*$html .= "<div class='col-12 col-sm-4 col-md-2 col-xl-1'>
|
/*$html .= "<div class='col-12 col-sm-4 col-md-2 col-xl-1'>
|
||||||
<div class='info-box'>
|
<div class='info-box'>
|
||||||
|
|||||||
@@ -19,3 +19,69 @@ input[type='range']::-webkit-slider-runnable-track {
|
|||||||
background-size: var(--background-size, 0%) 100%;
|
background-size: var(--background-size, 0%) 100%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Diagramme (Chart.js). Die Hoehe kommt aus diesem Container, nicht aus dem
|
||||||
|
canvas - die Charts laufen mit maintainAspectRatio: false. Auf dem Handy
|
||||||
|
ist der Container nur rund 300 px breit; mit 400 px Hoehe wird aus einer
|
||||||
|
Zeitreihe ein Hochformat, in dem die Zeitachse die kurze Seite ist. */
|
||||||
|
.chart-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.chart-container {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Statistik-Kacheln (ajax/getStats.php). Sie lagen in nackten .col ohne
|
||||||
|
Breitenangabe - Bootstrap laesst sie dann nach Textlaenge umbrechen, mal
|
||||||
|
zwei, mal drei je Zeile und unterschiedlich breit. Die Breite kommt jetzt
|
||||||
|
aus row-cols-* in getStats.php; hier sorgt die volle Kartenhoehe dafuer,
|
||||||
|
dass die Werte trotz ein- oder zweizeiliger Titel auf einer Linie
|
||||||
|
stehen. */
|
||||||
|
.card.stats {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.stats .card-body {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Auf dem Handy gehen von 375 px rund 75 an Innenabstaende verloren, und
|
||||||
|
zwischen den Karten stehen 24 px. Beides wird hier enger gefasst - nur
|
||||||
|
im Inhaltsbereich, damit Seitenleiste, Kopfzeile und Modals unberuehrt
|
||||||
|
bleiben. Die Abstandsklassen von Bootstrap (mb-4) tragen !important,
|
||||||
|
deshalb steht es auch hier. */
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.app-content {
|
||||||
|
padding: 0 .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-content-header {
|
||||||
|
padding: .5rem .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-content .row {
|
||||||
|
--bs-gutter-x: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-content .card {
|
||||||
|
margin-bottom: .75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nur der Standardwert wird kleiner; eigene Angaben im Markup (p-0 fuer
|
||||||
|
das Realtime-SVG, p-2 fuer die Statistik) gelten weiter. */
|
||||||
|
.app-content .card-body {
|
||||||
|
padding: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Eine Kachel ist auf dem Handy rund 150 px breit. In voller Schrift
|
||||||
|
passt "Verbrauchsersparnis" dort nicht in eine Zeile und wird mitten
|
||||||
|
im Wort umbrochen. */
|
||||||
|
.card.stats .card-body {
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+51
-3
@@ -156,12 +156,60 @@ function bindModalSlider(slider, span, label) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Meteoblue-Meteogramm einhängen, sofern die Seite einen Platz dafür hat. */
|
/** Meteoblue-Meteogramm einhängen, sofern die Seite einen Platz dafür hat. */
|
||||||
|
// Mindestbreite, in der das Meteogramm von meteoblue geladen wird. Der
|
||||||
|
// Anbieter legt sein Bild einmal beim Laden fest und zeichnet es bei einer
|
||||||
|
// Breitenaenderung nicht neu; unterhalb von etwa 600 px ueberlagern sich
|
||||||
|
// Wochentage und Stundenachse zu einem unlesbaren Streifen. Auf schmalen
|
||||||
|
// Schirmen wird es deshalb in dieser Breite geladen und als Ganzes
|
||||||
|
// verkleinert - dieselbe Ansicht wie am Rechner, nur kleiner. Ist die Karte
|
||||||
|
// breiter, wird gleich in Kartenbreite geladen und nichts skaliert.
|
||||||
|
const METEOGRAM_BREITE = 640;
|
||||||
|
const METEOGRAM_HOEHE = 500;
|
||||||
|
|
||||||
function mountMeteogram() {
|
function mountMeteogram() {
|
||||||
const target = document.getElementById("meteogram");
|
const ziel = document.getElementById("meteogram");
|
||||||
if (!target) return;
|
if (!ziel) return;
|
||||||
// loading="lazy": das Meteogramm ist ein vollstaendiges Fremd-Dokument und
|
// loading="lazy": das Meteogramm ist ein vollstaendiges Fremd-Dokument und
|
||||||
// liegt unterhalb der Falz - es wird erst geladen, wenn man hinscrollt.
|
// liegt unterhalb der Falz - es wird erst geladen, wenn man hinscrollt.
|
||||||
target.innerHTML = "<iframe loading='lazy' src='" + meteogramURL + "' frameborder='0' scrolling=NO' allowtransparency='true' sandbox='allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox' style='width: 100%;height: 500px;border: 0;overflow: hidden;'></iframe><!-- DO NOT REMOVE THIS LINK --><a href='https://www.meteoblue.com/de/wetter/woche/index' target='_blank' rel='noopener'></a>";
|
const stil = window.getComputedStyle(ziel);
|
||||||
|
const innenBreite = ziel.clientWidth - parseFloat(stil.paddingLeft) - parseFloat(stil.paddingRight);
|
||||||
|
const ladeBreite = Math.max(METEOGRAM_BREITE, Math.round(innenBreite) || 0);
|
||||||
|
ziel.innerHTML =
|
||||||
|
"<div class='meteogram-buehne'>"
|
||||||
|
+ "<iframe loading='lazy' src='" + meteogramURL + "' frameborder='0' scrolling='no'"
|
||||||
|
+ " allowtransparency='true'"
|
||||||
|
+ " sandbox='allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox'"
|
||||||
|
+ " style='width:" + ladeBreite + "px;height:" + METEOGRAM_HOEHE + "px;border:0;overflow:hidden;'></iframe>"
|
||||||
|
+ "</div>"
|
||||||
|
+ "<!-- DO NOT REMOVE THIS LINK -->"
|
||||||
|
+ "<a href='https://www.meteoblue.com/de/wetter/woche/index' target='_blank' rel='noopener'></a>";
|
||||||
|
|
||||||
|
const buehne = ziel.querySelector(".meteogram-buehne");
|
||||||
|
const rahmen = buehne.querySelector("iframe");
|
||||||
|
// Zuschnitt und Skalierung stehen hier und nicht im Stylesheet: sonst
|
||||||
|
// haengt die Darstellung an einer womoeglich veralteten solar.css im
|
||||||
|
// Browser-Cache, und der breit geladene Rahmen ragte ungeschnitten aus
|
||||||
|
// der Karte heraus.
|
||||||
|
buehne.style.overflow = "hidden";
|
||||||
|
rahmen.style.display = "block";
|
||||||
|
rahmen.style.transformOrigin = "0 0";
|
||||||
|
let letzteBreite = 0;
|
||||||
|
const anpassen = function () {
|
||||||
|
const breite = buehne.clientWidth;
|
||||||
|
if (breite === 0 || breite === letzteBreite) return;
|
||||||
|
letzteBreite = breite;
|
||||||
|
const faktor = Math.min(1, breite / ladeBreite);
|
||||||
|
rahmen.style.transform = "scale(" + faktor + ")";
|
||||||
|
buehne.style.height = Math.round(METEOGRAM_HOEHE * faktor) + "px";
|
||||||
|
};
|
||||||
|
anpassen();
|
||||||
|
// Nur auf Breitenaenderungen reagieren - die Hoehe setzt anpassen() selbst,
|
||||||
|
// sonst riefe sich der Beobachter gegenseitig auf.
|
||||||
|
if (window.ResizeObserver) {
|
||||||
|
new ResizeObserver(anpassen).observe(buehne);
|
||||||
|
} else {
|
||||||
|
window.addEventListener("resize", anpassen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -48,7 +48,11 @@
|
|||||||
// bei DPR 3 rund 75 %.
|
// bei DPR 3 rund 75 %.
|
||||||
Chart.defaults.devicePixelRatio = Math.min(1.5, window.devicePixelRatio || 1);
|
Chart.defaults.devicePixelRatio = Math.min(1.5, window.devicePixelRatio || 1);
|
||||||
|
|
||||||
Chart.defaults.font.size = 10;
|
// Auf schmalen Schirmen ist die Zeichenflaeche nur rund 300 px breit -
|
||||||
|
// 10 px Schrift nehmen dort zu viel davon weg. Gleiche Schwelle wie die
|
||||||
|
// flachere Diagrammhoehe in css/solar.css.
|
||||||
|
const schmalerSchirm = window.matchMedia("(max-width: 767.98px)").matches;
|
||||||
|
Chart.defaults.font.size = schmalerSchirm ? 8 : 10;
|
||||||
Chart.defaults.animations = false;
|
Chart.defaults.animations = false;
|
||||||
Chart.defaults.animation = false;
|
Chart.defaults.animation = false;
|
||||||
Chart.defaults.plugins.legend.position = "bottom";
|
Chart.defaults.plugins.legend.position = "bottom";
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ if (!isset($_GET["floor"]))
|
|||||||
<!-- Skip links will be dynamically added by accessibility.js -->
|
<!-- Skip links will be dynamically added by accessibility.js -->
|
||||||
<meta name="supported-color-schemes" content="light dark" />
|
<meta name="supported-color-schemes" content="light dark" />
|
||||||
<link rel="preload" href="./css/adminlte.min.css?v=2" as="style" />
|
<link rel="preload" href="./css/adminlte.min.css?v=2" as="style" />
|
||||||
<link rel="stylesheet" href="./css/solar.css" />
|
<link rel="stylesheet" href="./css/solar.css?v=<?= filemtime("css/solar.css") ?>" />
|
||||||
<!--end::Accessibility Features-->
|
<!--end::Accessibility Features-->
|
||||||
|
|
||||||
<!--begin::Fonts-->
|
<!--begin::Fonts-->
|
||||||
|
|||||||
+4
-4
@@ -60,8 +60,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body pb-1">
|
<div class="card-body pb-1">
|
||||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
<div class="chart-container">
|
||||||
<canvas id="heat-chart" height="400px;"></canvas>
|
<canvas id="heat-chart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -86,8 +86,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body pb-1">
|
<div class="card-body pb-1">
|
||||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
<div class="chart-container">
|
||||||
<canvas id="water-chart" height="400px;"></canvas>
|
<canvas id="water-chart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ $statistics = [
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body pb-1">
|
<div class="card-body pb-1">
|
||||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
<div class="chart-container">
|
||||||
<canvas id="<?= $kind ?>-chart<?= $period == "month" ? "" : "-" . $period ?>" height="400px;"></canvas>
|
<canvas id="<?= $kind ?>-chart<?= $period == "month" ? "" : "-" . $period ?>"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -111,8 +111,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body pb-1">
|
<div class="card-body pb-1">
|
||||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
<div class="chart-container">
|
||||||
<canvas id="forecast-chart" height="400px;"></canvas>
|
<canvas id="forecast-chart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,8 +142,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body pb-1">
|
<div class="card-body pb-1">
|
||||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
<div class="chart-container">
|
||||||
<canvas id="consumption-chart" height="400px;"></canvas>
|
<canvas id="consumption-chart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,8 +172,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body pb-1">
|
<div class="card-body pb-1">
|
||||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
<div class="chart-container">
|
||||||
<canvas id="production-chart" height="400px;"></canvas>
|
<canvas id="production-chart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user