Dokumentation (canvas.quaese.de)
 

Anwendungen - Analog-Uhr

Ein Standardbeispiel für Anwendungen mit dem <canvas>-Element ist sicherlich die Analog-Uhr, da hier das Auflösen der eckigen und rechtwickligen Strukturen deutlich wird. Das Beispiel zeigt aber auch, wie Animationen mit dem neuen Element möglich werden.

Demonstration

Demonstriert wird das Beispiel an einer analogen Uhr im Bahnhofstil.

Ihr Browser unterstützt das CANVAS-Element leider nicht!

Internet Explorer

Da für den Quellcode lediglich Funktionen verwendet werden, die durch die Erweiterung ExplorerCanvas bereitgestellt und unterstützt werden, laufen die Scripts/Beispiele auch im IE.

Grafik

Grundlage der vorgestellten Beispiele ist eine Grafik, die das Ziffernblatt darstellt. Vorstellbar wäre auch ein Konstruieren und Zeichnen mit den Funktionen und Methoden des <canvas>-Elements. Aus Performanzgründen wird jedoch darauf verzichtet.

Die Grafik wird einem image-Objekt zugewiesen, wobei sie für moderne Browser im PNG-Format, für sonstige Anzeigegeräte im GIF-Format vorliegt.

Zum Deklarieren des Image-Objekts und dem korrekten Zuweisen der Quelle (src) kann folgendes Konstrukt verwendet werden.

var objImg = new Image();
// Falls es sich um einen IE vor Version 7 handelt
if(/MSIE/.test(navigator.userAgent) && !window.opera && (Number(navigator.userAgent.split(";")[1].substr(navigator.userAgent.split(";")[1].search(/\d/))) < 7)){
  objImg.src = "ziffernblatt.gif";
}else{
  objImg.src = "ziffernblatt.png";
}

Quellcode

Als nächstes wird der Quellcode vorgestellt, mit dem die Uhr animiert wird. Als Grundlage dienen hierfür neben den Methoden und Eigenschaften des <canvas>-Elements das JavaScript-Objekt Date sowie zum periodischen Aufrufen der Anzeigefunktion die Methode setTimeout des Objekts window.

function AnalogClock(objCanvas){
  // Neues Datumsobjekt
  var objDate = new Date();
  var intSek = objDate.getSeconds();     // Sekunden 0..59
  var intMin = objDate.getMinutes();     // Minuten 0..59
  var intHours = objDate.getHours()%12;  // Stunden 0..11
  // Kontext-Objekt
  var objContext = objCanvas.getContext("2d");

  objContext.clearRect(0, 0, 150, 150);  // Anzeigebereich leeren
  objContext.drawImage(objImg, 0, 0);    // Ziffernblatt zeichnen

  objContext.save();                     // Ausgangszustand speichern
  objContext.translate(75, 75);          // Koordinatensystem in Mittelpkt des Ziffernblatts verschieben

  // Stunden
  objContext.save();
  // Aktuelle Stunde zzgl. Minutenanteil über Drehung des Koordinatensystems
  // (kontinuierlicher Übergang zwischen zwei Stunden gewünscht, keine Sprung)
  objContext.rotate(intHours*Math.PI/6+intMin*Math.PI/360);
  objContext.beginPath();                // Neuen Pfad anlegen
  objContext.moveTo(0, 10);              // Zeiger über Mitte hinaus zeichnen
  objContext.lineTo(0, -38);             // Stundenzeiger im gedrehten Koord-Sys. um 38 Einheiten nach oben zeichnen
  // Linienstyle festlegen und zeichnen
  objContext.lineWidth = 4;
  objContext.strokeStyle = "#666";
  objContext.stroke();
  objContext.restore();

  // Minuten
  objContext.save();
  objContext.rotate(intMin*Math.PI/30);
  objContext.beginPath();
  objContext.moveTo(0, 10);
  objContext.lineTo(0, -50);
  objContext.lineWidth = 4;
  objContext.strokeStyle = "#666";
  objContext.stroke();
  objContext.restore();

  // Sekunden
  objContext.save();
  objContext.rotate(intSek*Math.PI/30);
  objContext.beginPath();
  objContext.moveTo(0, 10);
  objContext.lineTo(0, -50);
  objContext.lineWidth = 2;
  objContext.strokeStyle = "#a00";
  objContext.stroke();
  objContext.restore();

  objContext.restore();

  hTimer = window.setTimeout(function(){ AnalogClock(objCanvas);}, 1000);
}

