iPhoneリボンスピン

リボンをくるくる回すiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var sceneView : SCNView?

    var count = 0

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createArea()

        createRibbon()

    }

    func setupScene() {

        sceneView = { (v : UIView)-> SCNView in

            let sv = SCNView(frame: v.bounds)

            sv.scene = SCNScene()

            sv.backgroundColor = UIColor(hue: 0.6, saturation: 0.1, brightness: 1, alpha: 1)

            sv.allowsCameraControl = true

            v.addSubview(sv)

            return sv

        }(self.view)

    }

    

    func createArea() {

        let area = SCNBox(width: 20, height: 1, length: 20, chamferRadius: 1)

        area.firstMaterial?.diffuse.contents = UIColor(hue: 0.16, saturation: 0.3, brightness: 0.7, alpha: 1)

        let areaNode = SCNNode(geometry: area)

        sceneView?.scene?.rootNode.addChildNode(areaNode)

    }

    

    func createRibbon() {

        

        var ribbonCreator = {() -> SCNNode in

            let piece = SCNBox(width: 0.1, height: 0.1, length: 0.3, chamferRadius: 0)

            piece.firstMaterial?.diffuse.contents = UIColor(hue: 0, saturation: 0.5, brightness: 1, alpha: 1)

            let node = SCNNode(geometry: piece)

            return node

        }

        

        let ribbon = SCNNode()

        ribbon.name = “ribbon”

        ribbon.position = SCNVector3(x: 0, y: 5, z: 0)

        self.sceneView?.scene?.rootNode.addChildNode(ribbon)

        

        let r = 0.8

        [Int](010).each { i -> Void in

            [Int](060).each { j -> Void in

                let n = ribbonCreator()

                let angle = j * M_PI / 30.0

                let (x, y) = (r * cos(angle), r * sin(angle))

                n.position = SCNVector3(x: Float(x), y: Float(y), z: Float(i) + Float(j) / 60.0)

                ribbon.addChildNode(n)

            }

        }

    }

    

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

        self.count = (self.count + 2) % 10

        

        let node = sceneView?.scene?.rootNode.childNodeWithName(“ribbon”, recursively: false)

        node?.removeAllActions()

        node?.runAction(SCNAction.repeatActionForever(SCNAction.rotateByAngle(CGFloat(M_PI), aroundAxis: SCNVector3(x: 0, y: 0, z: 1), duration: 1.0 / max(Double(self.count), 1.0) )))

    }

}

func * (left: Int, right: Double) -> Double {

    return Double(left) * right

}

extension Array {

    func each(doit:(T)->Void) { for i in self { doit(i)} }

}