Alte Uhr mit CSS3 und jQuery

Avatar of Toby Pitman
Toby Pitman am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Hallo zusammen, mein Name ist Toby Pitman und Chris hat mich gebeten, einen Beitrag über ein aktuelles Experiment zu schreiben, das ich vor einiger Zeit im Forum veröffentlicht habe. Alles begann, als ich mir das WebKit-Blog ansah und einen Artikel über die neuen CSS3-Animationen sah. Was mir ins Auge stach, war „rotate“. Ich begann darüber nachzudenken, was man denn überhaupt auf einer Webseite drehen kann (das ist wie animierte GIFs mal zehn!). Dann traf es mich – die Zeiger einer Uhr drehen sich! Bingo!

CSS3 transform: rotate

transform: rotate; ist eine neue Funktion von CSS 3, mit der man Dinge drehen kann. Transform erlaubt auch das Skalieren, Verzerren und Verschieben (translating) von Objekten auf Ihrer Webseite. All dies kann mit der Transition-Eigenschaft animiert werden (komplett mit Timing-Funktion und Dauer).

Klingt bekannt? Das sollte es auch, denn es ist dasselbe, was wir derzeit mit Frameworks wie jQuery verwenden, um Elemente auf unseren Webseiten zu animieren. Ähnlich wie bei jQuery kann man praktisch jede nennenswerte CSS-Eigenschaft mit Transition animieren. Denken Sie an einen :hover-Effekt, und Sie sollten einige Ideen bekommen. Es ist bei weitem nicht so mächtig wie jQuery oder Mootools usw., aber es kann immer noch einige coole Dinge tun. Ich bezweifle, dass John Resig schlaflose Nächte haben wird!

WICHTIGER HINWEIS: Diese Demo funktioniert nur in Firefox 3.1+ und Safari 3+ (und anderen modernen WebKit-basierten Browsern wie Chrome).

Und nein, das wird in IE6 niemals funktionieren! Okay, legen wir los!

Demo ansehen Dateien herunterladen

Die Grafiken

Zuerst benötigen wir einige Grafiken für unser Uhr-Interface. Wir haben ein Zifferblatt und drei Zeiger. Alle beweglichen Teile sind in Photoshop auf 600 Pixel Höhe und 30 Pixel Breite geschnitten und vertikal mittig positioniert, da die rotate-Eigenschaft standardmäßig vom Mittelpunkt des Elements aus dreht. Sie können 'transform-origin' verwenden, um einen Drehpunkt festzulegen, wenn Sie möchten.

Ich habe mich hier für eine generische Uhr entschieden, aber es hindert Sie nichts daran, sich für eine Micky-Maus-Uhr zu entscheiden, wenn Sie möchten. Die beweglichen Teile sind alle PNG-Bilder, was diesen Effekt ermöglicht.

Das HTML-Markup

Die Markup für die Uhr ist eine einfache ungeordnete Liste. Jedes Listenelement enthält einen beweglichen Teil und erhält eine entsprechende ID. Hier ist sie.

<ul id="clock">	
  <li id="sec"></li>
  <li id="hour"></li>
  <li id="min"></li>
</ul>

HINWEIS: Der Forenbeitrag hatte ein etwas umständlicheres Markup, da er realistische Schatten auf den Zeigern hatte. Ich habe einige der Codes für diese Demo verfeinert und der Forenbeitrag wurde so belassen, wie er ist.

Das CSS

#clock {
  position: relative;
  width: 600px;
  height: 600px;
  margin: 20px auto 0 auto;
  background: url(clockface.jpg);
  list-style: none;
}

#sec, #min, #hour {
  position: absolute;
  width: 30px;
  height: 600px;
  top: 0px;
  left: 285px;
}

#sec {
  background: url(sechand.png);
  z-index: 3;
}
   
#min {
  background: url(minhand.png);
  z-index: 2;
}
   
#hour {
  background: url(hourhand.png);
  z-index: 1;
}

