5 Punkte von GN⁺ 2025-09-09 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Einführung, wie sich der von Apple auf der WWDC 2025 vorgestellte Liquid-Glass-Effekt im Web mit CSS, SVG und physikbasierter Brechungsberechnung nachbilden lässt
  • Erklärung der Prinzipien der Lichtbrechung und des Einsatzes des Snelliusschen Gesetzes zur Darstellung einer Glasoberfläche und zur Simulation der Brechung
  • Demonstration, wie sich mit einer SVG-Displacement-Map ein für das Rendering geeignetes Verschiebungsvektorfeld erzeugen und auf echte UI-Komponenten anwenden lässt
  • In Chrome kann ein SVG-Filter als backdrop-filter genutzt werden; gezeigt werden Beispiele für verschiedene UI-Elemente (Lupe, Schalter, Player usw.)
  • Echtzeiteffekte sind möglich, es gibt jedoch Cross-Browser-Probleme und Performance-Grenzen; außerdem wird ein künftiger Open-Source-Plan erwähnt

Einführung

Apple hat den Liquid-Glass-Effekt erstmals im Juni 2025 auf der WWDC vorgestellt. Dieser Effekt lässt Interface-Elemente wie gebogenes Brechungsglas erscheinen und erzeugt so ein visuelles Erlebnis, das an echte Glasoberflächen erinnert. Dieser Artikel behandelt eine praktische Umsetzung, mit der sich in einer Web-Umgebung ein ähnlicher Effekt über CSS, SVG-Displacement-Maps und physikbasierte Brechungsberechnungen erzeugen lässt. Ziel ist keine vollständige Reproduktion, sondern ein skalierbarer Proof of Concept, der zentrale Merkmale wie Brechung und reflektierende Highlights nachbildet. Dafür wird schrittweise vom Grundprinzip ausgegangen, wie Licht beim Durchgang durch unterschiedliche Materialien gebrochen wird. Die am Ende bereitgestellte interaktive Demo funktioniert derzeit nur in Chrome korrekt.

Die Brechung verstehen

Brechung bezeichnet das Phänomen, dass Licht seine Ausbreitungsrichtung ändert, wenn es von einem Material in ein anderes übergeht. Das geschieht, weil sich die Lichtgeschwindigkeit je nach Material unterscheidet; die Beziehung zwischen Einfallswinkel und Brechungswinkel wird durch das Snelliussche Gesetz beschrieben:

  • n1 * sin(θ1) = n2 * sin(θ2)
    • n1: Brechungsindex des ersten Mediums
    • θ1: Einfallswinkel
    • n2: Brechungsindex des zweiten Mediums
    • θ2: Brechungswinkel

Was sich im interaktiven Diagramm beobachten lässt:

  • Haben beide Medien denselben Brechungsindex, läuft das Licht ohne Brechung geradeaus
  • Hat das zweite Medium einen höheren Brechungsindex, wird das Licht zur Normalen hin gebrochen
  • Hat das zweite Medium einen niedrigeren Brechungsindex, wird das Licht von der Normalen weg gebrochen; unter Umständen kann totale interne Reflexion auftreten
  • Fällt das Licht senkrecht auf die Oberfläche, läuft es unabhängig vom Brechungsindex geradeaus

Grenzen dieses Projekts

Um die Komplexität zu begrenzen und den Algorithmus zu vereinfachen, werden folgende Bedingungen gesetzt:

  • Brechungsindex des äußeren Mediums ist 1 (Luft)
  • Für das innere Glasmaterial wird 1,5 verwendet (typisches Glas)
  • Es wird nur ein Brechungsereignis berücksichtigt (Brechung am Austritt wird ignoriert)
  • Einfallendes Licht steht immer senkrecht auf der Hintergrundebene
  • Alle Objekte sind 2D-Formen, es werden nur Kreisformen verwendet (auf Rechtecke usw. erweiterbar, aber mit zusätzlicher Berechnung)
  • Zwischen Objekt und Hintergrundebene gibt es keinen Abstand
  • Unter diesen Bedingungen lassen sich alle Lichtstrahlen mit dem Snelliusschen Gesetz einfach berechnen

Eine Glasoberfläche erzeugen

Um den Liquid-Glass-Effekt umzusetzen, muss der Querschnitt des virtuellen Glases (Linse oder gebogenes Panel) als mathematische Funktion definiert werden.

Oberflächenfunktion

Die Glasoberfläche wird über eine surface function definiert und beschreibt die Dicke vom Rand bis zum flachen Inneren.

  • Eingabewert der Funktion 0: Außenkante, 1: Ende der Fase (Beginn der flachen Fläche)
  • Aus der Ableitung an jedem Punkt der Dicke wird der Normalenvektor der Oberfläche bestimmt
