Δύο ενδύματα — χρυσό κι ασήμι
Το θέμα διανέμεται σε όλες τις όψεις μέσω του Environment κι αλλάζει ακαριαία. Ως και το ύφος του καντράν, των δεικτών και των αριθμών πλάθεται ξεχωριστά για κάθε ένδυμα.
Χρυσό — ρολόι κυνηγού
Σμάλτο σε βαθύ λαζουρί × χρυσοί ρωμαϊκοί αριθμοί (γραφή IIII) · κεντρικό έμβλημα με μισοφέγγαρο κι οκτάκτινο άστρο
Χαραγμένη θήκη από παλιό χρυσό (γερασμένος ορείχαλκος). Στη θέση των 6 η ώρα, ένα παραθυράκι της επόμενης ορισμένης ώρας
#8F7028
Λαζουρί #101838
Χρύσωμα #D9B45C
Σεληνόχρυσο #F2DC96
tint #A67C2E
Ασήμι — σιδηροδρομικό ρολόι
Λευκό καντράν · χοντροί αραβικοί αριθμοί · δείκτες-ράβδοι
Ο δείκτης δευτερολέπτων, κατά το έθιμο των σιδηροδρομικών ρολογιών, μπαίνει κόκκινος
#9CA3AE
Λευκή πορσελάνη #FAFAF7
Σιδερένιο μαύρο #1A1C22
Κόκκινο #B02E2E
tint #44546A
Ρύθμισε την ώρα με τους δείκτες
Δεν χρησιμοποιείται DatePicker. Αντί για την κίνηση του κουρδίσματος της κορώνας, ορίζεις την ώρα του ήχου σύροντας τους ίδιους τους δείκτες του καντράν. Το καντράν παρακάτω σύρεται στ' αλήθεια.
π.μ.7:30
- Μετατροπή γωνίας → ώρας — οι συντεταγμένες του συρσίματος μετατρέπονται σε γωνία με atan2, κι ο λεπτοδείκτης κβαντίζεται ανά 6°, ο ωροδείκτης ανά 30° (ως καθαρή συνάρτηση
ClockAngleMathυπό δοκιμή). - Σύνδεση — όταν στρίβεις τον λεπτοδείκτη, ο ωροδείκτης ακολουθεί με 0.5°/λεπτό. Περνώντας το 0 λεπτό, η ώρα προχωρά/γυρίζει πίσω (κρίνεται από το πέρασμα 45→15 λεπτών).
- Απτική ανάδραση — σε κάθε βήμα του 1 λεπτού, .sensoryFeedback(.selection). Επιστρέφει στο δάχτυλο την αίσθηση του κλικ του γραναζιού.
- Ο επιλεγμένος δείκτης — στην άκρη του δείκτη εμφανίζεται ένας δακτύλιος σε χρώμα ορείχαλκου (πόμολο), δείχνοντας ποιον χειρίζεσαι.
- Επιβεβαίωση — αποθηκεύεις με την πλάκα «Ρύθμισε σ' αυτή την ώρα». Μετατρέπεται σε Alarm.Schedule.relative του AlarmKit.
Η θολούρα της ώρας — το σκοτάδι της νύχτας κι η αυγή
Όσο βαθαίνει η νύχτα, τόσο το καντράν θολώνει βαθυπόρφυρο, σαν δοχείο ψυχής. Την ώρα της αυγής, η θολούρα εξαγνίζεται με το φως. Την ώρα της δύσης, ο αστερισμός εκείνης της εποχής προβάλλει και λάμπει στο καντράν. Σύρετε τον ολισθητήρα παρακάτω για να διατρέξετε ολόκληρη τη μέρα.
21:00Σούρουπο
- Θολούρα — από τις 16 ως το σούρουπο, μια βαθυπόρφυρη θολούρα γεμίζει από την άκρη του καντράν, φτάνοντας στο μέγιστο από τις 23 ως τις 4 τα ξημερώματα. Με μια πολυεπίπεδη διαβάθμιση σε πολλαπλασιαστικό μείγμα, το χρώμα του ελεφαντόδοντου βυθίζεται σαν στον «πάτο του δοχείου».
- Ο εξαγνισμός της αυγής — από τις 4 ως τις 6 το πρωί, το φως από ψηλά (σύνθεση screen) διαλύει τη θολούρα. Το ρολόι-ήρωας ζει διαρκώς αυτόν τον κύκλο, συγχρονισμένο με την πραγματική ώρα.
- Ο αστερισμός της εποχής — στη δύση (±2 ώρες) ο αστερισμός εκείνης της εποχής προβάλλει χρυσός. Άνοιξη = Λέων / καλοκαίρι = Σκορπιός / φθινόπωρο = Κασσιόπη / χειμώνας = Ωρίων. Τη νύχτα απομένει ως αχνό φως.
- Υλοποίηση σε SwiftUI — ο συντελεστής ώρας υπολογίζεται με
TimelineView(.everyMinute)κι αποτυπώνεται στη σχεδίαση πολλαπλασιασμού/screen του Canvas και στη διαφάνεια της διαδρομής του αστερισμού.
Το καπάκι των δώδεκα οίκων — το έμβλημα του αστερισμού που αλλάζει κάθε μήνα
Στο κέντρο του καπακιού είναι ένθετο σμάλτο σε βαθύ λαζουρί, και με κάθε αλλαγή του μήνα ο οίκος (αστερισμός) εκείνου του μήνα χαράζεται ξανά με χρυσό — μαζί μ' ένα μισοφέγγαρο και το παραδοσιακό ιαπωνικό όνομα του μήνα. Το καπάκι του ρολογιού-ήρωα φορεί το έμβλημα του τωρινού μήνα.
Οι αστερισμοί που περιστρέφονται — · τ' άστρα έχουν βάθος και περιστρέφονται ασταμάτητα στο διάστημα. Χάιδεψε και στρίψε, κι αποκτούν αδράνεια
Ο τόνος του σχεδίου μιμείται τα αντίκα ρολόγια τσέπης σε ύφος «λαζουρί σμάλτο × παλιό χρυσό» (υλικό αναφοράς: design-refs/ref-watch.jpg). Οι γραμμές των αστερισμών είναι μια στιλιζαρισμένη, απλουστευμένη μορφή. Στο SwiftUI, το έμβλημα που αλλάζει κάθε μήνα επιλέγεται με Calendar.current.component(.month) και σχεδιάζεται με χρύσωμα στο Canvas.
Άρκανα — το μυστήριο των δώδεκα οίκων
Χάιδεψε το καντράν κυκλικά και κούρδισέ το δώδεκα στροφές, και φανερώνεται το ξόρκι. Τη νύχτα τα Άρκανα (12 είδη των δώδεκα οίκων), την ημέρα οι Ηλιακές Τέχνες (6 είδη), με κλειστό το καπάκι οι Σφραγίδες (6 είδη) — στην πραγματική συσκευή, 24 είδη τριών συστημάτων. Η επίδειξη αυτής της σελίδας σου επιτρέπει να δοκιμάσεις επτά αντιπροσωπευτικά απ' αυτά.
Η μαγεία με ανοιχτό το καπάκι
Η μαγεία με κλειστό το καπάκι (στη συσκευή, η Σφραγίδα)
Η ώρα του ήχου (όταν ενεργοποιείται η καμπάνα-κήρυκας)
Μόλις φτάσει η ορισμένη ώρα, ολόκληρη η οθόνη αναβοσβήνει χρυσή, κι ανοίγει ο μαγικός κύκλος με τη σφραγίδα «Η ορισμένη ώρα έφτασε».
- Ανίχνευση κουρδίσματος — παρακολουθείται η σωρευτική γωνία περιστροφής γύρω από το κέντρο του καντράν, και κάθε 2π μετριέται μία στροφή. Ανάβει ο ρόμβος του μαγικού κύκλου. Αν το αφήσεις 4 δευτερόλεπτα, το κούρδισμα σκορπίζεται.
- Ο Εξαγνισμός του Φωτός της Αυγής — Εξαγνίζει τη θολούρα με φως. Το καντράν μεταβαίνει αναγκαστικά στην κατάσταση της αυγής, και μια χρυσή έκρηξη διατρέχει τον χώρο.
- Η Καταιγίδα των Αστερισμών — Ο αστερισμός της εποχής φουντώνει στις φλόγες, και τ' άστρα σκορπίζονται από το ρολόι.
- Η Αναστροφή του Χρόνου — Οι δείκτες γυρίζουν ολοταχώς προς τα πίσω, κι ο μαγικός κύκλος περιστρέφεται αντίστροφα.
- Το Φράγμα του Πορφυρού Κεραυνού — Βαθυπόρφυρη λάμψη και κραδασμός. Ο μαγικός κύκλος μεταβάλλεται σε πορφυρό.
- Η Πυρφόρα Φλόγα — Από ολόγυρα το ρολόι, σπίθες υψώνονται μέσα στον χώρο 3D (σωματίδια σε προοπτική προβολή, με τρεμούλιασμα).
- Η Δίνη των Γαλάζιων Κυμάτων — Στα πόδια σου απλώνονται ρυτιδώσεις, κι οι σταγόνες χαράζουν τόξο, τραβηγμένες απ' τη βαρύτητα.
- Ο Δακτύλιος του Ανεμοστρόβιλου — Ρεύματα ανέμου περιτριγυρίζουν το ρολόι, τυλίγοντάς το μπρος και πίσω, κι η πίεση του αέρα το ταλαντεύει.
- Υλοποίηση σε SwiftUI — η ανίχνευση περιστροφής βασίζεται στη σώρευση του
atan2(προστέθηκε στο ClockAngleMath), η μαγεία ενοποιείται στο πρωτόκολλοSpellEffect, κι οι ρυθμίσεις των θυρίδων αποθηκεύονται στο UserDefaults. Την ώρα του ήχου, ανιχνεύεται η κατάσταση alerting του AlarmKit, και με fullScreenCover ξεσπά το μεγάλο ξύπνημα.
Διάταξη οθονών
Η αρχική είναι πάντα το ρολόι. Ο κατάλογος, η επεξεργασία κι ο χρονομετρητής στήνονται σαν εργασιακή επιφάνεια στο πίσω μέρος του καπακιού — χαραγμένες πλάκες πάνω στην ίδια τσόχινη βάση.
Εσύ, ελευθέρωσε την ορισμένη ώρα
Η επόμενη ορισμένη ώρα — αύριο 7:30 π.μ.
Παρατεταμένο πάτημα για αλλαγή θέματος
Αρχική (RootView)
Καμπάνα-Κήρυκας
π.μ.7:30
Καθημερινές · αναβολή 9 λεπτά
π.μ.9:00
Σαββατοκύριακο
μ.μ.10:15
Μόνο μία φορά
Κατάλογος (AlarmListView)
Ρύθμιση ώρας
π.μ.7:30
Ετικέτα — «Πρωινό τσάι» · αναβολή 9 λεπτά
Ρύθμισε σ' αυτή την ώραΕπεξεργασία (AlarmEditorView)
Χρονομετρητής
Χρονομετρητής (TimerView)
Live Activity / Dynamic Island
Ο χρονομετρητής και το χρονόμετρο ζουν στην οθόνη κλειδώματος και στο Dynamic Island. Σε μαύρο φόντο μ' έναν και μόνο τόνο ορείχαλκου, κρατούν την αύρα του ρολογιού τσέπης ακόμη και μέσα στο περιβάλλον του συστήματος.
POCKETCHIME
Ο χρονομετρητής του τσαγιού
4:23
Οθόνη κλειδώματος — οδηγείται από Text(timerInterval:)
Dynamic Island (compact) — αριστερά το καντράν, δεξιά ο χρόνος που απομένει
Στοιχειοθεσία και χρώμα
Η γραμματοσειρά είναι η σειφ του συστήματος (New York / Hiragino Mincho). Οι αριθμοί χαράζονται με ισοπλατή ψηφία, κι οι λατινικές ετικέτες παίρνουν πλατύ διάστιχο γραμμάτων, σαν χαραγμένη επιγραφή σε μέταλλο.
10:09
Ρύθμιση ώρας
Ανοίγεις το καπάκι κι αρχίζει η μέρα. Κουρδίζεις τους δείκτες και προσμένεις την ώρα.
RAILROAD GRADE · EST. 2026
| Τσόχινη βάση (φόντο) | #24331F → #0B110A | |
| Χρώμα μελανιού (κείμενο) | #EFE6CD | |
| Ορείχαλκος (τόνος) | #C9A24B | |
| Άλικο (δείκτης δευτερολέπτων, προειδοποίηση) | #A03A2A | |
| Ατσάλι (ασημένιο θέμα) | #AEB6C2 |
| Σχέδιο | Υλοποίηση (σύμφωνα με το DESIGN.md) |
|---|---|
| Άνοιγμα και κλείσιμο του καπακιού | rotation3DEffect(axis:(0,1,0), anchor:.leading) + spring 1.3s |
| Η κίνηση των δεικτών | Συνεχής οδήγηση μέσω TimelineView(.animation) |
| Σύρσιμο του δείκτη | ClockAngleMath (καθαρή συνάρτηση atan2 · υπό δοκιμή μονάδας) |
| Αναβολή | secondaryButtonBehavior: .countdown + postAlert 9 λεπτά |
| Εμφάνιση του χρόνου που απομένει | Live Activity μέσω AlarmAttributes<PocketWatchMetadata> |
| Διάδοση του θέματος | Συνέπεια ως και το Widget μέσω tintColor και metadata.themeName |