Skip to content

Instantly share code, notes, and snippets.

@jonahaung
Created January 16, 2020 17:02
Show Gist options
  • Save jonahaung/3ed303f474d6410ba7a669c74297b75d to your computer and use it in GitHub Desktop.
Save jonahaung/3ed303f474d6410ba7a669c74297b75d to your computer and use it in GitHub Desktop.
//
// ClockSUIView.swift
// Myanmar Lens
//
// Created by Aung Ko Min on 11/1/20.
// Copyright © 2020 Aung Ko Min. All rights reserved.
//
import SwiftUI
// MARK: - Example 5: Clock Shape
struct ClockSUIView: View {
@State private var time: ClockTime = ClockTime(9, 50, 5)
@State private var duration: Double = 2.0
var body: some View {
VStack {
ClockShape(clockTime: time)
.stroke(Color.blue, lineWidth: 3)
.padding(20)
.animation(.easeInOut(duration: duration))
.layoutPriority(Double(1))
Text("\(time.asString())")
HStack(spacing: 20) {
MyButton(label: "9:51:45", font: .footnote, textColor: .black) {
self.duration = 2.0
self.time = ClockTime(9, 51, 45)
}
MyButton(label: "9:51:15", font: .footnote, textColor: .black) {
self.duration = 2.0
self.time = ClockTime(9, 51, 15)
}
MyButton(label: "9:52:15", font: .footnote, textColor: .black) {
self.duration = 2.0
self.time = ClockTime(9, 52, 15)
}
MyButton(label: "10:01:45", font: .caption, textColor: .black) {
self.duration = 10.0
self.time = ClockTime(10, 01, 45)
}
}
}
}
}
struct ClockShape: Shape {
var clockTime: ClockTime
var animatableData: ClockTime {
get { clockTime }
set { clockTime = newValue }
}
func path(in rect: CGRect) -> Path {
var path = Path()
let radius = min(rect.size.width / 2.0, rect.size.height / 2.0)
let center = CGPoint(x: rect.size.width / 2.0, y: rect.size.height / 2.0)
let hHypotenuse = Double(radius) * 0.5 // hour needle length
let mHypotenuse = Double(radius) * 0.7 // minute needle length
let sHypotenuse = Double(radius) * 0.9 // second needle length
let hAngle: Angle = .degrees(Double(clockTime.hours) / 12 * 360 - 90)
let mAngle: Angle = .degrees(Double(clockTime.minutes) / 60 * 360 - 90)
let sAngle: Angle = .degrees(Double(clockTime.seconds) / 60 * 360 - 90)
let hourNeedle = CGPoint(x: center.x + CGFloat(cos(hAngle.radians) * hHypotenuse), y: center.y + CGFloat(sin(hAngle.radians) * hHypotenuse))
let minuteNeedle = CGPoint(x: center.x + CGFloat(cos(mAngle.radians) * mHypotenuse), y: center.y + CGFloat(sin(mAngle.radians) * mHypotenuse))
let secondNeedle = CGPoint(x: center.x + CGFloat(cos(sAngle.radians) * sHypotenuse), y: center.y + CGFloat(sin(sAngle.radians) * sHypotenuse))
path.addArc(center: center, radius: radius, startAngle: .degrees(0), endAngle: .degrees(360), clockwise: true)
path.move(to: center)
path.addLine(to: hourNeedle)
path = path.strokedPath(StrokeStyle(lineWidth: 3.0))
path.move(to: center)
path.addLine(to: minuteNeedle)
path = path.strokedPath(StrokeStyle(lineWidth: 3.0))
path.move(to: center)
path.addLine(to: secondNeedle)
path = path.strokedPath(StrokeStyle(lineWidth: 1.0))
return path
}
}
struct ClockTime {
var hours: Int // Hour needle should jump by integer numbers
var minutes: Int // Minute needle should jump by integer numbers
var seconds: Double // Second needle should move smoothly
// Initializer with hour, minute and seconds
init(_ h: Int, _ m: Int, _ s: Double) {
self.hours = h
self.minutes = m
self.seconds = s
}
// Initializer with total of seconds
init(_ seconds: Double) {
let h = Int(seconds) / 3600
let m = (Int(seconds) - (h * 3600)) / 60
let s = seconds - Double((h * 3600) + (m * 60))
self.hours = h
self.minutes = m
self.seconds = s
}
// compute number of seconds
var asSeconds: Double {
return Double(self.hours * 3600 + self.minutes * 60) + self.seconds
}
// show as string
func asString() -> String {
return String(format: "%2i", self.hours) + ":" + String(format: "%02i", self.minutes) + ":" + String(format: "%02.0f", self.seconds)
}
}
extension ClockTime: VectorArithmetic {
static func -= (lhs: inout ClockTime, rhs: ClockTime) {
lhs = lhs - rhs
}
static func - (lhs: ClockTime, rhs: ClockTime) -> ClockTime {
return ClockTime(lhs.asSeconds - rhs.asSeconds)
}
static func += (lhs: inout ClockTime, rhs: ClockTime) {
lhs = lhs + rhs
}
static func + (lhs: ClockTime, rhs: ClockTime) -> ClockTime {
return ClockTime(lhs.asSeconds + rhs.asSeconds)
}
mutating func scale(by rhs: Double) {
var s = Double(self.asSeconds)
s.scale(by: rhs)
let ct = ClockTime(s)
self.hours = ct.hours
self.minutes = ct.minutes
self.seconds = ct.seconds
}
var magnitudeSquared: Double {
1
}
static var zero: ClockTime {
return ClockTime(0, 0, 0)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment