2017-01-10 115 views
0

之前問這個問題,我已經搜查了SO:如何限制視圖/圖層的移動路徑到貝塞爾曲線路徑?

iPhone-Move UI Image view along a Bezier curve path

但它沒有給出明確的答案。我的要求是這樣的,我有一個貝塞爾路徑和一個視圖(或層,如果確定),我想添加pan gesture到視圖,並且視圖(或圖層)的移動路徑必須約束到貝塞爾路徑。

enter image description here

我的代碼如下:

MainDrawView.swift

import UIKit 

class MainDrawView: UIView { 


    // Only override draw() if you perform custom drawing. 
    // An empty implementation adversely affects performance during animation. 
    override func draw(_ rect: CGRect) { 
     // Drawing code 

     drawArc() 
    } 

    func drawArc() { 

     let context = UIGraphicsGetCurrentContext() 

     // set start point 
     context?.move(to: CGPoint.init(x: 0, y: 400)) 
     //draw curve 
     context?.addQuadCurve(to: CGPoint.init(x: 500, y: 250), control: CGPoint.init(x: UIScreen.main.bounds.size.width, y: 200)) 

     context?.strokePath() 

    } 
} 

ViewController.swift

import UIKit 

class ViewController: UIViewController { 

    @IBOutlet weak var clickButton: UIButton! 

    lazy var view1:UIView = { 

     let view: UIView = UIView.init(frame: CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: CGSize.init(width: 10, height: 10))) 
     view.center = CGPoint.init(x: UIScreen.main.bounds.size.width/2.0, y: UIScreen.main.bounds.size.height/2.0) 
     view.backgroundColor = UIColor.red 

     return view 
    }() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     initData() 
     initUI() 
    } 

    func initData() { 

    } 

    func initUI() { 

     self.clickButton.isHidden = true 

     // init the view 
     self.view.addSubview(self.view1) 
    } 

} 

編輯-1

我深需求量的是,當我使用pan guester移動視圖/層,視圖將貝塞爾路徑上移動。

+0

它可以是CALayers嗎?至少在我看來,更容易完成UIViews。一個UIView可以有幾個CALayers。如果這對你有用,我有代碼可以做到這一點。 – dfd

+0

@dfd,好的,使用CALayer也可以實現它。 – aircraft

+0

@aircraft - 那麼我是否正確理解你,你是否想讓用戶激活一個'UIPanGestureRecognizer',並且隨着更新,廣場將沿着路徑移動? – Pierce

回答

1

如果貝塞爾路徑是離線的,那麼你可以找到線的斜率,並且對於x或y中的每個變化,你都可以計算貝塞爾路徑的位置。 var y :Float = (slope * (xPos-previousCoord.x))+previousCoord.y; xPos正在不斷變化。同樣,你可以找到x。對於具有線段的任何封閉形狀,您可以使用它。

但是,如果你需要它的圈子,那麼你需要將笛卡兒轉換爲極地。即...從座標u可以找到角度,然後從該角度,你有半徑,所以通過使用該角度,你需要找到笛卡爾座標。 enter image description here

θ= TAN-1(5/12)

ü需要使用主要3座標之一是圓的中心,第二個是你的觸摸點,最後一個是(touchpoint.x ,centreofcircle.y)。從兩個座標之間的圓計算距離的中心 您有θ和圓的半徑,然後使用

X = R×cos(θ)

Y = R×SIN(θ)

唐找到點不要將圖像中的r誤認爲圓的半徑,圖像中的r是三個座標的斜邊。您應該計算觸摸點中每個x的變化。

希望它有效。但對於不規則的形狀,我不知道如何找到。

+0

我已經嘗試了它的圈子,並能夠限制它。如果你想要我可以給你代碼。 –

+0

我已經通過電子郵件發送了代碼,請檢查並告知我是否需要對該 –

+0

郵件代碼進行任何說明以及plz –

0

這聽起來像你可能需要做一些計算。當您設置的方法來處理UIPanGestureRecognizer,你可以得到一個向量回鍋裏,像這樣:

func panGestureRecognized(_ sender: UIPanGestureRecognizer) { 
    let vector:CGPoint = sender.translation(in: self.view) // Or use whatever view the UIPanGestureRecognizer was added to 
} 

然後,您可以用它來推斷沿x和y軸的運動。我建議首先得到一個代數方程,用於移動視圖的路徑。要沿該線移動視圖,必須能夠計算沿着該線相對於UIPanGestureRecognizer的移動的點,然後使用該線上的計算點更新視圖的位置。

我不知道這是否會爲你想要做什麼工作,但如果你想嘗試沿路徑動畫視圖,它實際上很簡單:

let path = UIBezierPath() // This would be your custom path 

let animation = CAKeyframeAnimation(keyPath: "position") 
animation.path = path.cgPath 
animation.fillMode = kCAFillModeForwards 
animation.isRemovedOnCompletion = false  animation.repeatCount = 0 
animation.duration = 5.0 // However long you want 
animation.speed = 2 // However fast you want 
animation.calculationMode = kCAAnimationPaced 
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 

animatingView.layer.add(animation, forKey: "moveAlongPath")