Auch das CSS ist wirklich einfach. Da die beweglichen Teile die gleichen Abmessungen und Startpositionen haben, können wir diese zusammen deklarieren, um Wiederholungen zu vermeiden und das CSS etwas schlanker zu gestalten. Die <ul> erhält eine relative Positionierung, die es uns ermöglicht, die Uhrzeiger darin absolut zu positionieren.

HINWEIS: Rotate beeinflusst das Layout nicht, und das Objekt verhält sich beim Rotieren wie ein absolut positioniertes Element außerhalb des normalen Flusses.

Wo ist also das CSS3-Zeug? Nun, das werden wir mit etwas einfachem jQuery anwenden.

Das jQuery JavaScript

  1. Holen Sie sich die Zeitinformationen für die Uhr.
  2. Berechnen und injizieren Sie den CSS-Stil (Rotationswinkel) für jedes Element.
  3. Aktualisieren Sie die CSS-Stilinformationen in regelmäßigen Abständen.

Es sollte beachtet werden, dass jQuery keinerlei Probleme mit der Verwendung dieser neuen CSS3-Eigenschaften hat. Da die Stile dynamisch und nicht aus der Stylesheet zugewiesen werden, validiert diese Uhr immer noch als CSS2.1!

Die Zeit abrufen

Einige von Ihnen mögen (na ja, ich schon!) Datums- und Zeitinformationen mit PHP gleichsetzen, und als ich damit anfing, war PHP mein erster Gedanke, aber dann entdeckte ich, dass JavaScript auch seine eigene integrierte Funktionalität zum Abrufen von Datums- und Zeitdaten hat. Beachten Sie, dass die Zeit bei JavaScript lokal auf dem Rechner ist und nicht auf dem Server.

Wir werden diese Informationen mit der Date()-Syntax abrufen und sie einer Variablen zuweisen. Wir können die spezifischen Daten jedes Zeigers abrufen, indem wir GetSeconds(), GetMinutes() oder GetHours() an die Date()-Syntax anhängen, wie in diesem Beispiel.

var seconds = new Date().getSeconds();

Der obige Code gibt eine Zahl zwischen 0 und 59 zurück und speichert sie in der Variablen 'seconds'.

Den Winkel abrufen

Als Nächstes müssen wir den Winkel für jeden Zeiger berechnen. Bei Sekunden und Minuten, die 60 Inkremente pro Umdrehung haben, teilen wir einfach 360 durch 60, was 6 ergibt. Das bedeutet, dass wir den Zeiger für jede Sekunde oder Minute um 6 Grad drehen müssen. Wir werden diese Gleichung in einer weiteren Variablen speichern. Für die Sekunden sieht das so aus.

var sdegree = seconds * 6;

Der Stundenzeiger wirft ein anderes Szenario auf. Da es 12 Inkremente pro Umdrehung gibt, beträgt der Winkel für jede Stunde 30 Grad. Das sind 360/12=30. Das wäre einfach, wenn sich der Stundenzeiger einer Uhr in Stundeninkrementen bewegen würde, aber das tut er nicht. Er bewegt sich in kleineren Beträgen, basierend auf dem Minutenwert. Sagen wir um 4:30 Uhr, der Stundenzeiger wird sich auf halbem Weg zwischen 3 und 4 befinden. Wie machen wir das also? Hier ist der Code.

var hdegree = hours * 30 + (mins / 2);

Grundsätzlich addieren wir die aktuelle Anzahl der Minuten geteilt durch zwei, was uns eine Zahl zwischen 0,5 und 29,5 ergeben sollte ('rotate' kann alle Gleitkommazahlen verarbeiten) – das platziert den Zeiger irgendwo zwischen einem gegebenen 30-Grad- (Stunden-) Inkrement.

Beispiel

2.40 wäre   2 * 30 = 60 Grad
  + 40 / 2 = 20 Grad
    ——— ———-
    hdegree = 80 Grad

Ich dachte, die Uhr könnte explodieren, wenn sie über 12 hinausgeht, da es eine Zahl größer als 360 wäre, aber es hat gut funktioniert.

Nachdem wir nun die Mathematik geklärt haben, injizieren wir das neue CSS.

Stil setzen

Hier ist das CSS3-Rotate, als ob es in einer Stylesheet wäre.

