[iOS] Event & Gesture handling : PTS (Pinch-Touch&Tap-Sketch/Swipe) Sketch Example 2

2022. 8. 31. 17:56iOS/Learning

 

지난 포스팅에 이어서 Sketch View, Swipe View를 구현한다.

 

 

Set the Sketch View Layout 

1. Library[➕]버튼을 클릭하여 Vertical Stack View 가져오기

 

2. Stack View 선택하고 하단의 Add New Constraints을 아래와 같이 세팅

3.  Library[➕]버튼을 클릭하여 Button, Image View를 Stack View안에 추가

 

4. Button text: Clear로 변경, Add New Constraints 버튼 클릭하여 Heght: 40으로 변경

 

5. Outlet Variable & Action Function 추가

Editor 영역 상단 우측 Adjust Editor Options 버튼 > Assistant 클릭 

Horizontal Stack View에서 값이 출력될 우측 Lable 3개 각각: Asisttant 코드 영역으로 Drag & Drop

 

 

 

Source Code

SketchViewController.swift

import UIKit

class SketchViewController: UIViewController {
    @IBOutlet var canvas: UIImageView!
    
    var lastPoint: CGPoint!
    var lineSize: CGFloat = 2.0
    var lineColor = UIColor.red.cgColor
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func clearCanvas(_ sender: UIButton) {
        canvas.image = nil
    }
    //    * 디바이스를 흔들었을때도 canvas를 clean
    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            canvas.image = nil
        }
    }
    
    //    * 사용자가 화면을 터치하면 스케치를 시작
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first! as UITouch // get the current touch event
        
        lastPoint = touch.location(in: canvas)
    }
    
    //    * 사용자가 터치한 손가락을 이동하면 스케치도 함께 이동
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        initalSketch()
        
        let touch = touches.first! as UITouch
        let currentPoint = touch.location(in: canvas)
        drawLine(currentPoint: currentPoint)
        
        lastPoint = currentPoint
    }
    
    //    * 사용자가 화면에서 손가락을 떼면 스케치 끝
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        initalSketch()
        drawLine(currentPoint: nil)
    }
    
    func initalSketch() {
        UIGraphicsBeginImageContext(canvas.frame.size) // create a context for sketch
        UIGraphicsGetCurrentContext()?.setStrokeColor(lineColor) // 라인 컬러
        UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round) // 라인 끝모양 둥글게
        UIGraphicsGetCurrentContext()?.setLineWidth(lineSize) // 라인 두께
    }
    
    func drawLine(currentPoint: CGPoint?) {
        // 현재 canvas에 있는 이미지를 canvas의 크기로 그리기
        canvas.image?.draw(in: CGRect(x: 0, y: 0, width: canvas.frame.size.width, height: canvas.frame.size.width))
        
        // 이전에 이동된 위치인 lastPoint로 시작 위치 이동
        UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
        
        // lastPoint에서 currentPoint/lastPoint(현재 위치)까지 선 추가
        if let currentPoint = currentPoint {
            UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: currentPoint.x, y: currentPoint.y))
        } else {
            UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
        }
        
        UIGraphicsGetCurrentContext()?.strokePath() // 추가한 선을 콘텍스트에 그림
        canvas.image = UIGraphicsGetImageFromCurrentImageContext() // 현재 콘텍스트에 그려진 이미지를 canvas(Image View)에 할당
        UIGraphicsEndImageContext()
    }
}

 

 

 

 

Result

더보기
DEBUG

drawLine함수에서 canvas 설정 할때 오타나서 생긴 버그

???????????? 왜이래 -> canvas이미지 뷰 전체 이미지 draw함수 파라미터의 CGRect초기화할때 height 값을 width로 잘못 전달했더니 저딴식으로 나옴

 

 

canvas.image?.draw(in: CGRect(x: 0, y: 0, width: canvas.frame.size.width, height: canvas.frame.size.width))

⬇️

canvas.image?.draw(in: CGRect(x: 0, y: 0, width: canvas.frame.size.width, height: canvas.frame.size.height))

 

 

 

 

 


Reference

Do it! 스위프트로 아이폰 앱 만들기 입문 개정 4판, 이지스 퍼블리싱, 송호정, 이범근