LoginSignup
0
1

More than 5 years have passed since last update.

SwiftでUIBezierPathを使い、簡単な図形を描画するアプリを作ってみた。②

Posted at

はじめに

簡単な図形描画アプリ「DotView」を作成する2回目です。

前回:SwiftでUIBezierPathを使い、簡単な図形を描画するアプリを作ってみた。①

今回は、TextFieldやSliderで入力した値をUIViewに反映させる部分を作成し、DotViewを完成させたいと思います。

各TextFieldに値を入力した場合の処理を作成する。

前回で、TextFieldとプログラムとの関連づけを行いました。
これから、それらのTextFieldに値が入力された場合の処理を作成していきます。

まずは、TextFieldごとにタグ付けを行います。(各TextFieldごとに処理を記述するため)

ViewController.swift
override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // テキストフィールド毎にタグを設定
        xText.delegate = self
        xText.tag = 1
        yText.delegate = self
        yText.tag = 2
        radiusText.delegate = self
        radiusText.tag = 3
        vertexText.delegate = self
        vertexText.tag = 4

        self.view.backgroundColor = UIColor.gray // 全体背景をグレーに設定
    }

TextFieldに値が入力された場合に呼び出されるデリゲートメソッドtextFieldShouldReturnを記述し、その中でタグごとに処理を分岐させます。

ViewController.swift
// 各テキストフィールドに値が入力された場合
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // キーボードを閉じる
        textField.resignFirstResponder()
        // switch文により、それぞれのtextに入力した場合を分ける
        switch textField.tag {
        case 1: // xText

        case 2: // yText

        case 3: // radiusText

        case 4: // vertexText

        default:
            print("エラー")
        }
        return true
    }

それぞれのcaseでは、以下のような処理を行います。

  • TextFieldに入力された値をCGFloatやIntに変換
  • 変換した値を、TestDraw.swiftの対応する変数に格納
  • 円の面積を更新(radiusText変更時のみ)

UIViewを管理しているTestDraw.swift内のx,yなどの値を変更することで、その位置に円を再描画することができます。

ViewController.swift
// 各テキストフィールドに値が入力された場合
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // キーボードを閉じる
        textField.resignFirstResponder()
        // switch文により、それぞれのtextに入力した場合を分ける
        switch textField.tag {
        case 1:
            // xTextに入力した値をStringからCGFloatに変換
            let xDouble = Double(textField.text ?? "") ?? 0.0
            let x: CGFloat = CGFloat(xDouble)
            // 入力された値をTestDraw.swift内に存在する座標変数へと格納
            nextView.x = x

        case 2:
            // 同様のことをyTextについてもやる
            let yDouble = Double(textField.text ?? "") ?? 0.0
            let y:CGFloat = CGFloat(yDouble)
            nextView.y = y

        case 3:
            // radiusText
            let radiusDouble = Double(textField.text ?? "") ?? 0.0
            let radius: CGFloat = CGFloat(radiusDouble)
            nextView.radius = radius
            areaValueLabel.text = String(Double(nextView.area!))

        case 4:
            // vertexText
            let vertex = Int(textField.text ?? "") ?? 0
            nextView.vertex  = vertex

        default:
            print("エラー")
        }
        return true
    }

これで、TextFieldを変更した時の処理を作成することができました。
次は、Sliderの値を変更した時の処理を作成していきます。

Sliderの値変更時の処理を作成する。

Sliderの値を変更した時には、以下のような動作が行われるようにします。

  • Sliderの現在の値を、対応するTextFieldに表示する。
  • Sliderの現在の値を、TestDraw.swiftの対応する変数に格納する。
  • 面積の値を変更(radius変更時)

まずは、Sliderの最大値と最小値を設定します。
Sliderを選択し、Attribute Inspectorにて適当な値を入力します。
スクリーンショット 2018-10-04 午前3.02.20.png

valueは、この場合はアプリを起動した際の初期値となります。

それぞれのSliderにて設定ができたら、上記の動作を記述していきます。

