質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • Swift

    8559questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

お絵描きアプリを作成中なのですが上手く動きません

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 554

sgt.kowalski

score 24

iPhoneでタッチでお絵描きが出来るアプリを、swiftで作成中です。
滑らかな線を引くために、以下の処理をしています。

タッチ座標①
↓中間点①
タッチ座標②
↓中間点②
タッチ座標③

タッチ座標間の中間点を計算し、中間点①と中間点②を、タッチ座標②をコントロールポイントとした QuadBezierPath で結びます。

最初の指の移動では、最初にタッチした座標(A)と移動した後の座標(B)しかないので、最初にタッチした座標と(A)(B)の中間点を直線で結びます。
最後の指の移動についても同様で、最後の中間点と最終的に指を離した座標を直線で結びます。

発生している問題・エラーメッセージ

エラーは出ていないのですが、最初のタッチで画面左上の座標(0,0)からタッチしたポイントまでいきなり線が引かれてしまいます。
また、指を離して、次にタッチすると、その2点間にも線が引かれてしまいます。

該当のソースコード

swift3.0で書いてます。

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var imageView: UIImageView!

var lastPoint = CGPoint.zero
var currentPoint = CGPoint.zero
var midPoint1 = CGPoint.zero
var midPoint2 = CGPoint.zero
var swiped = false

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

}

//直線の描画
func drawLines(fromPoint:CGPoint,toPoint:CGPoint){
UIGraphicsBeginImageContext(self.view.frame.size)
imageView.image?.draw(in: CGRect(x:0,y:0,width:self.view.frame.width,height:self.view.frame.height))
let context = UIGraphicsGetCurrentContext()

context?.move(to:CGPoint(x:fromPoint.x,y:fromPoint.y))
context?.addLine(to:CGPoint(x:toPoint.x,y:toPoint.y))
context?.setBlendMode(CGBlendMode.normal)
context?.setLineCap(CGLineCap.round)
context?.setLineWidth(1)
context?.setStrokeColor(UIColor(red:0,green:0,blue:0,alpha:1).cgColor)

context?.strokePath()

imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}

//曲線の描画
func drawCurves(fromPoint:CGPoint,toPoint:CGPoint,controlPoint:CGPoint){
UIGraphicsBeginImageContext(self.view.frame.size)
imageView.image?.draw(in: CGRect(x:0,y:0,width:self.view.frame.width,height:self.view.frame.height))
let context = UIGraphicsGetCurrentContext()

context?.move(to:CGPoint(x:fromPoint.x,y:fromPoint.y))
context?.addQuadCurve(to:CGPoint(x:toPoint.x,y:toPoint.y),control:CGPoint(x:controlPoint.x,y:controlPoint.y))
context?.setBlendMode(CGBlendMode.normal)
context?.setLineCap(CGLineCap.round)
context?.setLineWidth(5)
context?.setStrokeColor(UIColor(red:0,green:0,blue:0,alpha:1).cgColor)

context?.strokePath()

imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}

//タッチスタート
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first{
lastPoint = touch.location(in: self.view)
}
}

//タッチ移動
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first{

//初回の移動なら最初の中間点まで直線を引く
if swiped == false{
let currentPoint = touch.location(in: self.view)
let midPoint1 = CGPoint(x:(lastPoint.x + currentPoint.x)/2,y:(lastPoint.y + currentPoint.y)/2)

drawLines(fromPoint:lastPoint,toPoint:midPoint1)
lastPoint = currentPoint
swiped = true

}else{
//2回目以降の移動なら中間点を繋いで曲線を引く
let currentPoint = touch.location(in: self.view)
let midPoint2 = CGPoint(x:(lastPoint.x + currentPoint.x)/2,y:(lastPoint.y + currentPoint.y)/2)
drawCurves(fromPoint:midPoint1,toPoint:midPoint2,controlPoint:lastPoint)
midPoint1 = midPoint2
lastPoint = currentPoint
swiped = true
}
}
}

//最後のタッチは、最後の中間点から最終点まで直線を引く
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first{
let currentPoint = touch.location(in: self.view)
drawLines(fromPoint: midPoint1, toPoint: currentPoint)
swiped = false

}
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

}

なにぶん初心者なもので、質問の書き方すらよく分かっていないのですが、上記コードのどこに問題があるのか、教えて頂けると幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

自己解決しました!

下記3つの処理の中で、

//初回の移動なら最初の中間点まで直線を引く
//2回目以降の移動なら中間点を繋いで曲線を引く
//最後のタッチは、最後の中間点から最終点まで直線を引く

いちいち let で lastPoint や midPoint の変数を定義してたのですが、let を外すと、次の処理まで値が持ち越されるようになり、解決しました!

ということで、以下の理解で合ってるのでしょうか??

let で定義すると、その変数の値は、その関数の中でのみ保持されて、次の関数に持ち越されない。
let をつけずに代入すると、変数の値が次の関数まで持ち越される。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • Swift

    8559questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています