10. November 2010
Bei dieser Übung galt es eine Uhr neu zu gestalten. Anfangs habe ich mit Gradienten experimentiert und bin dann über Zwischenschritte bei sich umkreisenden Zeiteinheiten gelandet. Die 24 Stunden des Tages bilden den Hauptkreis und die Minuten kreisen um die Stunde, die Sekunden um die Minuten und die Millisekunden und die Sekunden. Abfragen- Stunde: hour()
- Minuten: minute()
- Sekunden: second()
- Millisekunden seit Programmstart: millis()
- Aktuelle Systemzeit: System.currentTimeMillis()
-
Ideengang
- Zuerst habe ich zwei Prototypen mit Gradienten erstellt. Die Idee dabei war, dass jede Zeiteinheit (Stunde/Minute/Sekunde) einen Helligkeitswert besitzt und sich der Hintergrund dem Wert der aktuellen Stunde anpasst, sodass sich ein Fadeout beim Abschnitt der aktuellen Stunde ergibt.
- Danach habe ich innerhalb der Stundenbalken noch einen vertikalen Gradienten für die Minuten eingeführt. Hierbei hat sich gezeigt, dass die Abstufungen des Verlaufes durch die 60 Abschnitte so fein werden, dass diese fast nicht mehr zu unterscheiden sind, was das Ablesen der Zeit erschwerte.
- Nach verschiedene Varianten mit 1 Verlauf über 24h, oder einem zunehmenden und abnehmenden Verlauf über diese Zeit, bin ich dann von den rechteckigen Abschnitten bei runden gelandet.
- Hier war mir dann das Ganze zu statisch, sprich die Helligkeitswerte wurden angepasst, aber nur wenig Animation konnte ich in diesem Konzept umsetzen.
- So habe ich die Zeiteinheiten neu zusammenzustellen versucht und bin dann beim finalen Konzept gelandet, bei die kleinere Zeiteinheit als Kreis um die grössere dreht.
xP = xM + r*cos(ß) yP = yM + r*sin(ß)
xP: x-Koordinate des Punktes yP: y-Koordinate des Punktes xM: x-Koordinate des Mittelpunktes yM: y-Koordinate des Mittelpunktes r: Radius des Kreises ß: Winkel
Meine entsprechende Processing-Funktion// get coords (x/y) of point on circle with given angle PVector getCoordsOnCircle(float xM, float yM, float radius, float angle) { PVector cP = new PVector(); cP.x = xM + radius*cos(radians(angle)); // xP = xM + r*cos(ß) cP.y = yM + radius*sin(radians(angle)); // yP = yM + r*sin(ß) return cP; }
Der gesamte Processing-Codeint colorIncrease = 60; // added to rgb from bg circle to millis circle int[] colorSelectedBase = {102,51,51}; // rgb for selected hour int[] colorDefaultBase = {51,51,102}; // rgb default color int scaleH = 3; int scaleM = 2; int radiusH = 300; // radius circle hours are placed on int radiusT = 200; // radius circle texts are placed on void setup() { size(800, 800); smooth(); // load font and set font size PFont font = loadFont("00Basix-48.vlw"); textFont(font, 24); } void draw() { background(224,224,255); noStroke(); // get milliseconds (system) // modulo 1000 used to get current int mi = int(System.currentTimeMillis()%1000); // Background Circles // I split up the background circles and the animated indexes (minutes, secondds) // in order to have the stacking order right. Animated indexes overlap neighbouring circles for(int i=0; i<24; i++) { int angleH = (360/24)*i-90;// minute()*6; PVector pH = getCoordsOnCircle(width/2, height/2, radiusH, angleH); pushStyle(); setFillColor(i, 0, false); ellipse(pH.x, pH.y, 24*scaleH, 24*scaleH); popStyle(); int angleT = angleH-1;// minute()*6; PVector pT = getCoordsOnCircle(width/2, height/2, radiusT, angleT); pushStyle(); // text label setFillColor(i, 0, false); text(i,pT.x,pT.y); popStyle(); } // Indexes Minutes / Seconds / Millis for(int i=0; i<24; i++) { int angleH = (360/24)*i-90;// minute()*6; PVector pH = getCoordsOnCircle(width/2, height/2, radiusH, angleH); // Minutes int radiusM = 24*scaleM; int angleM = (minute()*6)-90; PVector pM = getCoordsOnCircle(pH.x, pH.y, radiusM, angleM); pushStyle(); setStrokeColor(i, 0, false); setFillColor(i, 1, false); ellipse(pM.x, pM.y, 28*scaleM, 28*scaleM); popStyle(); // Seconds int radiusS = 8*scaleH; int angleS = (second()*6)-90; PVector pS = getCoordsOnCircle(pM.x, pM.y, radiusS, angleS); pushStyle(); setStrokeColor(i, 1, false); setFillColor(i, 2, false); ellipse(pS.x, pS.y, 12*scaleH, 12*scaleH); popStyle(); // Milliseconds int radiusMs = 6*scaleH; float angleMs = (360*(mi/1000.0)); PVector pMs = getCoordsOnCircle(pS.x, pS.y, radiusMs, angleMs); pushStyle(); setStrokeColor(i, 2, false); setFillColor(i, 3, true); ellipse(pMs.x, pMs.y, 24, 24); popStyle(); } } // get coords (x/y) of point on circle with given angle PVector getCoordsOnCircle(float xM, float yM, float radius, float angle) { PVector cP = new PVector(); cP.x = xM + radius*cos(radians(angle)); // xP = xM + r*cos(ß) cP.y = yM + radius*sin(radians(angle)); // yP = yM + r*sin(ß) return cP; } // set fill color (current hour highlighted) void setFillColor(int cHour, int depth, boolean special) { if (cHour==hour()) { if (special==true) { fill(255); } else { fill(colorSelectedBase[0]+(colorIncrease*depth), colorSelectedBase[1]+(colorIncrease*depth), colorSelectedBase[2]+(colorIncrease*depth)); } } else { fill(colorDefaultBase[0]+(colorIncrease*depth), colorDefaultBase[1]+(colorIncrease*depth), colorDefaultBase[2]+(colorIncrease*depth)); } } // set stroke color (current hour highlighted) void setStrokeColor(int cHour, int depth, boolean special) { if (cHour==hour()) { if (special==true) { stroke(255); } else { stroke(colorSelectedBase[0]+(colorIncrease*depth), colorSelectedBase[1]+(colorIncrease*depth), colorSelectedBase[2]+(colorIncrease*depth)); } } else { stroke(colorDefaultBase[0]+(colorIncrease*depth), colorDefaultBase[1]+(colorIncrease*depth), colorDefaultBase[2]+(colorIncrease*depth)); } }