CALayerで丸、CATextLayerで番号を描き、タッチで選択して2つを同時に動かしたい。
しかし、なぜか先にCATextLayerの番号が選択されて、番号だけが動きます。
CALayerの丸を選択して動かすと番号の方も動きます。
重なっているレイヤの内、CALayerの丸の方を先に選択できれば解決すると思いますが、方法がわかりません。
CALayerを優先して選択する方法を教えて下さい。
self.addSublayer(textLayer)とself.addSublayer(ovalShapeLayer)の順番を変えても結果は同じでした。
どなたかご教授ください。
ViewController
1import UIKit 2 3class ViewController: UIViewController,UIGestureRecognizerDelegate { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 effectiveScale = 1.0 //現在のスケールを初期化 8 //MARK:- ボタンの設置 9 let width = self.view.bounds.width 10 let height = self.view.bounds.height 11 //丸ボタンを生成 12 let ovalBtn = UIButton() 13 ovalBtn.frame = CGRect(x: 0, y: 0, width: 100, height: 50) 14 ovalBtn.center = CGPoint(x: width/3, y: height-30) 15 ovalBtn.addTarget(self, action: #selector(self.ovalBtnTapped(sender:)), for: .touchUpInside) 16 ovalBtn.setTitle("丸",for:.normal) 17 ovalBtn.backgroundColor = UIColor.green 18 self.view.addSubview(ovalBtn) 19 //四角を生成するボタン 20 let rectBtn = UIButton() 21 rectBtn.frame = CGRect(x:0,y:0,width:100,height:50) 22 rectBtn.center = CGPoint(x:width * 2 / 3,y:height - 30) 23 rectBtn.addTarget(self, action: #selector(ViewController.rectBtnTapped(sender:)), for: .touchUpInside) 24 rectBtn.setTitle("四角",for:.normal) 25 rectBtn.backgroundColor = UIColor.red 26 self.view.addSubview(rectBtn) 27 //ピンチ時の処理 28 let pinch = UIPinchGestureRecognizer() 29 pinch.addTarget(self,action:#selector(ViewController.pinchGesture(sender:))) 30 pinch.delegate = self 31 self.view.addGestureRecognizer(pinch) 32 } 33 34 @objc func ovalBtnTapped(sender:UIButton){ 35 //丸を描く @objcを付けられたメソッド、プロパティにはSwiftの実装に加え、Objective-Cで用いられるふたつの隠し引数を持った関数を同時に作成するようになります。このことで@objcを付けたメソッド、プロパティはObective-Cからも正しく利用することができるようになります。 36 let oval = MyShapeLayer() 37 oval.frame = CGRect(x:100,y:100,width:30,height:30) 38 oval.drawOval(lineWidth:1) 39 self.view.layer.addSublayer(oval) 40 } 41 @objc func rectBtnTapped(sender:UIButton){ 42 //四角を描く 43 let rect = MyShapeLayer() 44 rect.frame = CGRect(x:40,y:40,width:50,height:50) 45 rect.drawRect(lineWidth:1) 46 self.view.layer.addSublayer(rect) 47 } 48 49 //MARK:- タッチした時 50 //選択したレイヤーをいれておく 51 private var selectLayer:CALayer! 52 //最後にタッチされた座標をいれておく 53 private var touchLastPoint:CGPoint! 54 55 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 56 selectLayer = nil //すでに選択されたあレイヤがあるかもしれないのでnilとしておく 57 let touch : UITouch = touches.first! //touches.first! はタッチをしたことを取得 58 let layer:CALayer = hitLayer(touch: touch)//後で作る関数 タッチされた場所にあるレイヤを取得 59 let touchPoint:CGPoint = touch.location(in: self.view) //タッチされた座標を取得 60 touchLastPoint=touchPoint //最後にタッチされた場所の座標を入れておく 61 self.selectLayerFunc(layer:layer) //選択されたレイヤをselectLayerに入れる 62 } 63 64 //MARK:- タッチをした場所にあるレイヤーを取得するhitLayer(touch:)を作成 65 //座標を変換してレイヤーを返却しています。 66 //returnのhitTest部分で座標上にあるレイヤーを取得しています。 67 func hitLayer(touch:UITouch) -> CALayer{ 68 print("hitLayer") 69 var touchPoint:CGPoint = touch.location(in:self.view) 70 touchPoint = self.view.layer.convert(touchPoint, to: self.view.layer.superlayer) 71 return self.view.layer.hitTest(touchPoint)! 72 } 73 74 //MARK:- 選択されたレイヤーをselectLayerに入れている部分 75 //タッチした座標に、view上でのせているレイヤーがない場合はselectLayerにnilをいれ、CALayerがあった場合にはそのレイヤーをそのレイヤーを格納しています。 76 func selectLayerFunc(layer:CALayer?) { 77 if((layer == self.view.layer) || (layer == nil)){ 78 selectLayer = nil 79 print("空振り、なにもないところをタッチした") 80 let oval = MyShapeLayer() 81 oval.frame = CGRect(x:touchLastPoint.x-15,y:touchLastPoint.y-15,width:30,height:30) 82 oval.drawOval(lineWidth:1) 83 self.view.layer.addSublayer(oval) 84// selectLayer = // 怪しい 85 return 86 } 87 selectLayer = layer 88 print("レイヤをタッチした") 89 } 90 91 //MARK:- タッチが動いた時 92 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 93 let touch:UITouch = touches.first! 94 let touchPoint:CGPoint = touch.location(in: self.view) 95 //直前の座標との差を取得 96 let touchOffsetPoint:CGPoint = CGPoint(x:touchPoint.x - touchLastPoint.x, 97 y:touchPoint.y - touchLastPoint.y) 98 touchLastPoint = touchPoint 99 100 if (selectLayer != nil){ 101 //hitしたレイヤーがあった場合 102 let px:CGFloat = selectLayer.position.x 103 let py:CGFloat = selectLayer.position.y 104 //レイヤーを移動させる 105 CATransaction.begin() 106 CATransaction.setDisableActions(true) 107 selectLayer.position = CGPoint(x:px + touchOffsetPoint.x,y:py + touchOffsetPoint.y) 108 selectLayer.borderWidth = 3.0 109 selectLayer.borderColor = UIColor.green.cgColor 110 CATransaction.commit() 111 112 } 113 } 114 //タッチを終えた時 115 override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 116 if(selectLayer != nil){ 117 selectLayer.borderWidth = 0 118 } 119 } 120 //タッチがキャンセルされた時 121 override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { 122 if(selectLayer != nil){ 123 selectLayer.borderWidth = 0 } 124 } 125 126 private var beginGestureScale:CGFloat! //ピンチ後のスケール 127 private var effectiveScale:CGFloat! //現在のスケール 128 129 //ピンチインアウトをした時によばれる。アクションの中にレイヤーを変形するコードをかきます。 130 @objc func pinchGesture(sender:UIPinchGestureRecognizer){ 131 effectiveScale = beginGestureScale * sender.scale 132 //選択されてるやつだけ 133 if (selectLayer != nil){ 134 selectLayer.setAffineTransform(CGAffineTransform(scaleX: effectiveScale,y:effectiveScale)) 135 } 136 } 137 //ピンチが始まった時に、現在のスケールをbeginGestureScaleにいれておきます 138 func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 139 if(gestureRecognizer.isKind(of:UIPinchGestureRecognizer.self)){ 140 beginGestureScale = effectiveScale 141 } 142 return true 143 } 144} 145
MyShapeLayer
1import UIKit 2 3class MyShapeLayer: CALayer { 4 //四角を描く関数 - CALayerの上に、そのCALayerのサイズと同じサイズのCAShapeLayerをのせています。 5 func drawRect(lineWidth:CGFloat){ 6 let rect = CAShapeLayer() 7 rect.strokeColor = UIColor.black.cgColor 8 rect.fillColor = UIColor.clear.cgColor 9 rect.lineWidth = lineWidth 10 rect.path = UIBezierPath(rect:CGRect(x:0,y:0,width:self.frame.width,height:self.frame.height)).cgPath 11 self.addSublayer(rect) 12 } 13 14 15 //丸を描く関数 - CALayerの上に、そのCALayerのサイズと同じサイズのCAShapeLayerをのせています。 16 func drawOval(lineWidth:CGFloat){ 17 let ovalShapeLayer = CAShapeLayer() 18 ovalShapeLayer.strokeColor = UIColor.blue.cgColor 19 ovalShapeLayer.fillColor = UIColor.clear.cgColor 20 ovalShapeLayer.lineWidth = lineWidth 21 ovalShapeLayer.path = UIBezierPath(ovalIn: CGRect(x:0, y:0, width:self.frame.width, height: self.frame.height)).cgPath 22 //番号を表示 23 let textLayer = CATextLayer() 24 textLayer.string = "999" 25 textLayer.foregroundColor = UIColor.green.cgColor 26 textLayer.fontSize = 10 27 textLayer.frame = CGRect(x:1,y:1,width:self.frame.width, height: self.frame.height) 28 29 self.addSublayer(textLayer) 30 self.addSublayer(ovalShapeLayer) 31 32 } 33 34} 35
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/01/26 08:48 編集