iPhoneナイチンゲールグラフ

ナイチンゲールが作ったグラフを模倣するiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SpriteKit

class ViewController: UIViewController {

    weak var scene : SKScene?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createGraph()

    }

    func setupScene() {

        let sv = SKView(frame: view.bounds)

        let s = SKScene(size: sv.bounds.size)

        s.backgroundColor = UIColor(hue: 0.22, saturation: 0.1, brightness: 1, alpha: 0.7)

        sv.presentScene(s)

        view.addSubview(sv)

        

        scene = s

    }

    

    func createGraph() {

        let data = [10, 9, 8, 5, 6.5, 5, 4.5, 4, 3, 2, 3, 5, 7, 8] as [CGFloat];

        let dAngle = 2 * Float(M_PI) / Float(data.count)

        

        for i in 0..<data.count {

            let angle = dAngle * Float(i)

            let n = SKNode()

            n.name = “arc”

            n.position = CGPoint(x:CGRectGetMidX(view.bounds), y:CGRectGetMidY(view.bounds))

            n.zRotation = CGFloat(angle)

            n.userData = [“angle” : n.zRotation]

            

            n.runAction(SKAction.rotateByAngle(n.zRotation, duration: 0))

            

            scene?.addChild(n)

            

            let r = CGRectGetMidX(view.bounds) * data[i] * 0.1

            let path = UIBezierPath()

            path.moveToPoint(CGPointZero)

            path.addLineToPoint(CGPoint(x: r * CGFloat(cos(-dAngle * 0.5)), y: r * CGFloat(sin(-dAngle * 0.5))))

            path.addLineToPoint(CGPoint(x: r * CGFloat(cos(dAngle * 0.5)), y: r * CGFloat(sin(dAngle * 0.5))))

            path.closePath()

            

            let a = SKShapeNode(path: path.CGPath)

            a.fillColor = UIColor(hue: 0.22, saturation: 0.1, brightness: 1, alpha: 0.7)

            n.addChild(a)

            

            let rate = CGFloat(arc4random_uniform(8)) * 0.1

            path.applyTransform(CGAffineTransformMakeScale(rate, rate))

            let b = SKShapeNode(path: path.CGPath)

            b.fillColor = (r * rate < 40) ? UIColor.blackColor() : UIColor(hue: 0, saturation: 0.4, brightness: 0.8, alpha: 1)

            n.addChild(b)

        }

    }

    

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

        scene?.children

            .filter { $0.name == “arc” }

            .map { (n : AnyObject) -> AnyObject in

                if let a = (n as SKNode).userData![“angle”] as? CGFloat{

                    n.runAction(SKAction.rotateToAngle(a, duration: 2.0))

                }

                return n;

        }

    }

    

}