お絵描きアプリを作成中なのですが上手く動きません
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 1,231
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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
check解決した方法
0
自己解決しました!
下記3つの処理の中で、
//初回の移動なら最初の中間点まで直線を引く
//2回目以降の移動なら中間点を繋いで曲線を引く
//最後のタッチは、最後の中間点から最終点まで直線を引く
いちいち let で lastPoint や midPoint の変数を定義してたのですが、let を外すと、次の処理まで値が持ち越されるようになり、解決しました!
ということで、以下の理解で合ってるのでしょうか??
let で定義すると、その変数の値は、その関数の中でのみ保持されて、次の関数に持ち越されない。
let をつけずに代入すると、変数の値が次の関数まで持ち越される。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.19%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる