Iris - Lamellenblende mit echter Mechanik

Klassisch, 8 Lamellen - atmet
Bild 16:9 - zum Drehen ziehen
ziehen · scrollen · Pfeiltasten
Bild 9:16 - Wirbel, gespiegelt
Die fünf Lamellenformen (je 9 Lamellen)
wirbel
rund
klassisch
flach
vieleck
Themes
standard
messing
hell
icon
icon, ohne Ring
Mechanik sichtbar
Drehpunkte unter dem Ring, Umriss einer Lamelle
Per JavaScript gesteuert

Iris ist eine SVG-Lamellenblende mit echter Mechanik: starre Lamellen, die sich um feste Drehpunkte unter dem Ring schwenken. Die Öffnung ist durchsichtig - dahinter liegt die Seite oder ein Bild. Konfiguration deklarativ über data-iris-* oder per JavaScript, Auto-Init beim DOM-ready inklusive.

iris.js JavaScript + CSS in einer Datei

Eine Datei

Es gibt kein separates Stylesheet. Beim ersten Einsatz setzt iris.js einmal ein kleines <style id="iris-tokens"> an den Anfang des <head>. Darin stehen ausschließlich Theme-Tokens (--iris-*) am Host .iris. Weil das Element ganz vorn steht, überschreibt jedes Seiten-CSS diese Tokens schon mit gleicher Spezifität.

Das gesamte Painting liegt gekapselt im Shadow Root jeder Instanz. Alle Instanzen teilen sich ein CSSStyleSheet-Objekt (adoptedStyleSheets); wo das nicht geht, greift automatisch ein <style>-Fallback. Seiten-CSS auf nackte Tags erreicht die Blende nicht.

Quick Start

<script src="iris.js" defer></script>

<div class="iris"
     data-iris-shape="klassisch"
     data-iris-blades="8"
     data-iris-open="60"></div>

Die Größe steuerst du über --iris-size (Standard 100% der Breite) oder einfach über die Breite des Elements; die Blende ist immer quadratisch.

<div class="iris" style="--iris-size: 240px" data-iris-animate="breathe"></div>

Mechanik

Jede Lamelle ist ein starres Blech - ein Kreis, aus dem der sogenannte Arbeitskreis ausgeschnitten ist - und schwenkt um einen festen Drehpunkt unter dem Ring. Aus der gewünschten Öffnung folgt der Schwenkwinkel über den Kosinussatz. Die Öffnung dreht sich dabei mit, wie bei einer echten Blende.

Jede Lamelle wird von ihren (bis zu) drei Nachfolgerinnen verdeckt. Diese Stapelung ist ringsum gleich - es gibt keine erste oder letzte Lamelle. Alle Formen sind für 3 bis 24 Lamellen durchgerechnet: in jeder Stellung ohne Lücke und mit genau einer obersten Lamelle an jedem Punkt.

Lamellenformen

Die Formen unterscheiden sich durch die Krümmung der Arbeitskante. Sie bestimmt die Öffnungsform und zugleich die Fugenlinien, denn die sichtbare Grenze zwischen zwei Lamellen ist die Fortsetzung der Arbeitskante der oberen.

WertCharakterKleinste Öffnung
wirbelstark geschwungene Fugen, fast runde Öffnung12 %
rundweiche, runde Öffnung5 %
klassisch (default)leicht gerundetes Vieleck0 % (schließt ganz)
flachsanfte Kanten0 %
vielecknahezu gerade Fugen, scharfes Vieleck0 %
Warum schließen Wirbel und Rund nicht ganz? Stark gekrümmte Lamellen würden beim völligen Schließen quer über die Mitte greifen. Dort läge dann ein ganzer Ring von Lamellen übereinander, von denen keine oben sein kann - das unmögliche Dreieck in echt. Echte Objektivblenden schließen aus demselben Grund nie ganz. Die Stellung open läuft trotzdem immer von 0 bis 100; 0 bedeutet die kleinste Öffnung der Form.

Data-Attribute

AttributWertBeschreibung
data-iris-shapewirbel | rund | klassisch | flach | vieleckLamellenform. Default klassisch.
data-iris-blades3 – 24Anzahl der Lamellen. Default 8.
data-iris-open0 – 100Stellung. 0 = kleinste Öffnung der Form, 100 = ganz offen. Default 60.
data-iris-mirrortrue | falseDrehsinn umkehren (exaktes Spiegelbild).
data-iris-thememessing | hell | iconVorgefertigtes Theme. Ohne Attribut: Stahl.
data-iris-edgeZahl, z.B. 3Stärke der Kantenlinien (viewBox-Einheiten, Blende = 1000). Ohne Angabe gilt --iris-edge-width aus dem CSS bzw. dem Theme.
data-iris-imageURLBild hinter der Öffnung, siehe unten.
data-iris-ringfalseFrontring ausblenden; der Ausschnitt wird dann enger.
data-iris-mechanismtrueDrehpunkte und Umriss einer Lamelle einblenden.
data-iris-interactivetrueBedienbar per Ziehen, Mausrad und Tastatur.
data-iris-animatebreatheÖffnet und schließt selbstständig.
data-iris-durationZahl (ms)Dauer eines Atemzugs. Default 4000.
data-iris-min / data-iris-max0 – 100Unter- und Obergrenze der Stellung beim Atmen.
data-iris-labelTextaria-label. Default Blende.

Bild hinter der Öffnung

