手描き機能
【手描き機能を作る】
UIImageを利用して手描き線をペイントできる方法を紹介しています。
1.UIImageViewを設定する まず、手描きのためのキャンバスとなるUIImageViewを設定します。
let canvas = UIImageView(frame: self.view.bounds)
self.view.addSubview(canvas)
self.view.addSubview(canvas)
2.次に、ユーザーのタッチイベントを検出して、画像を描画するための座標を収集します。
タッチイベントを処理するには、以下のようなメソッドを追加します。
タッチイベントを処理するには、以下のようなメソッドを追加します。
var lastPoint = CGPoint.zero
var swiped = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
swiped = false
if let touch = touches.first {
lastPoint = touch.location(in: self.view)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
swiped = true
if let touch = touches.first {
let currentPoint = touch.location(in: self.view)
drawLine(from: lastPoint, to: currentPoint)
lastPoint = currentPoint
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if !swiped {
drawLine(from: lastPoint, to: lastPoint)
}
}
var swiped = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
swiped = false
if let touch = touches.first {
lastPoint = touch.location(in: self.view)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
swiped = true
if let touch = touches.first {
let currentPoint = touch.location(in: self.view)
drawLine(from: lastPoint, to: currentPoint)
lastPoint = currentPoint
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if !swiped {
drawLine(from: lastPoint, to: lastPoint)
}
}
3.タッチイベントで収集された座標を使用して、UIImageViewに線を描画します。
func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) {
UIGraphicsBeginImageContext(self.view.frame.size)
canvas.image?.draw(in: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height))
let context = UIGraphicsGetCurrentContext()
context?.move(to: fromPoint)
context?.addLine(to: toPoint)
context?.setBlendMode(.normal)
context?.setLineCap(.round)
context?.setLineWidth(5.0)
context?.setStrokeColor(UIColor.red.cgColor)
context?.strokePath()
canvas.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
UIGraphicsBeginImageContext(self.view.frame.size)
canvas.image?.draw(in: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height))
let context = UIGraphicsGetCurrentContext()
context?.move(to: fromPoint)
context?.addLine(to: toPoint)
context?.setBlendMode(.normal)
context?.setLineCap(.round)
context?.setLineWidth(5.0)
context?.setStrokeColor(UIColor.red.cgColor)
context?.strokePath()
canvas.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
4.コードをまとめていきます。
import UIKit
class ViewController: UIViewController {
//手描きするためのUIImage
var canvas:UIImageView!
var bezierPath:UIBezierPath!
var lastdrawImage:UIImage?
//クリアにするためのボタン
let clearbtn = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
//ステータスバーの高さ
let statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 30
let screenWidth = self.view.frame.width
let screenHeight = self.view.frame.height
//キャンバスを設置
canvas = UIImageView()
canvas.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)
canvas.backgroundColor = UIColor.clear
self.view.addSubview(canvas)
//クリアーボタン
clearbtn.backgroundColor = UIColor(red: 0, green: 0, blue: 1.0, alpha: 1.0)
clearbtn.frame = CGRect(x:screenWidth/5, y:statusBarHeight + screenHeight/12, width:screenWidth/2/2, height: screenWidth/2/2)
clearbtn.layer.cornerRadius = screenWidth/2/4
clearbtn.addTarget(self, action: #selector(ViewController.clearbtntap(_:)), for: .touchUpInside)
self.view.addSubview(clearbtn)
}
//タッチ開始の際の処理
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchEvent = touches.first!
let currentPoint:CGPoint = touchEvent.location(in: self.canvas)
bezierPath = UIBezierPath()
bezierPath.lineWidth = 10.0
bezierPath.lineCapStyle = .butt
bezierPath.move(to:currentPoint)
}
//タッチ中の処理
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if bezierPath == nil {
return
}
let touchEvent = touches.first!
let currentPoint:CGPoint = touchEvent.location(in: self.canvas)
bezierPath.addLine(to: currentPoint)
drawLine(path: bezierPath)
}
//タッチ終了時の処理
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if bezierPath == nil {
return
}
let touchEvent = touches.first!
let currentPoint:CGPoint = touchEvent.location(in: canvas)
bezierPath.addLine(to: currentPoint)
drawLine(path: bezierPath)
self.lastdrawImage = canvas.image
}
//描画処理
func drawLine(path:UIBezierPath){
UIGraphicsBeginImageContext(canvas)
if let image = self.lastdrawImage {
image.draw(at: CGPoint.zero)
}
let lineColor = UIColor.black
lineColor.setStroke()
path.stroke()
self.canvas.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
//クリアボタンをタップした時の処理
@IBAction func clearbtntap(_ sender: Any) {
print("ボタン押したよ")
lastdrawImage = nil
canvas.image = nil
}
}
class ViewController: UIViewController {
//手描きするためのUIImage
var canvas:UIImageView!
var bezierPath:UIBezierPath!
var lastdrawImage:UIImage?
//クリアにするためのボタン
let clearbtn = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
//ステータスバーの高さ
let statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 30
let screenWidth = self.view.frame.width
let screenHeight = self.view.frame.height
//キャンバスを設置
canvas = UIImageView()
canvas.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)
canvas.backgroundColor = UIColor.clear
self.view.addSubview(canvas)
//クリアーボタン
clearbtn.backgroundColor = UIColor(red: 0, green: 0, blue: 1.0, alpha: 1.0)
clearbtn.frame = CGRect(x:screenWidth/5, y:statusBarHeight + screenHeight/12, width:screenWidth/2/2, height: screenWidth/2/2)
clearbtn.layer.cornerRadius = screenWidth/2/4
clearbtn.addTarget(self, action: #selector(ViewController.clearbtntap(_:)), for: .touchUpInside)
self.view.addSubview(clearbtn)
}
//タッチ開始の際の処理
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchEvent = touches.first!
let currentPoint:CGPoint = touchEvent.location(in: self.canvas)
bezierPath = UIBezierPath()
bezierPath.lineWidth = 10.0
bezierPath.lineCapStyle = .butt
bezierPath.move(to:currentPoint)
}
//タッチ中の処理
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if bezierPath == nil {
return
}
let touchEvent = touches.first!
let currentPoint:CGPoint = touchEvent.location(in: self.canvas)
bezierPath.addLine(to: currentPoint)
drawLine(path: bezierPath)
}
//タッチ終了時の処理
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if bezierPath == nil {
return
}
let touchEvent = touches.first!
let currentPoint:CGPoint = touchEvent.location(in: canvas)
bezierPath.addLine(to: currentPoint)
drawLine(path: bezierPath)
self.lastdrawImage = canvas.image
}
//描画処理
func drawLine(path:UIBezierPath){
UIGraphicsBeginImageContext(canvas)
if let image = self.lastdrawImage {
image.draw(at: CGPoint.zero)
}
let lineColor = UIColor.black
lineColor.setStroke()
path.stroke()
self.canvas.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
//クリアボタンをタップした時の処理
@IBAction func clearbtntap(_ sender: Any) {
print("ボタン押したよ")
lastdrawImage = nil
canvas.image = nil
}
}