https://www.bignerdranch.com/blog/uidynamics-in
Transkrypt
https://www.bignerdranch.com/blog/uidynamics-in
https://www.bignerdranch.com/blog/uidynamics-in-swift/ http://www.raywenderlich.com/76147/uikit-dynamics-tutorial-swift http://www.sitepoint.com/using-uikit-dynamics-swift-animate-apps/ Zrób kwadrat import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() zrobBox(CGRectMake(100,100,30,30), kolor: UIColor.redColor()) } func zrobBox(ramka: CGRect, kolor: UIColor) { let b = UIView(frame: location) b.backgroundColor = kolor view.insertSubview(b, atIndex: 0) } } Dodaj składniki klasy: animator i grawitację var animator = UIDynamicAnimator() let gravity = UIGravityBehavior() override func viewDidLoad() { super.viewDidLoad() zrobAnimator() zrobBox(CGRectMake(100,100,30,30)) } // (0,0) jest w lewym górnym wierzchołku ekranu func zrobBox(ramka: CGRect, kolor: UIColor) { let b = UIView(frame: location) b.backgroundColor = kolor view.insertSubview(b, atIndex: 0) gravity.addItem(b) } func zrobAnimator() { animator = UIDynamicAnimator(referenceView: self.view) gravity.gravityDirection = CGVectorMake(0, 0.4) animator.addBehavior(gravity) } } Dodaj collider, na początek obsługa granic widoku let collider = UICollisionBehavior() // składnik klasy w funkcji zróbBox: collider.addItem(b) w funkcji zrobAnimator: collider.translatesReferenceBoundsIntoBoundary = true animator.addBehavior(collider) Dodaj własną granicę do collidera, zrób barierę override func viewDidLoad() { super.viewDidLoad() zrobAnimator() bariera() zrobBox(CGRectMake(130,100,30,30)) // wypróbuj różne wartości x boxa } func bariera() { let bar = UIView(frame: CGRectMake(0,330,140,5)); bar.backgroundColor = UIColor.blueColor() self.view.addSubview(bar) let lewy = CGPointMake(0, 330) let prawy = CGPointMake(140, 330) collider.addBoundaryWithIdentifier("gornaKrawedzBariery", fromPoint: lewy, toPoint: prawy) } Dodaj UIDynamicItemBehaviour - można przypisać różne cechy do dynamicznych elementów: friction - tarcie - liczba rzeczywista z przedziału od 0 do 1, która określa, jak bardzo odporny na ruch produkt będzie, gdy przesuwa się na inne przedmioty lub inne przedmioty przesuń na jego krawędziach. elasticity - liczba rzeczywista z przedziału od 0 do 1, która określa sprężystość kolizji elementu. density - wykorzystywana przez animatora do obliczania masy elementu, domyślnie 1, zakres 0-1 allowsRotation - wartość logiczna, czy produkt może być obracany przez animatora. resistance - opory ruchu, od 0 do CGFLOAT_MAX angularResistance - opory w ruchu obrotowym składnik klasy: let dynamic = UIDynamicItemBehavior() do funkcji zrobAnimator: animator.addBehavior(dynamic) dynamic.friction = 0.1 dynamic.elasticity = 0.9 // wypróbuj inne wartości, np 1.2 do funkcji zrobBox: dynamic.addItem(b) Dodaj detekcję parametrów kolizji: licznik kolizji i identyfikator obiektu kolidującego Klasa VievController musi implementować protokół: UICollisionBehaviorDelegate i zdefiniować delegata do detekcji kolizji (w funkcji zrobAnimator): collider.collisionDelegate = self wówczas można w klasie ViewController zdefiniować licznik kolizji var liczkolizje: Int = 0 i zaimplementować funkcję tego protokołu: func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, atPoint p: CGPoint) { liczkolizje++ print("licznik kolizji = \(liczkolizje) obiekt = \(identifier)”) let v: UIView = item as! UIView let kolor = v.backgroundColor v.backgroundColor = UIColor.yellowColor() UIView.animateWithDuration(1.0, animations: { v.backgroundColor = kolor }) // zapamiętaj jaki był kolor boxa // zmiana koloru przy kolizji } Wiele boxów Nowy składnik klasy ViewController, tablica box-ów. Nowo tworzony box nie może kolidować z żadnym wcześniej utworzonym. W tym celu zapamiętaj wszystkie tworzone boxy w tablicy: var B = [UIView]() Dodaj we funkcji zrobBox: B.append(b) Nowe funkcje func koliduje(ramka: CGRect) -> Bool { for b in B { let r = b.frame; if(CGRectIntersectsRect(ramka, r)) { return true } } return false } func losowyBox() -> CGRect { var box = CGRectZero repeat { let x = CGFloat(arc4random()) % 320 // losuj z szerokości widoku let y = CGFloat(arc4random()) % 400 // losuj z wysokości widoku box = CGRectMake(x, y, 30, 30); } while(koliduje(box)) return box } func losowyKolor() -> UIColor { let red = CGFloat(CGFloat(arc4random()%255)/255); let green = CGFloat(CGFloat(arc4random()%255)/255); let blue = CGFloat(CGFloat(arc4random()%255)/255); return UIColor(red: red, green: green, blue: blue, alpha: 0.85); } Zmiana we funkcji viewDidLoad override func viewDidLoad() { super.viewDidLoad() zrobAnimator() bariera() // zrobBox(CGRectMake(130,100,30,30),kolor: UIColor.redColor()) for _ in 0..<10 { let box = losowyBox() // taka ramka która nie koliduje z innym boxem let kolor = losowyKolor() zrobBox(box, kolor: kolor); } } Jak przerobić kwadraty na kółka we funkcji zróbBox zaokrąglij narożniki tworzonego boxa func zrobBox(ramka: CGRect, kolor: UIColor) { let b = UIView(frame: ramka) b.backgroundColor = kolor b.layer.cornerRadius = 15 // połowa boku kwadratu view.insertSubview(b, atIndex: 0) gravity.addItem(b) collider.addItem(b) dynamic.addItem(b) B.append(b) // tablica boxów, aby wybrać następny box nie kolidujący z dotychczasowymi } Zmień typ granicy stosowanej do detekcji kolizji. Domyślnie jest prostokąt, zmień na elipsę class Kolko: UIView { override var collisionBoundsType: UIDynamicItemCollisionBoundsType { return .Ellipse } } We funkcji zrobBox() zmień klasę tworzonego obiektu, zamiast UIView zrób Kolko // let b = UIView(frame: ramka) let b = Kolko(frame: ramka) W odpowiedzi na touch-dragging zmień wektor grawitacji W Main.storyboard, przeciągnij na widok z Object Library kontrolkę PanGestureRecognizer, z jej ikony zrób akcję: @IBAction func ciagnij(sender: UIPanGestureRecognizer) { // let translation = sender.translationInView(view) let v = sender.velocityInView(view) let dx = 0.01*v.x let dy = 0.01*v.y print(" dx = \(dx) dy = \(dy)") gravity.gravityDirection = CGVectorMake(dx, dy) }