ViewController.swift
// radiusを設定するスライダー
    @IBAction func radiusSlider(_ sender: UISlider) {
        //最大値と最小値はstoryboardにて設定済み
        //sliderの値が変更された場合の処理
        //valueをradiusのテキストフィールドに表示
        radiusText.text = String(sender.value)
        //設定したradiusを円描画用のradiusに送る
        nextView.radius = CGFloat(sender.value)
        print(sender.value) // ログ
        //面積の変更
        areaValueLabel.text = String(Double(nextView.area!))
    }

    // vertexを設定するスライダー
    @IBAction func vertexSlider(_ sender: UISlider) {
        //最大値と最小値はstoryboardにて設定済み
        //valueをNo.Vertのテキストフィールドに表示
        vertexText.text = String(Int(sender.value))
        //設定したvertexを円描画用のvertexに送る
        nextView.vertex = Int(sender.value)
        print(nextView.vertex) // ログ

    }

これで、Sliderを動かした時、それに伴って円が描画されるようになりました。

完成

これで、簡単な図形描画アプリ「DotView」を作成することができました。
最後にもう一度、コード全体とアプリ画面を載せておきます。

ViewController.swift
//
//  ViewController.swift
//  DotView
//
//  Created by iwai on 2018/09/14.
//  Copyright © 2018年 iwai. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // テキストフィールド毎にタグを設定
        xText.delegate = self
        xText.tag = 1
        yText.delegate = self
        yText.tag = 2
        radiusText.delegate = self
        radiusText.tag = 3
        vertexText.delegate = self
        vertexText.tag = 4

        self.view.backgroundColor = UIColor.gray // 全体背景をグレーに設定
    }

    @IBOutlet weak var nextView: TestDraw!

    @IBOutlet weak var xLabel: UILabel! // 「X」
    @IBOutlet weak var yLabel: UILabel! // 「Y」
    @IBOutlet weak var radiusLabel: UILabel! // 「Radius」
    @IBOutlet weak var areaLabel: UILabel! // 「Area」
    @IBOutlet weak var vertexLabel: UILabel! // 「No.Vert」
    @IBOutlet weak var radius2Label: UILabel! // UISliderの隣の「Radius」
    @IBOutlet weak var vertex2Label: UILabel! // UISliderの隣の「No.Vert」


    @IBOutlet weak var xText: UITextField! // 中心のX座標入力
    @IBOutlet weak var yText: UITextField! // 中心のY座標入力
    @IBOutlet weak var radiusText: UITextField! // 円の半径入力
    @IBOutlet weak var vertexText: UITextField! // 正多角形の頂点の数入力
    @IBOutlet weak var areaValueLabel: UILabel! // 計算された円の面積を表示



    // 各テキストフィールドに値が入力された場合
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // キーボードを閉じる
        textField.resignFirstResponder()
        // switch文により、それぞれのtextに入力した場合を分ける
        switch textField.tag {
        case 1:
            // xTextに入力した値をStringからCGFloatに変換
            let xDouble = Double(textField.text ?? "") ?? 0.0
            let x: CGFloat = CGFloat(xDouble)
            // 入力された値をTestDraw.swift内に存在する座標変数へと格納
            nextView.x = x

        case 2:
            // 同様のことをyTextについてもやる
            let yDouble = Double(textField.text ?? "") ?? 0.0
            let y:CGFloat = CGFloat(yDouble)
            nextView.y = y

        case 3:
            // radiusText
            let radiusDouble = Double(textField.text ?? "") ?? 0.0
            let radius: CGFloat = CGFloat(radiusDouble)
            nextView.radius = radius
            areaValueLabel.text = String(Double(nextView.area!))

        case 4:
            // vertexText
            let vertex = Int(textField.text ?? "") ?? 0
            nextView.vertex  = vertex

        default:
            print("エラー")
        }
        return true
    }


    // radiusを設定するスライダー
    @IBAction func radiusSlider(_ sender: UISlider) {
        //最大値と最小値はstoryboardにて設定済み
        //sliderの値が変更された場合の処理
        //valueをradiusのテキストフィールドに表示
        radiusText.text = String(sender.value)
        //設定したradiusを円描画用のradiusに送る
        nextView.radius = CGFloat(sender.value)
        print(sender.value)
        //面積の変更
        areaValueLabel.text = String(Double(nextView.area!))
    }

    // vertexを設定するスライダー
    @IBAction func vertexSlider(_ sender: UISlider) {
        //最大値と最小値はstoryboardにて設定済み
        //valueをNo.Vertのテキストフィールドに表示
        vertexText.text = String(Int(sender.value))
        //設定したvertexを円描画用のvertexに送る
        nextView.vertex = Int(sender.value)
        print(nextView.vertex)

    }
}
TestDraw.swift
//
//  TestDraw.swift
//  DotView
//
//  Created by iwai on 2018/09/14.
//  Copyright © 2018年 iwai. All rights reserved.
//

