🌀CGRect
這個擴展幫 CGRect 新增一些好用的屬性。
目前版本
/*
* ⭐️ required:
* - 🅿️ Rectangular
*/
import SwiftUI // for CGRect
// 🌀CGRect + Rectangular
extension CGRect: Rectangular { }
// 🌀CGRect + convenience inits
extension CGRect {
/// CGRect(x,y,w,h)
public init(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) {
self.init(x: x, y: y, width: width, height: height)
}
/// rect from one corner to another.
/// `CGRect(from: A, to: B)`
public init(from p1: CGPoint, to p2: CGPoint) {
let x = p1.x
let y = p1.y
let w = p2.x - p1.x
let h = p2.y - p1.y
self.init(x: x, y: y, width: w, height: h)
}
/// rect with center and corner.
/// - `CGRect(center: A, corner: B)`
public init(center: CGPoint, corner: CGPoint) {
let x = corner.x
let y = corner.y
let dx = center.x - corner.x
let dy = center.y - corner.y
self.init(x: x, y: y, width: 2 * dx, height: 2 * dy)
}
/* ------ Modifiers -------- */
/// - turn a `CGRect` into `Path`
public var path: Path { Path(self) }
}
import SwiftUI
// ⭐️ required: 🌀CGPoint+Vector2D, 🌀CGRect
// points
let A = CGPoint(40, 40)
let B = CGPoint(80, 70)
// rects
let rect1 = CGRect(from: A, to: B) // origin: (40,40), size:(30,40)
let rect2 = CGRect(center: A, corner: B) // origin: ( 0,10), size:(60,80)
// instance members
rect1.point(0.5, 0.5) // (60, 55)
rect2.point(1,1) // (80, 70)
rect2.bottomRight // (80, 70)
rect2.corners // [(0,70), (80,70), (80,10), (0,10)]
// subscript
let p = CGPoint(1,2) // 🌀CGPoint
let size = CGSize(20, 20) // 🌀CGSize
let rect = CGRect(origin: p, size: size / 2) // 🌀CGSize + 🅿️Vector2D
rect[ 0, 0] // ( 1, 2)
rect[ 1, 0] // ( 11, 2)
rect[ 0, 1] // ( 1, 12)
rect[ 2, 1] // ( 21, 12)
rect[-2,-2] // (-19, -18)
2020.09.30:➕ added .path
2020.10.08: ➕ .maxSide ✏️
minLength➝ minSide ➕ CGRect(x, y, w, h) ➕ subscript: rect[x, y]
修改記錄
2020.09.30:➕ added .path
2020.10.08: ➕ .maxSide ✏️
minLength➝ minSide ➕ CGRect(x, y, w, h) ➕ subscript: rect[x, y]➊ 2020.10.11:將大部分的功能移至 Rectangular
// 封存日期:2020.10.11
// 修改內容:
// 1. 將大部分的功能移至 Rectangular
// 2. 移除對 Vector2D 的依賴
// ------------------------------------
/*
* ⭐️ required:
* - 🅿️ Vector2D
*/
import SwiftUI // for CGRect
import VectorSpace // for 🅿️ Vector2D
// 🌀CGRect
extension CGRect {
/* ------- ⭐️ Points ------- */
/// # Key Points of a CGRect
/// - Example: `.top`, `.bottom`, `.center`, ...
public enum KeyPoint: CaseIterable {
case topLeft, top, topRight
case left, center, right
case bottomLeft, bottom, bottomRight
}
// `rect.point(at: .top) == rect.top`
public func point(at position: KeyPoint) -> CGPoint {
switch position {
case .topLeft : return topLeft
case .top : return top
case .topRight : return topRight
case .left : return left
case .center : return center
case .right : return right
case .bottomLeft : return bottomLeft
case .bottom : return bottom
case .bottomRight: return bottomRight
}
}
// rect.top, ...
public var top : CGPoint { CGPoint(x: midX, y: minY) }
public var bottom : CGPoint { CGPoint(x: midX, y: maxY) }
public var left : CGPoint { CGPoint(x: minX, y: midY) }
public var right : CGPoint { CGPoint(x: maxX, y: midY) }
public var center : CGPoint { CGPoint(x: midX, y: midY) }
public var bottomLeft : CGPoint { CGPoint(x: minX, y: maxY) }
public var bottomRight: CGPoint { CGPoint(x: maxX, y: maxY) }
public var topLeft : CGPoint { CGPoint(x: minX, y: minY) }
public var topRight : CGPoint { CGPoint(x: maxX, y: minY) }
/// 4 corners of a rect
public var corners: [CGPoint] { [bottomLeft, bottomRight, topRight, topLeft] }
/// # Relative Point
/// a point relative to the rectangle's width and height
/// ## Examples
/// - `rect.point(0,0) == rect.topLeft`
/// - `rect.point(1,1) == rect.bottomRight`
public func point(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
let u = topRight - topLeft // 🅿️ Vector2D
let v = bottomLeft - topLeft
let w = x * u + y * v
return topLeft + w
}
/// ## Examples
/// - `rect[1,0] == rect.topRight`
/// - `rect[0,1] == rect.bottomLeft`
public subscript(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
point(x, y)
}
/* ------- ⭐️ Dimensions ------- */
/// side length of the rect.
public var minSide: CGFloat { min(width, height) }
public var maxSide: CGFloat { max(width, height) }
/* ------- ⭐️ Initializers ------- */
/// CGRect(x,y,w,h)
public init(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) {
self.init(x: x, y: y, width: width, height: height)
}
/// draws a `CGRect` from a corner to another corner.
/// `CGRect(from: A, to: B)`
public init(from p1: CGPoint, to p2: CGPoint) {
let x = min(p1.x, p2.x)
let y = min(p1.y, p2.y)
let w = abs(p1.x - p2.x)
let h = abs(p1.y - p2.y)
self.init(x: x, y: y, width: w, height: h)
}
/// draws a `CGRect` with center and a corner.
/// - `CGRect(center: A, corner: B)`
public init(center p1: CGPoint, corner p2: CGPoint) {
self.init(from: p2, to: 2 * p1 - p2) // 🅿️ Vector2D
}
/* ------ Modifiers -------- */
/// - turn a `CGRect` into `Path`
public var path: Path { Path(self) }
}
Last updated