[Swift] ARKit でお絵かきアプリを作成する

2019年6月14日ITARKit, Swift

ARKit でお絵かきアプリを作成しました。

色を変えられます。

DrawingViewController.swift

import UIKit
import ARKit

class DrawingViewController: UIViewController {

    @IBOutlet weak var sceneView: ARSCNView!
    @IBOutlet weak var colorLabel: UILabel!
    @IBOutlet weak var colorCollectionView: UICollectionView!
    
    let configuration = ARWorldTrackingConfiguration()
    let colorsArray: [String] = ["red", "green", "blue", "white", "gray", "black"]
    let colorsTestArray: [UIColor] = [.red, .green, .blue, .white, .gray, .black]
    var selectedColorIndex: Int = 0
    var selectedColorString: String = "red"
    var selectedColor: UIColor = .red
    var isChangeColor = false
    
    var lineNode: SCNNode?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.sceneView.debugOptions = [.showWorldOrigin, .showFeaturePoints]
        self.configuration.planeDetection = .horizontal
        // 全方向光源ON
        sceneView.autoenablesDefaultLighting = true
        self.sceneView.session.run(configuration)
//        self.sceneView.delegate = self
        self.colorCollectionView.dataSource = self
        self.colorCollectionView.delegate = self
        
        self.colorLabel.text = selectedColorString
        self.colorLabel.textColor = selectedColor
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let tmpNode: SCNNode
        
        if isChangeColor {
            let newLineNode = createLineNode()
            lineNode = newLineNode
            tmpNode = newLineNode
        } else {
            if let existLineNode = lineNode {
                tmpNode = existLineNode.clone()
            } else {
                let newLineNode = createLineNode()
                lineNode = newLineNode
                tmpNode = newLineNode
            }
        }
        
        isChangeColor = false
        
        // スクリーン座標系(ディスプレイをタッチした座標)
        guard let touchLocation: CGPoint = touches.first?.location(in: sceneView) else { return }
        
        // タッチした座標にZ座標を加える
        let linePosition: SCNVector3 = SCNVector3(touchLocation.x, touchLocation.y, 0.996)
        
        // 世界座標系にあてる
        let worldPosition = sceneView.unprojectPoint(linePosition)
        
        tmpNode.name = "line"
        tmpNode.position = worldPosition
        sceneView.scene.rootNode.addChildNode(tmpNode)
    }
    
    func createLineNode() -> SCNNode {
        let spehere = SCNSphere(radius: 0.002)
        let node = SCNNode(geometry: spehere)
        node.geometry?.firstMaterial?.diffuse.contents = selectedColor
        return node
    }
    
    func setColor() {
        switch selectedColorString {
        case "red":
            selectedColor = .red
        case "green":
            selectedColor = .green
        case "blue":
            selectedColor = .blue
        case "white":
            selectedColor = .white
        case "gray":
            selectedColor = .gray
        case "black":
            selectedColor = .black
        default:
            break // do nothing
        }
    }
    
    
    @IBAction func deleteButton_Tap(_ sender: UIButton) {
        self.sceneView.scene.rootNode.enumerateChildNodes { (node, _) in
            if node.name == "line" {
                node.removeFromParentNode()
            }
        }
    }
    
}

extension DrawingViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//        let cell = collectionView.cellForItem(at: indexPath)
        
        self.selectedColorIndex = indexPath.row
        self.selectedColorString = colorsArray[indexPath.row]
        self.setColor()
        self.colorLabel.text = selectedColorString
        self.colorLabel.textColor = selectedColor
        self.isChangeColor = true
        self.colorCollectionView.reloadData()
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return colorsArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as! itemViewCell
//        if selectedColorIndex == indexPath.row {
//            cell.backgroundColor = self.colorsTestArray[indexPath.row].withAlphaComponent(0.4)
//        } else {
//            cell.backgroundColor = self.colorsTestArray[indexPath.row]
//        }
        cell.backgroundColor = self.colorsTestArray[indexPath.row]
        return cell
    }

}

itemViewCell.swift

import UIKit

class itemViewCell: UICollectionViewCell {
   
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        self.setLayer()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.setLayer()
    }
    
    internal func setLayer() {
        self.layer.cornerRadius = self.frame.width/2
        self.layer.masksToBounds = false
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOffset = CGSize(width: 0, height: 0)
        self.layer.shadowOpacity = 0.5
        self.layer.shadowRadius = 20
    }
}

スポンサーリンク

Posted by nobuhiro harada