Raum-Modal: Regler gedreht statt writing-mode, eigenes Aussehen
Der senkrechte Positionsregler liess sich am Handy kaum anfassen. Gebaut
war er mit writing-mode: vertical-rl - dem neueren Weg, aber einem, bei
dem der Browser das Ziehen als Wischen liest und die Seite blaettert,
statt den Griff mitzunehmen.
Jetzt liegt ein gewoehnlicher waagerechter Regler um 90 Grad gedreht in
seinem Kasten. Er bewegt sich in seinen eigenen Koordinaten waagerecht,
wird von jedem Browser unterstuetzt, traegt dieselbe Gestaltung wie die
liegenden Regler, und touch-action: none haelt die Seite still, solange
der Finger auf ihm liegt. Die Trefferflaeche ist 1,6 rem breit statt der
sichtbaren 0,375 rem Bahn. Nachgemessen: oben angeklickt 8 %, unten 93 %.
Die Neigung steht jetzt ebenfalls senkrecht, daneben das Lamellenbild -
Regler und Bild bilden ein Paar, das Bild sagt, was der Regler bedeutet.
Beide Spalten sind mit Namen und den Worten an ihren Enden beschriftet
("oben"/"unten", "auf"/"zu"); die Zahl darunter ist das, was sich beim
Ziehen aendert.
Die Regler im Raum-Modal haben ein eigenes Aussehen bekommen: Bootstraps
weisse Bahn mit blauem Griff stach auf den dunklen Karten heraus, und in
einem Raum mit drei Jalousien waren das sechs helle Balken. Bahn und Griff
tragen jetzt dasselbe Blaugruen wie der Temperaturregler, der ungefuellte
Teil ein Grau, das in beiden Themes traegt. Die Regler in den Modals fuer
Autoladung und Heizstab bleiben unberuehrt.
Die Regel fuer die Bahn steht zweimal da, einmal fuer -webkit- und einmal
fuer -moz-: als Liste notiert wirft der Browser beim unbekannten Selektor
die ganze Regel weg, und dann bliebe die Bahn ungestaltet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+108
-25
@@ -160,14 +160,75 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Schieberegler stehen dicht untereinander (Position und Neigung). Ohne den
|
||||
/* --------------------------------------------------------------------------
|
||||
Regler im Raum-Modal
|
||||
|
||||
Eigenes Aussehen statt des Bootstrap-Standards: dessen weisse Bahn mit dem
|
||||
blauen Griff sticht auf den dunklen Karten heraus, und in einem Raum mit
|
||||
drei Jalousien sind das sechs helle Balken. Bahn und Griff tragen deshalb
|
||||
dasselbe Blaugruen wie der Temperaturregler, und der ungefuellte Teil ist
|
||||
ein Grau, das in beiden Themes traegt.
|
||||
|
||||
Bewusst nur innerhalb von #roomView: die Regler in den Modals fuer
|
||||
Autoladung und Heizstab bleiben, wie sie sind.
|
||||
-------------------------------------------------------------------------- */
|
||||
#roomView input[type='range'] {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
height: 1.5rem;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
}
|
||||
#roomView input[type='range']:focus {
|
||||
outline: 0;
|
||||
}
|
||||
/* Getrennt notiert, nicht als Liste: einen Selektor, den er nicht kennt,
|
||||
wirft der Browser samt der ganzen Regel weg - und dann bliebe die Bahn
|
||||
ungestaltet. */
|
||||
#roomView input[type='range']::-webkit-slider-runnable-track {
|
||||
height: 0.375rem;
|
||||
border: 0;
|
||||
border-radius: 0.375rem;
|
||||
background: linear-gradient(to right, #00788F, #00788F), rgba(128, 128, 128, 0.32);
|
||||
background-size: var(--background-size, 0%) 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
#roomView input[type='range']::-moz-range-track {
|
||||
height: 0.375rem;
|
||||
border: 0;
|
||||
border-radius: 0.375rem;
|
||||
background: linear-gradient(to right, #00788F, #00788F), rgba(128, 128, 128, 0.32);
|
||||
background-size: var(--background-size, 0%) 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
#roomView input[type='range']::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 1.05rem;
|
||||
height: 1.05rem;
|
||||
/* (Bahnhoehe - Griffhoehe) / 2, damit der Griff auf der Bahn sitzt. */
|
||||
margin-top: -0.34rem;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 50%;
|
||||
background: #00788F;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
#roomView input[type='range']::-moz-range-thumb {
|
||||
width: 1.05rem;
|
||||
height: 1.05rem;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 50%;
|
||||
background: #00788F;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
/* Schieberegler stehen dicht untereinander (Helligkeit, Farbe). Ohne den
|
||||
Abstand kleben Beschriftung und Bahn aneinander. */
|
||||
.raum-regler + .raum-regler {
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
.raum-regler .form-range {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Messwerte als Gitter statt als Textwurst: ein Stromzaehler hat sechzehn
|
||||
Werte, die in einer Zeile niemand findet. auto-fill statt fester Spalten,
|
||||
@@ -216,10 +277,14 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
align-items: stretch;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
/* Neigungsregler und Lamellenbild gehoeren zusammen: das Bild sagt, was der
|
||||
Regler daneben bedeutet, und laeuft beim Ziehen mit. */
|
||||
.raum-jalousie .raum-neigung-block {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0.4rem;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
align-self: center;
|
||||
}
|
||||
.raum-jalousie .dropdown {
|
||||
align-self: flex-start;
|
||||
@@ -235,28 +300,42 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Die Hoehe als senkrechter Regler: der Griff steht dort, wo der Rollladen
|
||||
steht. writing-mode ist der Weg, den Chrome und Firefox heute gehen -
|
||||
slider-vertical war nie standardisiert und ist inzwischen entfernt. */
|
||||
.raum-position {
|
||||
flex: 0 0 auto;
|
||||
/* Eine Spalte mit senkrechtem Regler: Name, oberes Wort, Bahn, unteres
|
||||
Wort, Zahl. Breit genug fuer "Position" in der kleinen Schrift. */
|
||||
.raum-spalte {
|
||||
flex: 0 0 3.4rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
.raum-position input[type='range'] {
|
||||
writing-mode: vertical-rl;
|
||||
width: 1.2rem;
|
||||
height: 4.5rem;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
.raum-name {
|
||||
font-size: 0.62rem;
|
||||
opacity: 0.8;
|
||||
white-space: nowrap;
|
||||
line-height: 1.2;
|
||||
}
|
||||
/* Die gefuellte Bahn laeuft hier von oben nach unten mit - "voll" heisst
|
||||
heruntergefahren. */
|
||||
.raum-position input[type='range']::-webkit-slider-runnable-track {
|
||||
background: linear-gradient(to bottom, #00788F, #00788F), #D7D7D7;
|
||||
background-size: 100% var(--background-size, 0%);
|
||||
|
||||
/* Der Kasten, in dem ein gewoehnlicher Regler auf der Seite liegt.
|
||||
Gedreht statt writing-mode: so gebaute Regler lassen sich am Handy kaum
|
||||
anfassen - das Ziehen wird als Wischen gelesen und blaettert die Seite.
|
||||
Gedreht bewegt sich der Regler in seinen eigenen Koordinaten waagerecht,
|
||||
und touch-action haelt die Seite still, solange der Finger auf ihm liegt.
|
||||
rotate(90deg) legt den kleinen Wert nach oben: "oben" ist 0 %. */
|
||||
.raum-senkrecht {
|
||||
position: relative;
|
||||
width: 1.6rem;
|
||||
height: 5rem;
|
||||
margin: 0.1rem 0;
|
||||
}
|
||||
#roomView .raum-senkrecht input[type='range'] {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 5rem; /* = Hoehe des Kastens, die Laenge der Bahn */
|
||||
height: 1.6rem; /* = Breite des Kastens, die Flaeche zum Treffen */
|
||||
transform: translate(-50%, -50%) rotate(90deg);
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
/* Die Endstellungen in Worten statt in Prozent. */
|
||||
@@ -271,9 +350,10 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
aneinanderliegend heisst geschlossen. */
|
||||
.raum-lamellen {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 1.8rem;
|
||||
margin: 0.1rem 0;
|
||||
flex: 1 1 auto;
|
||||
min-width: 2.5rem;
|
||||
align-self: center;
|
||||
height: 5rem;
|
||||
/* Der Rahmen macht aus dem Streifen ein Fenster - ohne ihn liest sich das
|
||||
geschlossene Bild wie eine zweite Reglerbahn. */
|
||||
background: rgba(0, 120, 143, 0.14);
|
||||
@@ -283,4 +363,7 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
.raum-lamelle {
|
||||
fill: currentColor;
|
||||
opacity: 0.6;
|
||||
stroke: rgba(0, 0, 0, 0.35);
|
||||
stroke-width: 0.6;
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
|
||||
@@ -282,9 +282,9 @@ function switchFloor(floor){
|
||||
/**
|
||||
* Anzeige, gefuellte Bahn und Lamellenbild eines Reglers nachziehen.
|
||||
*
|
||||
* An den Endstellungen steht ein Wort statt der Zahl: "unten" liest sich
|
||||
* ohne Umweg, "100 %" muss man erst uebersetzen. Dazwischen bleibt es bei
|
||||
* der Prozentzahl - fuer halb heruntergefahren gibt es kein Wort.
|
||||
* Was 0 % und 100 % bedeuten, steht bei den senkrechten Reglern als Wort
|
||||
* an ihren Enden ("oben"/"unten", "auf"/"zu"); die Anzeige braucht deshalb
|
||||
* nur noch die Zahl, und die ist beim Ziehen das Interessante.
|
||||
*/
|
||||
function reglerAnzeigen(regler) {
|
||||
const schieber = regler.querySelector("input[type=range]");
|
||||
@@ -292,10 +292,7 @@ function switchFloor(floor){
|
||||
const wert = Number(schieber.value);
|
||||
|
||||
if (anzeige) {
|
||||
const worte = regler.dataset.worte ? JSON.parse(regler.dataset.worte) : null;
|
||||
anzeige.textContent = (worte && worte[wert] !== undefined)
|
||||
? worte[wert]
|
||||
: wert + (schieber.dataset.einheit || "");
|
||||
anzeige.textContent = wert + (schieber.dataset.einheit || "");
|
||||
}
|
||||
|
||||
// Der gefuellte Anteil der Bahn - dieselbe Eigenschaft, aus der auch
|
||||
@@ -314,7 +311,9 @@ function switchFloor(floor){
|
||||
* Gezeichnet wird die Hoehe, die eine gekippte Lamelle von vorn zeigt:
|
||||
* w * sin(Winkel). Bei 0 % steht sie waagerecht und man sieht nur ihre
|
||||
* Kante, bei 100 % steht sie quer und deckt den Abstand zur naechsten
|
||||
* vollstaendig ab - genau das, was das Licht abhaelt.
|
||||
* vollstaendig ab - genau das, was das Licht abhaelt. Der Abstand von
|
||||
* Mitte zu Mitte ist 10, die Lamelle 11 tief: ab etwa 65 % schliesst
|
||||
* das Bild, so wie es die Jalousie auch tut.
|
||||
*/
|
||||
function lamellenZeichnen(block, wert, min, max) {
|
||||
if (!block) return;
|
||||
|
||||
+38
-49
@@ -260,75 +260,57 @@ function reglerWert($wert, $min, $max)
|
||||
return max($min, min($max, $wert));
|
||||
}
|
||||
|
||||
function reglerFeld($min, $max, $wert, $einheit)
|
||||
function reglerFeld($min, $max, $wert, $einheit, $beschriftung = "")
|
||||
{
|
||||
return "<input type='range' class='form-range range-color-track' min='" . $min . "' max='" . $max . "'"
|
||||
. " step='1' value='" . $wert . "' data-einheit='" . htmlspecialchars($einheit, ENT_QUOTES) . "'>";
|
||||
. " step='1' value='" . $wert . "' data-einheit='" . htmlspecialchars($einheit, ENT_QUOTES) . "'"
|
||||
. ($beschriftung === "" ? ""
|
||||
: " aria-label='" . htmlspecialchars($beschriftung, ENT_QUOTES) . "'")
|
||||
. ">";
|
||||
}
|
||||
|
||||
/**
|
||||
* Die beiden Endstellungen in Worten.
|
||||
* Ein senkrechter Regler mit Wort an jedem Ende.
|
||||
*
|
||||
* "Position 100 %" muss man uebersetzen, "unten" nicht. Dazwischen bleibt es
|
||||
* bei der Zahl - fuer halb heruntergefahren gibt es kein Wort. Ausgewertet
|
||||
* wird das Attribut in raumBedienungAktivieren(), js/solar/homeMQTT.js.
|
||||
*/
|
||||
function worteAttribut($beiNull, $beiHundert)
|
||||
{
|
||||
return " data-worte='" . htmlspecialchars(
|
||||
json_encode([0 => $beiNull, 100 => $beiHundert], JSON_UNESCAPED_UNICODE), ENT_QUOTES) . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Hoehe als senkrechter Regler - oben ist oben.
|
||||
* Beide Werte einer Jalousie bewegen etwas, das oben und unten hat; ein
|
||||
* waagerechter Schieber dafuer muss erst uebersetzt werden. Senkrecht steht
|
||||
* der Griff dort, wo der Rollladen steht.
|
||||
*
|
||||
* Einen waagerechten Schieber fuer eine Bewegung, die hoch und runter geht,
|
||||
* muss man erst uebersetzen; senkrecht steht der Griff dort, wo der Rollladen
|
||||
* steht.
|
||||
* Gedreht wird mit transform, nicht mit writing-mode. writing-mode ist zwar
|
||||
* der neuere Weg, aber am Handy laesst sich ein so gebauter Regler nur
|
||||
* schlecht anfassen - das Ziehen wird als Wischen gelesen und blaettert die
|
||||
* Seite, statt den Griff mitzunehmen. Ein gedrehter gewoehnlicher Regler
|
||||
* bewegt sich in seinen eigenen Koordinaten waagerecht, wird von jedem
|
||||
* Browser unterstuetzt und traegt dieselbe Gestaltung wie die liegenden.
|
||||
*/
|
||||
function positionsRegler($cmd, $param, $wert)
|
||||
function senkrechterRegler($cmd, $param, $wert, $titel, $oben, $unten)
|
||||
{
|
||||
$min = reglerMin($param);
|
||||
$max = reglerMax($param);
|
||||
$wert = reglerWert($wert, $min, $max);
|
||||
return "<div class='raum-regler raum-position' data-cmd='" . intval($cmd["id"]) . "'"
|
||||
. " data-param='" . intval($param["id"]) . "'" . worteAttribut("oben", "unten") . ">"
|
||||
. "<span class='raum-ende'>oben</span>"
|
||||
. reglerFeld($min, $max, $wert, "%")
|
||||
. "<span class='raum-ende'>unten</span>"
|
||||
return "<div class='raum-regler raum-spalte' data-cmd='" . intval($cmd["id"]) . "'"
|
||||
. " data-param='" . intval($param["id"]) . "'>"
|
||||
. "<span class='raum-name'>" . htmlspecialchars($titel) . "</span>"
|
||||
. "<span class='raum-ende'>" . htmlspecialchars($oben) . "</span>"
|
||||
. "<div class='raum-senkrecht'>" . reglerFeld($min, $max, $wert, "%", $titel) . "</div>"
|
||||
. "<span class='raum-ende'>" . htmlspecialchars($unten) . "</span>"
|
||||
. "<span class='raum-regler-wert small fw-semibold'>" . $wert . "%</span>"
|
||||
. "</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Lamellenstellung mit einem Bild daneben.
|
||||
* Die sechs Lamellen neben dem Neigungsregler.
|
||||
*
|
||||
* Bei 30 % oder 70 % sagt die Zahl nicht, ob man noch hinaussieht. Die vier
|
||||
* Bei 30 % oder 70 % sagt die Zahl nicht, ob man noch hinaussieht. Die
|
||||
* Streifen zeigen es: schmal mit Luft dazwischen heisst offen, geschlossen
|
||||
* liegen sie aneinander. Gezeichnet wird die Hoehe, die eine gekippte
|
||||
* Lamelle von vorn zeigt - genau das, was das Licht abhaelt.
|
||||
* Lamelle von vorn zeigt - genau das, was das Licht abhaelt. Die Hoehe setzt
|
||||
* lamellenZeichnen() in js/solar/homeMQTT.js.
|
||||
*/
|
||||
function neigungsRegler($cmd, $param, $wert)
|
||||
{
|
||||
$min = reglerMin($param);
|
||||
$max = reglerMax($param);
|
||||
$wert = reglerWert($wert, $min, $max);
|
||||
return "<div class='raum-regler raum-neigung raum-neigung-block'"
|
||||
. " data-cmd='" . intval($cmd["id"]) . "'"
|
||||
. " data-param='" . intval($param["id"]) . "'" . worteAttribut("auf", "zu") . ">"
|
||||
. "<div class='d-flex justify-content-between small'>"
|
||||
. "<span>Neigung</span>"
|
||||
. "<span class='raum-regler-wert fw-semibold'>" . $wert . "%</span></div>"
|
||||
. lamellenBild()
|
||||
. reglerFeld($min, $max, $wert, "%")
|
||||
. "<div class='d-flex justify-content-between raum-ende'><span>auf</span><span>zu</span></div>"
|
||||
. "</div>";
|
||||
}
|
||||
|
||||
/** Die vier Lamellen. Ihre Hoehe setzt der Browser, siehe homeMQTT.js. */
|
||||
function lamellenBild()
|
||||
{
|
||||
$html = "<svg class='raum-lamellen' viewBox='0 0 100 40' preserveAspectRatio='none' aria-hidden='true'>";
|
||||
foreach ([5, 15, 25, 35] as $mitte) {
|
||||
$html = "<svg class='raum-lamellen' viewBox='0 0 100 60' preserveAspectRatio='none' aria-hidden='true'>";
|
||||
foreach ([5, 15, 25, 35, 45, 55] as $mitte) {
|
||||
$html .= "<rect class='raum-lamelle' x='0' width='100' data-mitte='" . $mitte . "'"
|
||||
. " y='" . ($mitte - 1) . "' height='2'></rect>";
|
||||
}
|
||||
@@ -453,10 +435,17 @@ function zeichneBeschattung($d)
|
||||
$html .= "</div>";
|
||||
}
|
||||
if ($position) {
|
||||
$html .= positionsRegler($position, $position["params"][0], $standPos);
|
||||
$html .= senkrechterRegler($position, $position["params"][0], $standPos,
|
||||
"Position", "oben", "unten");
|
||||
}
|
||||
if ($neigung) {
|
||||
$html .= neigungsRegler($neigung, $neigung["params"][0], $standNeigung);
|
||||
// Regler und Lamellenbild bilden ein Paar: das Bild sagt, was der
|
||||
// Regler daneben bedeutet, und laeuft beim Ziehen mit.
|
||||
$html .= "<div class='raum-neigung-block'>"
|
||||
. senkrechterRegler($neigung, $neigung["params"][0], $standNeigung,
|
||||
"Neigung", "auf", "zu")
|
||||
. lamellenBild()
|
||||
. "</div>";
|
||||
}
|
||||
$html .= mehrMenue($rest);
|
||||
return $html . "</div>" . karteZu();
|
||||
|
||||
Reference in New Issue
Block a user