#sec {
   -webkit-transform: rotate(45deg);
   -moz-transform: rotate(45deg);
   -ms-transform: rotate(45deg);
   -o-transform: rotate(45deg);
   transform: rotate(45deg);
}

Hier wird es von jQuery injiziert (HINWEIS: Ab jQuery 1.8 werden die korrekten Vendor-Präfixe bei der Verwendung der .css()-Funktion angewendet. Ältere Versionen von jQuery müssen diese manuell anwenden).

$("#sec").css({
  "transform": "rotate(45deg)"
});

Das Problem, das wir hier haben, ist, die Variable 'sdegree' (die unseren Winkel enthält) in diese Syntax einzufügen, um die (45deg) zu ersetzen. Zuerst habe ich versucht, die Variable zwischen die Klammern zu setzen, aber es hat nicht funktioniert. Um dies zu ermöglichen, müssen wir einen 'String' in einer anderen Variablen namens 'srotate' erstellen und das zweite Argument vollständig ersetzen. So machen wir es.

var srotate = "rotate(" + sdegree + "deg)";

Das jQuery wird nun so geschrieben:

$("#sec").css({ "transform": srotate });

Alles zusammenfügen (pünktlich!)

Der gesamte jQuery-Code sieht so aus.

$(function() {
 
      setInterval( function() {
      var seconds = new Date().getSeconds();
      var sdegree = seconds * 6;
      var srotate = "rotate(" + sdegree + "deg)";
      
      $("#sec").css({ "transform": srotate });
          
      }, 1000 );
      
      setInterval( function() {
      var hours = new Date().getHours();
      var mins = new Date().getMinutes();
      var hdegree = hours * 30 + (mins / 2);
      var hrotate = "rotate(" + hdegree + "deg)";
      
      $("#hour").css({ "transform": hrotate});
          
      }, 1000 );

      setInterval( function() {
      var mins = new Date().getMinutes();
      var mdegree = mins * 6;
      var mrotate = "rotate(" + mdegree + "deg)";
      
      $("#min").css({ "transform" : mrotate });
          
      }, 1000 );
 
});

Beachten Sie, wie wir ein JavaScript-setInterval verwendet haben, damit die Funktion jede Sekunde ausgeführt wird. Die Variablen, die die Zeitdaten abrufen, müssen sich innerhalb der Funktion befinden, damit sie sich ebenfalls aktualisieren. Wenn nicht, würden sie die Daten nur einmal beim Laden der Seite abrufen, was eine ziemlich schlechte Uhr wäre.

Unsere Uhr sollte nun funktionieren (in Safari und anderen modernen Browsern).

Alternativen

Flash ist die offensichtliche Wahl, aber es sei denn, Sie haben ActionScript-Talent, würde ich es meiden. Dies ist vielleicht sogar mit PHP unter Verwendung der GD-Bildbibliothek möglich, um die Zeiger zu drehen, aber das übersteigt mein Niveau bei weitem.

Übrigens, Soh Tanaka hat dies ein paar Tage später fast zufällig veröffentlicht: CSS-Uhr. Seine Uhr verwendet JavaScript, um Klassen und Sprite-Bilder für die Zeiger hinzuzufügen.

UPDATE Nov 2012: Daniel Bakan hat einen sehr ähnlichen Artikel „How To Write a Full Screen Web App Optimized For iOS Devices“, in dem er ebenfalls eine altmodische Uhr baut. Wenn Sie sich dafür sehr interessieren, ist das auch einen Blick wert.

Fazit

Da haben Sie es, Leute, ein wirklicher und (wahrscheinlich der einzige) praktischer Anwendungsfall für die neue CSS3-Eigenschaft transform:rotate. Ich persönlich kann es kaum erwarten, umgedrehte und seitliche Webseiten zu sehen (Ja, Sie können sogar das HTML-Tag drehen! Obwohl schauen Sie, was das mit Safari macht) und meine persönlichen Favoriten sind die rotierenden/zoomenden Cartoon-Zeitung-Blogbeiträge.

Also los, probieren Sie einige dieser neuen CSS3-Funktionen aus!