const height = f(distanceFromSide);
const delta = 0.001;
const y1 = f(distanceFromSide - delta);
const y2 = f(distanceFromSide + delta);
const derivative = (y2 - y1) / (2 * delta);
const normal = { x: -derivative, y: 1 };

Wichtige Typen von Oberflächenfunktionen

  • Convex Circle: y = sqrt((1 - (1 - x))^2)
    • Einfache Kreisbogenform, die nach innen hin schnell flach wird und dadurch eine deutliche Brechung am Rand erzeugt
  • Convex Squircle: y = ((1 - (1 - x))^4)^(1/4)
    • Eine von Apple bevorzugte Form, bei der der Übergang zwischen Kurve und Fläche weich ist und der Effekt auch bei Skalierung natürlich wirkt
  • Concave: y = 1 - Convex(x)
    • Konkave Form, bei der Licht über die Objektgrenze hinaus nach außen gebrochen wird, sodass Sampling außerhalb erforderlich ist
  • Lip: y = mix(Convex(x), Concave(x), Smootherstep(x))
    • Zusammengesetzte Struktur mit hervorstehender Lippe am Rand und flacher Einbuchtung in der Mitte

Schon mit diesen vier Funktionen lassen sich die Unterschiede der Brechung je nach Oberflächenform gut vergleichen.

Simulation

Für jede Oberflächenfunktion wird der Brechungspfad der Lichtstrahlen simuliert, um die tatsächlichen visuellen Unterschiede sichtbar zu machen.

  • Konvex bündelt die Lichtpfade nach innen, konkav drückt sie nach außen
  • Apples Liquid Glass bevorzugt meist konvexe Formen (mit Ausnahmen wie dem Switch)
  • Hintergrundpfeile visualisieren den Brechungsbetrag (die Verschiebung) farblich nach Magnitude
  • Bei gleichem Abstand zur linken bzw. rechten Kante entsteht dieselbe Verschiebung, was effiziente Wiederverwendung ermöglicht

Ein Verschiebungsvektorfeld erzeugen

Über die gesamte Glasoberfläche wird ein Vektorfeld aufgebaut, das für jede Position Richtung und Stärke der Lichtverschiebung beschreibt.

  • Bei Kreisformen erfolgt die Verschiebung relativ zur Kante immer in Richtung der Normalen

Verschiebungsstärke vorab berechnen

  • Da die Verschiebungsstärke für jeden Abstand zur Kante symmetrisch ist, werden die Werte radial vorab berechnet und in einem Array gespeichert
  • In 2D wird nur einmal gerechnet (127 Strahlensimulationen), danach wird das gesamte Feld durch Rotation um die z-Achse erzeugt

Vektornormalisierung

Damit die Vektoren in einer Displacement-Map verwendet werden können, erfolgt eine Normalisierung (maximaler Maßstab 1.0).

  • Ausgehend vom größten Verschiebungswert werden die restlichen Vektormagnituden entsprechend geteilt
const maximumDisplacement = Math.max(...displacementMagnitudes);
displacementVector_normalized = {
  angle: normalAtBorder,
  magnitude: magnitude / maximumDisplacement,
};

In der SVG-Displacement-Map wird beim Umrechnen in echte Pixelwerte über scale wieder mit dem maximalen Verschiebungswert multipliziert, um die ursprüngliche Größe herzustellen.

SVG-Displacement-Map

Um die Ergebnisse der mathematischen Brechungsberechnung tatsächlich im Browser-Rendering anzuwenden, wird eine SVG-Displacement-Map verwendet.

  • Jeder Kanal (RGBA, 8 Bit) von <feDisplacementMap /> kann jeweils die Verschiebung auf der X- bzw. Y-Achse übernehmen
  • Jeder Kanal hat Werte von 0 bis 255, wobei 128 neutral ist (keine Verschiebung)
  • Die Displacement-Map muss unbedingt in ein Bild umgewandelt werden
<svg colorInterpolationFilters="sRGB">
  <filter id={id}>
    <feImage
      href={displacementMapDataUrl}
      x={0}
      y={0}
      width={width}
      height={height}
      result="displacement_map"
    />
    <feDisplacementMap
      in="SourceGraphic"
      in2="displacement_map"
      scale={scale}
      xChannelSelector="R"
      yChannelSelector="G"
    />
  </filter>
</svg>

Scale