import UIKit

class TestDraw: UIView {

    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
 */
    // 中心のx座標。ViewControllerのXtextからの値を格納する変数
    var x:CGFloat = 150 // 初期値
    {
        didSet {
            if oldValue != x {
                self.setNeedsDisplay()
            }
        }
    }
    // 中心のy座標。同じくyTextからの値を格納する変数
    var y:CGFloat = 100 // 初期値
    {
        didSet {
            if oldValue != y {
                self.setNeedsDisplay()
            }
        }
    }

    //円の半径
    var radius: CGFloat = 50
    {
        didSet {
            if oldValue != radius {
                self.setNeedsDisplay()
            }
        }
    }

    //正多角形の頂点の数
    var vertex: Int = 3
    {
        didSet {
            if oldValue != vertex {
                self.setNeedsDisplay()
            }
        }
    }

    var area: CGFloat?

    override func draw(_ rect: CGRect) {
        // Drawing code
        // 円の描画
        let center = CGPoint(x: x,y: y) // 円の中心座標を設定
        self.drawCircle(radius: radius,center: center) // 半径と中心を設定し、円を描画
        // 正多角形の描画
        self.drawRegularPolygon(vertex, radius: radius, center: center) // 頂点の数・外接円の半径・中心を設定し多角形を描画
    }


    // 円の描画関数
    func drawCircle(radius: CGFloat, center: CGPoint){

        let circle = UIBezierPath(arcCenter: center, radius: radius, startAngle: CGFloat(Double.pi*2.0*0.0/360.0), endAngle: CGFloat(Double.pi*2.0*360.0/360.0), clockwise: true)
        let circleColor = UIColor.red // 色を赤に設定
        circleColor.setStroke() // 線の色を設定
        circleColor.setFill() // 内側塗りつぶし色の設定
        circle.fill() // 内側塗りつぶし
        circle.lineWidth = 4
        circle.stroke() // 描画
        area = (radius * radius) * CGFloat(Double.pi) // 面積の計算

        print(area) // ログ
        print(String(Double(area!)))
    }


    // 正多角形の描画関数
    func drawRegularPolygon(_ p:Int, radius:CGFloat, center:CGPoint){
        let line = UIBezierPath()// インスタンス生成
        var pt:[CGPoint]=[] // 頂点の座標を格納する配列
        for i in 0 ..< p {
            let rad: CGFloat = CGFloat(Double.pi * Double(i) * 2.0 / Double(p) + Double.pi / 2.0)
            let point = CGPoint(x: center.x + radius * cos(rad), y: center.y - radius * sin(rad))
            pt.append(point)
        }

        // 起点
        line.move(to: pt[0])
        // 帰着点
        for j in 1..<p {
            line.addLine(to: pt[j])
        }
        //ラインを結ぶ
        line.close()
        //色の設定
        UIColor.yellow.setStroke()
        //ライン幅
        line.lineWidth = 4
        //描画
        line.stroke()
    }
}

Simulator Screen Shot - iPhone 8 Plus - 2018-09-26 at 18.16.19.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1