在這篇文章中,我們將挑戰使用 UIBezierPath 來設計並實現一個完整的互動棋盤 UI。UIBezierPath 是一個非常強大的工具,能讓我們以簡單的方式繪製複雜的形狀和路徑。在這次的練習中,我們會利用它繪製棋盤,並讓玩家可以互動放置棋子。這次整個 UI 完全使用程式碼動態生成,讓我們來看看如何只依賴程式碼來打造實現這個 UI 吧!
透過這篇文章,你將學習到以下幾個核心技能:
在這篇文章中,我們將使用到以下幾個 iOS 開發的核心技術:
這些技術相互結合,使得我們能夠創建一個富有交互性和視覺效果的遊戲介面。
使用 Xcode 15 提供的 #Preview 功能,讓我們能即時看到 UIBezierPath 繪製的效果。這有助於在開發過程中快速調整圖形和界面。
#Preview {
UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()!
}
UIBezierPath 是 iOS 中用來繪製 2D 向量路徑的工具。它可以用來畫直線、曲線、矩形、圓形、橢圓形等,甚至是任意多邊形或複雜形狀。
在這個例子中,我們使用 UIBezierPath 和 CAShapeLayer 來畫出一個三角形,並且可以利用 fillColor 屬性來更改三角形的顏色。。UIBezierPath 有以下幾個關鍵步驟:
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 110, y: 0))
path.addLine(to: CGPoint(x: 90, y: 70))
path.close()
let triangleLayer = CAShapeLayer()
triangleLayer.path = path.cgPath
triangleLayer.fillColor = UIColor.init(red: 0.7, green: 0.5, blue: 0.5, alpha: 0.5).cgColor
view.layer.addSublayer(triangleLayer)
棋盤由 12x12 的網格組成,使用 UIBezierPath 繪製直線,通過 move(to:) 和 addLine(to:) 定義起點和終點來完成線條的繪製,並且我們加入了 CABasicAnimation 讓線條一條條地顯示,增添動感。
let boardWidth = 300.0
let boardHeight = 300.0
let numRows = 12
let numCols = 12
let cellWidth = boardWidth / CGFloat(numCols)
let cellHeight = boardHeight / CGFloat(numRows)
let path = UIBezierPath()
for i in 0...numRows {
let y = CGFloat(i) * cellHeight
path.move(to: CGPoint(x: 50, y: y+100))
path.addLine(to: CGPoint(x: boardWidth+50, y: y+100))
}
for i in 0...numCols {
let x = CGFloat(i) * cellWidth
path.move(to: CGPoint(x: x+50, y: 0+100))
path.addLine(to: CGPoint(x: x+50, y: boardHeight+100))
}
UIColor.lightGray.setStroke()
path.lineWidth = 1.0
let lineLayer = CAShapeLayer()
lineLayer.path = path.cgPath
lineLayer.strokeColor = UIColor.lightGray.cgColor
lineLayer.lineWidth = 1.0
view.layer.addSublayer(lineLayer)
接下來,我們要處理棋子的放置。由於 CAShapeLayer 不支援事件處理,所以我們需要將棋盤搬到 UIView 裡來處理互動。為了實現棋子放置的功能,我們覆寫了 touchesBegan 方法,這個方法能捕捉到使用者的觸控事件。
當玩家點擊棋盤上的某個位置時,我們會計算點擊的座標,並透過算法找到與此座標最接近的棋盤交叉點,這樣就能精準地在棋盤上放置棋子。棋子的顏色會根據玩家的回合輪流變換,模擬出雙方對弈的效果。以下是實現邏輯的示範程式碼:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let touchLocation = touch.location(in: self)
// 找到與點擊座標最接近的棋盤交叉點
let nearestPoint = findNearestIntersection(for: touchLocation)
// 在最近的交叉點放置棋子
placePiece(at: nearestPoint)
}
透過這個步驟,玩家的每一次點擊都會觸發棋子的放置動作,使得棋盤上的互動變得自然且準確。
利用 CAShapeLayer 和 UIBezierPath 繪製一個特別的外框,提示玩家最近一次放置的棋子位置,增強遊戲的互動性。
我們使用 UIBezierPath 繪製了多種棋子形狀,包括圓形、心形、方形和星形,並且將它們動態添加到棋盤中,讓玩家可以自由選擇棋子的形狀。每個棋子形狀都是一個 UIView,其 layer 使用 UIBezierPath 來繪製圖形,最後這些棋子形狀會加入棋盤視圖中。
在這篇文章中,我們探索了如何使用 UIBezierPath、CAShapeLayer 和 CABasicAnimation,實現一個具有豐富交互性和視覺效果的棋盤 App。本次設計完全依靠程式碼動態生成,使界面設計更具靈活性和可擴展性。希望你也能從中學到更多有關 iOS 繪圖和動畫的技巧,並將這些知識應用到你的開發中。