Ein Bild wird immer passend eingesetzt: die kürzere Bildseite füllt die Öffnung, die längere wird mittig beschnitten - wie object-fit: cover. Ein Querformat verliert also links und rechts, ein Hochformat oben und unten.

<div class="iris" data-iris-image="landschaft.jpg"></div>

// oder zur Laufzeit
el._iris.setImage('landschaft.jpg');
el._iris.setImage(null);   // entfernen

Ohne Bild ist die Öffnung durchsichtig. Willst du dort eine Farbe, setze --iris-backdrop.

JavaScript-API

const iris = new Iris(element, {
  shape: 'rund',
  blades: 11,
  open: 40,
  interactive: true,
  onChange: (d) => console.log(d.open, d.diameter)
});

iris.setOpen(75);                 // sofort
await iris.animateTo(0, 800);     // weich, liefert ein Promise
iris.play();                      // atmen
iris.stop();
iris.update({ shape: 'vieleck', blades: 6, theme: 'messing' });
const svg = iris.toSVG();         // eigenständiges SVG als String
iris.destroy();

// Alle .iris-Elemente nachträglich initialisieren (idempotent):
Iris.init();

// Optional: jQuery-Bridge
$('.iris').iris({ blades: 12 });

Die Optionen heißen wie die Data-Attribute ohne Präfix (shape, blades, open, mirror, theme, edge, image, ring, mechanism, interactive, animate, duration, min, max, label) plus onChange. Übergebene Optionen haben Vorrang vor den Attributen. Die Instanz hängt als element._iris am Element. Ein zweites new Iris(element, options) liefert dieselbe Instanz und wendet die Optionen per update() an.

Methoden

MethodeBeschreibung
setOpen(v)Stellung 0 – 100 sofort setzen. Hält ein laufendes Atmen an.
animateTo(v, ms?)Weich zur Stellung, Default 600 ms. Liefert ein Promise (true = angekommen, false = unterbrochen).
play() / stop() / toggle()Atmen starten, anhalten, umschalten. Der Atemzug schließt nahtlos an die aktuelle Stellung an.
update(options)Beliebige Optionen ändern und neu zeichnen. Enthält options ein open, werden Atmen und ein laufendes animateTo() beendet.
setShape(), setBlades(), setMirror(), setTheme(), setImage(), setMechanism()Kurzformen für update().
toSVG()Eigenständiges SVG mit aufgelösten Farben. Bilder werden per URL referenziert, nur data:-URLs sind eingebettet.
destroy()Stoppt Animationen, löst Listener, leert den Shadow Root, entfernt _iris. Attribute, Klasse und --iris-edge-width am Element erhalten wieder ihren Zustand von vor der Initialisierung.
Iris.init(selector?)Statisch. Initialisiert alle passenden Elemente, Default .iris. Idempotent.

Eigenschaften

EigenschaftBeschreibung
openAktuelle Stellung 0 – 100.
diameterTatsächlicher Durchmesser der Öffnung in % der größten Öffnung (berücksichtigt die kleinste Öffnung der Form).
minDiameterKleinste Öffnung der aktuellen Form in %.
isPlayingTruthy, solange geatmet wird.
optionsKopie der aktuellen Optionen.
Iris.shapes, Iris.themes, Iris.versionStatisch. Listen für eigene Bedienoberflächen.

Event

Bei jeder Änderung der Stellung feuert am Element iris:change (bubbelt). event.detail enthält open, diameter, blades, shape und source - user, api, animation oder breathe.

el.addEventListener('iris:change', e => {
  if (e.detail.source === 'user') label.textContent = e.detail.diameter + ' %';
});

Bedienung

Mit data-iris-interactive="true" wird die Blende zu einem Regler (role="slider"):

Themes

Drei vorgefertigte Themes via data-iris-theme, dazu der Standard ohne Attribut (Stahl mit Messing-Akzent):

Eigene Themes per CSS-Variablen

.iris.mein-theme {
  --iris-blade:      #2d3b4a;   /* Grundfarbe der Lamellen */
  --iris-edge:       #9fc2e0;   /* Kantenlinien */
  --iris-edge-width: 3;         /* Linienstärke, Blende = 1000 Einheiten */
  --iris-shade:      0.7;       /* Stärke der Lichtschattierung, 0 = flach */
  --iris-ring-1:     #8aa3bb;   /* Ringverlauf, hell ... */
  --iris-ring-2:     #55697d;
  --iris-ring-3:     #2a3642;
  --iris-ring-4:     #4b5c6d;   /* ... dunkel */
  --iris-ring-line:  #10161c;   /* Ringkanten */
  --iris-ring-line-width: 3;    /* Linie zwischen Ring und Lamellen */
  --iris-ring-outer: #10161c;   /* äußere Ringkante, Default = --iris-ring-line */
  --iris-tick:       #a9c0d6;   /* Rändelung */
  --iris-backdrop:   transparent; /* Füllung der Öffnung ohne Bild */
  --iris-mech:       #e8b964;   /* Mechanik-Ansicht */
  --iris-focus:      #e8b964;   /* Fokusring */
}

Da das Painting gekapselt ist, ist das der einzige Weg zum Theming. CSS auf interne Klassen im Shadow Root wirkt nicht. toSVG() übernimmt die gerade gültigen Token-Werte in das exportierte SVG.

Hinweise

Verhalten
Theme
Bild hinter der Öffnung
Die kürzere Bildseite füllt die Öffnung, die längere wird mittig beschnitten.
Einbettung