Swift でヒマワリを描く
に触発されて、試しにSwiftで書いてみた。
準備
16進数カラーコードを UIColor に変換する必要があるので、 SwiftでHexColor(#34495eみたいなやつ) - Qiita を参考に、UIColorに簡易イニシャライザを追加する。
extension UIColor { convenience init(hexString: String, alpha: CGFloat) { let hex = hexString.stringByReplacingOccurrencesOfString("#", withString: "") let scanner = NSScanner(string: hex) var rgbValue: UInt32 = 0 if scanner.scanHexInt(&rgbValue) { self.init(red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgbValue & 0xFF00) >> 8) / 255.0, blue: CGFloat(rgbValue & 0xFF) / 255.0, alpha: alpha) } else { self.init(red: 0.0, green: 0.0, blue: 0.0, alpha: alpha) } } convenience init(hexString: String) { self.init(hexString: hexString, alpha: 1.0) } }
mkCoords 関数
配置する円の座標を求める関数。
func mkCoords(n: Int) -> [CGPoint] { // Helper 関数 func coord(n: Int) -> CGPoint { return fromPolar(sqrt(CGFloat(n)), theta: 2.4 * CGFloat(n)) } func fromPolar(r: CGFloat, theta: CGFloat) -> CGPoint { return CGPointMake(r * cos(theta), r * sin(theta)) } return (1...n).map(coord) }
floret 関数
円を作成する関数。とりあえずCALayerにしておく。ここで使用しているカラーセットの定義はここからコピーしてきた。
func floret(r: CGFloat) -> CALayer { let layer = CAShapeLayer() let path = UIBezierPath(arcCenter: CGPointZero, radius: 0.6, startAngle: 0, endAngle: CGFloat(2 * M_PI), clockwise: true).CGPath layer.path = path let n = floor(1.4 * sqrt(r)) % 9 let colors = ["#ffffe5","#fff7bc","#fee391","#fec44f", "#fe9929","#ec7014","#cc4c02","#993404", "#662506","#000000"].map(UIColor.init).reverse() as [UIColor] layer.fillColor = colors[Int(n)].CGColor return layer }
sunflower 関数
ひまわりのレイヤーを返す関数。
func sunflower(n: Int) -> [CALayer] { func florets(n: Int) -> [CALayer] { return (1...n).map { floret(sqrt(CGFloat($0))) } } return zip(mkCoords(n), florets(n)).map { (position, layer) in // 円の位置を変更 layer.position = CGPointMake(position.x + 100, position.y + 100) return layer } }
SunflowerView クラス
ひまわりを描画するView
class SunflowerView: UIView { override func drawRect(rect: CGRect) { let baseLayer = CALayer() baseLayer.frame = CGRectMake(0, 0, 200, 200) sunflower(2000).forEach { baseLayer.addSublayer($0) } // ちょっと拡大 baseLayer.transform = CATransform3DMakeScale(3.0, 3.0, 0.0) layer.addSublayer(baseLayer) } }
完成
SunflowerView(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 200.0))
をaddSubview等すれば完成。以下のようなひまわりが描画される。
注意
試す場合は、Playgroundでは時間がかかるので、Single View Application で行う方が良い(?)