學習目標:
- Gesture Recognizer
- CALayer & UIBezierPath
- Class & Function
練習成果:
原始碼:
GitHub - takawang/olympic-drone
緣起:
這次的練習,主要是看到下面這篇文章的啟發,不過我簡化了觸模散開與加速度這個部分,主要是練習 swift 實作。
說明:
實作的構想還算直覺,除了長壓連續觸發需要研究一下。
- 使用 javascript 的 canvas getImageData() 將 SVG 存成 json 檔 (可參考上文連結中的 getDotPos 方法。
- 在 swift 中,透過讀取 json 檔,存成座標點的類別陣列,這兩步驟也可以用來畫其他圖案,不用手工一直描點。
load all points from json file
import UIKit
// Point definition for json object
class Point: Decodable {
let x, y: Int
let color: String
// load all points from json file.
//
// ref: https://stackoverflow.com/a/50042872
// ref: https://praveenkommuri.medium.com/how-to-read-parse-local-json-file-in-swift-28f6cec747cf
static func loadFromJson(fileName name: String) -> [Point] {
do {
guard let filePath = Bundle.main.path(forResource: name, ofType: "json") else { return [] }
let fileUrl = URL(fileURLWithPath: filePath)
let data = try Data(contentsOf: fileUrl)
let points = try JSONDecoder().decode([Point].self, from: data)
return points
} catch {
// should not happen!
print("Something went wrong: \(error)")
return []
}
}
}
- 設計 Drone 類別,讓 Drone 初始位置是隨機的,目的位置是剛剛載入的圖形座標。
- 將兩座標分成 20 份,持續按壓連續觸發時,一次移動一份。
- 當到達目的座標時,改變 Drone 的顏色。
handle long press event
import UIKit
class ViewController: UIViewController {
var touchCountTimer: Timer?
var touchBeginTime: Double = 0
let droneCollection = DroneCollectionController(fromJsonFile: "ring") // composition
override func viewDidLoad() {
super.viewDidLoad()
droneCollection.attachToLayer(to: self.view.layer) // attach drone layer
addLongPressGesture() // handle press
}
// register gesture recognizer
//
// ref: [How can i count time on long-pressed button using UILongPressGestureRecognizer](https://stackoverflow.com/a/53146530)
func addLongPressGesture(){
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gesture:)))
longPress.minimumPressDuration = 0.1
longPress.numberOfTouchesRequired = 1
self.view.addGestureRecognizer(longPress)
}
// handle long press event
//
// ref: [How can i count time on long-pressed button using UILongPressGestureRecognizer](https://stackoverflow.com/a/53146530)
@objc func longPress(gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case UIGestureRecognizer.State.began:
touchCountTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { [self] (timer) in
// MARK: - do animation
droneCollection.animation()
})
touchBeginTime = Date().timeIntervalSince1970
case .ended, .failed, .cancelled:
touchCountTimer?.invalidate() // Stops the timer
DroneCollectionController.isArrived = false
case .changed: // wipe
break
default:
print("unknown")
}
}
}