Die Werte der roten (X) und grünen (Y) Kanäle werden auf den Bereich [−1, 1] abgebildet.

  • Über das Attribut scale wird dann mit der maximalen Verschiebung in Pixeln multipliziert, um das eigentliche Rendering umzusetzen
  • Durch Animation von scale lässt sich die Intensität des Effekts steuern

Umwandlung von Vektor → Rot/Grün-Werten

  • Der Verschiebungsvektor (Winkel, Magnitude) wird in kartesische x/y-Koordinaten umgerechnet und dann mit 128 als neutralem Mittelpunkt auf 0 bis 255 abgebildet
const x = Math.cos(angle) * magnitude;
const y = Math.sin(angle) * magnitude;
const result = {
  r: 128 + x * 127,
  g: 128 + y * 127,
  b: 128,
  a: 255,
};

Das fertige Bild kann anschließend als Displacement-Map für den SVG-Filter verwendet werden.

Playground

Im interaktiven Playground lassen sich Oberflächenform, Fasenstärke, Glasdicke, Effect Scale usw. in Echtzeit ändern, sodass Brechungsfeld, Displacement-Map und endgültiges Rendering direkt erlebbar sind.

Specular Highlight

Zum Schluss wird ein specular highlight hinzugefügt, also der helle Kanten-Highlight-Effekt der Glasoberfläche.

  • Apples Umsetzung arbeitet als Rim Light, bei dem die Helligkeitsintensität vom Winkel zwischen Oberflächennormale und Lichtquelle abhängt

Kombination von Brechung und Specular Highlight

Im finalen SVG-Filter werden Displacement-Map und Specular-Highlight jeweils über <feImage /> geladen und mit <feBlend /> zum Endeffekt kombiniert.

  • Über die Filterparameter lassen sich unterschiedliche visuelle Ergebnisse erzeugen

SVG-Filter als backdrop-filter verwenden

  • Um UI-Komponenten praktisch mit dem Liquid-Glass-Effekt zu versehen, ist die Chrome-Unterstützung für backdrop-filter: url(#...) nötig
  • Da die Bildgröße bei backdrop-filter nicht automatisch angepasst wird, muss eine zur Elementgröße passende Displacement-Map vorbereitet werden
.glass-panel {
  backdrop-filter: url(#liquidGlassFilterId);
}

Anwendung auf reale UI-Komponenten

Auf Basis der berechneten Brechung und der Displacement-Map werden Beispiele für den Einsatz in realistisch wirkenden UI-Komponenten umgesetzt.

  • Nur Chrome kann SVG-Filter per backdrop-filter verarbeiten
  • Die Beispiele sind keine echten Produktionskomponenten, sondern dienen dazu zu demonstrieren, wie sich der Liquid-Glass-Effekt auf unterschiedliche UIs anwenden lässt

Lupe

  • Auf beiden Seiten werden Brechung und Zoom sowie zwei Displacement-Maps verwendet
  • Schatten und Skalierungsanpassungen sorgen für einen interaktiven Effekt
  • Die Linse kann per Drag verformt werden, um den Brechungspfad zu beobachten
  • Ein weiches specular highlight kommt hinzu

Searchbox

  • Der Liquid-Glass-Effekt wird auf eine Standard-Eingabebox angewendet

Switch

  • Verwendet eine Lip-Fase, außen konvex und innen konkav
  • Nur der mittlere Slider ist vergrößert/verkleinert, während die Ränder das innere Bild brechen

Slider

  • Verwendet eine konvexe Fase; der aktuelle Wert bleibt durch das Glas sichtbar, während auf beiden Seiten Hintergrundbrechung angewendet wird

Music Player

  • Ahmt den Liquid-Glass-Panel-Stil von Apple Music nach

  • Konvexe Fase und ein dezentes specular highlight verleihen Tiefe

  • Nutzt die iTunes Search API, um Album-Art, Songtitel und weitere Informationen zu laden

  • (Bereitstellung von Songtiteln und Albuminformationen in Listenform)

Fazit

Dieser Prototyp vereinfacht Apples Liquid-Glass-Konzept zu einem Echtzeit-Brechungseffekt mit einfachen Highlights. Praktisch nutzbar ist er nur in Chromium-basierten Browsern (oder Electron); in anderen Browsern kann stattdessen eine Blur-Ebene eingesetzt werden.
Es handelt sich um eine experimentelle Implementierung, und die Neugenerierung der Displacement-Map bei jeder Änderung von Form oder Größe ist sehr ineffizient (animierbar sind nur einige Parameter wie scale des Filters).
Eine spätere Open-Source-Veröffentlichung wird geprüft; außerdem wird Interesse an Optimierung und Code-Bereinigung geäußert.

Noch keine Kommentare.

Noch keine Kommentare.