Zu Beginn wird ein Date-Objekt erstellt. Davon ausgehend werden die Sekunden, Minuten und Stunden ermittelt. Da die analoge Uhr nur 12 Stunden darstellen kann, wird vom 24-Stundenwert durch eine Modulo-Operation (%) lediglich Werte von 0 bis 11 errechnet.

Nachdem das Kontext-Objekt generiert wurde, werden mit der Methode clearRect zunächst die Inhalte des <canvas>-Elements gelöscht. Anschliessend wird das Ziffernblatt eingebunden (drawImage), der Canvas-Zustand gesichert (save) und der Ursprung in den Mittelpunkt des Ziffernblatts verschoben (translate). Das Sichern erfolgt, um am Ende der Routine wieder den "Ausgangszustand" herstellen zu können.

Jetzt erfolgt die Darstellung der Zeitkomponenten, wobei mit der Anzeige der Stunden begonnen wird. Da zum Zeichnen des Stundenzeigers das Koordinatensystem gedreht wird, wird der Zustand erneut gespeichert.
Um die Stunden anzeigen zu können, wird der Vollkreis (2*PI) zunächst in 12 Teile zerlegt (PI/6). Die Multiplikation mit der aktuellen Stunde gibt den Winkel α im Bogenmass, um zur gesuchten Stunden zu gelangen.
Da ein Springen des Zeigers beim Erreichen einer vollen Stunde nicht gewünscht ist, soll ein kontinuierliches Vorrücken umgesetzt werden. Das wird realisiert, indem der Zeiger minutenweise um den entsprechenden Anteil weitergedreht wird. Hierfür wird der Bereich, den der Stundenzeiger in einer Stunde überstreicht (PI/6) in 60 Teile zerlegt (PI/360). Die Multiplikation mit der aktuellen Minute ergibt den Winkel β, der zu α addiert wird.
Jetzt kann das Koordinatensystem mit der Methode rotate um den gerade errechneten Winkel gedreht werden. Zum Abschluss der Stundendarstellung wird noch der Zeiger in negative y-Richtung (= nach oben) eingezeichnet.

Die Vorgehensweisen bei den Darstellungen von Minuten und Sekunden erfolgen in identischer Weise. Lediglich die Drehwinkel unterscheiden sich, da der Vollkreis in beiden Fällen in 60 Teile unterteilt werden muss (PI/30).
Zudem werden die Zeiger in unterschiedlicher Länge, Farbe und Stärke dargestellt. Dies dient aber nur der Unterscheidbarkeit, greift jedoch nicht in die Funktionalität ein.

Variationen

Variation 1

In der ersten Variation werden die Sekunden abwechselnd als zunehmender bzw. abnehmender Kreisausschnitt dargestellt.

Ihr Browser unterstützt das CANVAS-Element leider nicht!

Nachstehend ohne weitere Beschreibung die Sequenz des Quellcodes, der für die Darstellung der Sekunden verantwortlich ist. Die entscheidenden Stellen wurden kommentiert.

objContext.save();
var intSek = objDate.getSeconds();
objContext.rotate(3*Math.PI/2);
objContext.beginPath();
objContext.moveTo(0, 0);

// Falls eine Minute voll ist
if(intSek == 0)
  intCheck *= -1;

// Falls ein zunehmender Kreisausschnitt dargestellt werden soll
if(intCheck>0)
  // Kreisausschnitt von 0° bis aktuelle Sekunde
  objContext.arc(0, 0, 50, 0, intSek*Math.PI/30, false);
// Falls ein abnehmender Kreisausschnitt dargestellt werden soll
else
  // Kreisausschnitt von aktueller Sekunde bis 360°
  objContext.arc(0, 0, 50, intSek*Math.PI/30, 2*Math.PI, false);

objContext.closePath();
objContext.fillStyle = "rgba(0, 33, 191, 0.5)";
objContext.fill();
objContext.restore();

Variante 2

In der zweiten Variante ist die Laufrichtung der Uhr umgekehrt. D.h. die Zeiger bewegen sich links herum. Um das zu realisieren, müssen nur die negativen Winkel den rotate-Methoden übergeben werden.

Ihr Browser unterstützt das CANVAS-Element leider nicht!

 
Dokument zuletzt modifiziert: 13.11.2009, 16:06 Uhr
<canvas>-Dokumentation Ver. 0.1 | Quaese, Jan 2008 | Datenschutz | Sitemap