今Swiftお絵かきアプリを作ろうと試行錯誤しているのですが、
肝心の描画部分のサンプルがあまりなかったので、
Objective-Cで実装しているこちらの記事をSwift化してみました。
ただし、undo,redo,クリアはボタンではなくtableViewで実装しています。
変数宣言
必要な変数を宣言します。
lastDrawImage以下の変数も最初はnilであるため、Implicitly Unwrapped Optionalを示すエクスクラメーションマーク(!)を付けます。
lastDrawImage, bezierPathは処理中にnilである場合があるので、
厳密にはクエスチョンマーク(?)のほうがいいかもしれません。
class MainViewController: UIViewController, UIScrollViewDelegate, UITableViewDataSource, UITableViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet weak var canvas: UIImageView! @IBOutlet weak var toolBar: UITableView! var lastDrawImage: UIImage! var bezierPath: UIBezierPath! var undoStack: NSMutableArray! var redoStack: NSMutableArray!
初期化
ViewWillApperで初期化を行います。
/** * View初期表示時の処理 */ override func viewWillAppear(animated: Bool) { undoStack = NSMutableArray() redoStack = NSMutableArray() }
タッチ時の処理
/** * タッチ開始時の処理 */ override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { let touch = touches.anyObject() as UITouch let currentPoint:CGPoint = touch.locationInView(canvas) bezierPath = UIBezierPath() bezierPath.lineCapStyle = kCGLineCapRound bezierPath.lineWidth = 1.0 bezierPath.moveToPoint(currentPoint) } /** * タッチ移動時の処理 */ override func touchesMoved(touches: NSSet, withEvent event: UIEvent) { if bezierPath == nil { return } let touch = touches.anyObject() as UITouch let currentPoint:CGPoint = touch.locationInView(canvas) bezierPath.addLineToPoint(currentPoint) drawLine(bezierPath) } /** * タッチ終了時の処理 */ override func touchesEnded(touches: NSSet, withEvent event: UIEvent) { if bezierPath == nil { return } let touch = touches.anyObject() as UITouch let currentPoint:CGPoint = touch.locationInView(canvas) bezierPath.addLineToPoint(currentPoint) drawLine(bezierPath) lastDrawImage = canvas.image undoStack.addObject(bezierPath) redoStack.removeAllObjects() } /** * 描画処理 */ func drawLine(path:UIBezierPath) { UIGraphicsBeginImageContext(canvas.frame.size) if lastDrawImage != nil { lastDrawImage.drawAtPoint(CGPointZero) } var blackColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1) blackColor.setStroke() path.stroke() canvas.image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() }
やっていることはObjective-C版と同じなので特に言うことはありませんが、
UIColorの初期化に引数が必要になったところだけ違います。
ていうかBezierってことはまさにベジェ曲線なんですかね。
昔イラレで死ぬほど触りましたが、今度はプログラムで触ることになるとは。
こちらの記事のようにコントロールポイントも指定できるようなので、スムージングとか色々できそうですね。
undo, redo, クリア
ここはObjective-C版と異なり、クリア処理もundoできるようにしようとundoStackに”clear”文字列を入れたりしているのですが、
まだ処理が甘々なのでうまく動作していません。(redoは無視してるし)
func undo() { let undoPath: AnyObject? = undoStack.lastObject undoStack.removeLastObject() redoStack.addObject(undoPath!) lastDrawImage = nil canvas.image = nil for path in undoStack { if path is NSString { lastDrawImage = nil } else { drawLine(path as UIBezierPath) lastDrawImage = canvas.image } } } func redo() { let redoPath: UIBezierPath = redoStack.lastObject as UIBezierPath redoStack.removeLastObject() undoStack.addObject(redoPath) for path in undoStack { drawLine(path as UIBezierPath) lastDrawImage = canvas.image } } func clear() { lastDrawImage = nil canvas.image = nil undoStack.addObject("clear"); } // table view delegate var texts = ["undo", "redo", "clear"] func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return texts.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell") cell.textLabel?.text = texts[indexPath.row] return cell } func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { if indexPath.row == 0 { if undoStack.count > 0 { undo() } } else if indexPath.row == 1 { if redoStack.count > 0 { redo() } } else if indexPath.row == 2 { clear() } }
お絵かきアプリを作るにあたっての検討事項
これでタッチで描画ができるようにはなったのですが、
アプリに仕上げていくには色々と追加すべきものがあります。
優先順位順に上げていくと…
- 拡大、縮小、スクロール
- 保存処理
- ペンのプロパティ変更
- 消しゴム
- レイヤー
- 透明度
などなど。
iOS開発初心者、Swift初心者の自分がどこまで実装できるか、やるだけやってみます。
コメント
[…] 今回は全体コードは割愛させていただきます。 参考サイト [iOSアプリ開発] タッチでお絵かきしてみる をSwift化 [iOSアプリ開発] タッチでお絵かきしてみる [Swift] 画像をドラッグ […]