UIkit Dynamics 投掷效果

图片来源于网络

前言:上章UIKit Dynamics 置身真实世界介绍了基本用法,下面我们继续深入学习——手势跟Dynamics结合的用法

一、触摸处理

1、在ViewController.swift添加以下属性,并在Main.storyboard结合这些属性,在Main.storyboard添加一个imageView,以及扮演redSquareblueSquare的俩个view

    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var redSquare: UIView!
    private var originalBounds = CGRect.zero
    private var orignalCenter = CGPoint.zero
    private var animator: UIDynamicAnimator!
    private var attachmentBehavior: UIAttachmentBehavior!
    private var pushBehavior: UIPushBehavior!
    private var itemBehavior: UIDynamicItemBehavior!

<code>blueSquare</code>将简单地表示您的触摸开始的位置,即您的手指首先与屏幕接触。redSquare会在您的手指移动时跟踪您的手指。
另外,在view添加一个手势识别器(Pan Gesture Recognizer),打开ViewController.swift并将此新方法添加到该文件中:

    @IBAction func handleAttachmentGesture(_ sender: UIPanGestureRcodeecognizer) {
        let location = sender.location(in: view)
        let boxLocation = sender.location(in: imageView)
        
        switch sender.state {
        case .began:
            print("Your touch start position is \(location)")
            print("Start location in image is \(boxLocation)")
        case .ended:
            print("Your touch end position is \(location)")
            print("End location in image is \(boxLocation)")
        default:
            break
        }

    }

在屏幕上滑动或者拖动下,会打印如下

Your touch start position is (73.0, 363.5)
Start location in image is (40.0, 226.5)
Your touch end position is (72.5, 363.0)
End location in image is (39.5, 226.0)

二、UIDynamicAnimator和UIAttachmentBehavior

设置完简单的UI,现在加上Dynamics,使其动态化
首先,我们得让imageView跟随我们的拖动而移动,用到Dynamics中的一个类--UIAttachmentBehavior

打开ViewController.swift并将以下代码放在viewDidLoad()下面

animator = UIDynamicAnimator(referenceView: view)
originalBounds = imageView.bounds
orignalCenter = imageView.center

上面的代码设置了一个UIDynamicAnimator——基于物理动画的UIKit引擎,将视图控制器的视图作为参考视图来定义animator的坐标系。
我们可以添加行为到animator,它允许你做很多事情例如:附着view,推动view,使他们受重力的影响,等等。

请在handleAttachmentGesture(sender:)中的case .began:两个print语句下方添加以下代码

    //1
    animator.removeAllBehaviors()
    //2
    let centerOffset = UIOffset(horizontal: boxLocation.x - imageView.bounds.midX, vertical: boxLocation.y - imageView.bounds.midY)
    attachmentBehavior = UIAttachmentBehavior(item: imageView, offsetFromCenter: centerOffset, attachedToAnchor: location)
    //3
    redSquare.center = attachmentBehavior.anchorPoint
    blueSquare.center = location
    //4
    animator.addBehavior(attachmentBehavior)

我们先来看看上面代码👆:

1、首先删除可能存在的任何现有的动画行为。
2、接下来,您创建一个UIAttachmentBehaviorimageView的点附加到用户点击锚点(恰好相同点)的位置。稍后,您将更改锚点,这将导致imageView移动。
将锚点连接到视图就像安装一个不可见的杆,将锚点连接到视图上的固定附件位置。
3、更新红色方块以指示锚点,蓝色方块表示imageView中附加的点。当手势开始时,这些将是相同的点。
4、将此行为添加到animator,使其生效。

接下来你需要告诉锚点本身跟随你的手指.将下列代码替换defaultbreak语句

  attachmentBehavior.anchorPoint = sender.location(in: view)
  redSquare.center = attachmentBehavior.anchorPoint

拖拽完之后,最好imageView可以回到初始位置,所以我们写一个方法func resetPosintion()

func resetPosintion() {
    animator.removeAllBehaviors()
    
    UIView.animate(withDuration: 0.45) { 
        self.imageView.bounds = self.originalBounds
        self.imageView.center = self.orignalCenter
        self.imageView.transform = CGAffineTransform.identity
    }
}

接着把 resetPosintion()放入handleAttachmentGesturecase .ended:print语句下面
效果如下:


但是很明显,我们一放开拖动,imageView马上回到原始位置,显然我们更希望手拖动后,存在惯性,还可以移动一段距离,为了解决这个问题,继续下面的学习

三、UIPushBehavior

在停止拖动时分离视图,并赋予动量,使其在运动时释放时可以继续其轨迹
首先,添加两个常量到顶部:

let ThrowingThreshold: CGFloat = 1000
let ThrowingVelocityPadding: CGFloat = 35

<code>ThrowingThreshhold</code>指示视图必须移动多快以使视图继续移动(而不是立即返回到原始位置)。ThrowingVelocityPadding是一个魔法常数,影响运动多快或者多慢(这是通过反复试验选择的)。

替换上面的case.end :resetPosintion()

// 1
let velocity = sender.velocity(in: view)
let magnitude = sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y))

if magnitude > ThrowingThreshold {
    // 2
    let pushBehavior = UIPushBehavior (items: [imageView], mode: .instantaneous)
    pushBehavior.pushDirection = CGVector(dx: velocity.x / 10, dy: velocity.y / 10)
    pushBehavior.magnitude = magnitude / ThrowingVelocityPadding
    
    self.pushBehavior = pushBehavior
    animator.addBehavior(pushBehavior)
    
    // 3
    let angle = Int(arc4random_uniform(20)) - 10
    
    itemBehavior = UIDynamicItemBehavior(items: [imageView])
    itemBehavior.friction = 0.2
    itemBehavior.allowsRotation = true
    itemBehavior.addAngularVelocity(CGFloat(angle), for: imageView)
    animator.addBehavior(itemBehavior)
    
    // 4
    let timeOffset = Int64(0.4 * Double(NSEC_PER_SEC))
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(timeOffset) / Double(NSEC_PER_SEC)) {
        self.resetPosition()
    }
} else {
  resetPosition()
}

我们先来看看这一节:

1、询问手势的拖动速度。
使用速度和你的老朋友毕达哥拉斯定理,你可以计算速度的大小 - 这是由x方向速度和y方向速度形成的三角形的斜边。

2、假设手势幅度超过为动作设置的最小阈值,则设置推送行为。
推动行为对指定的项目施加力。
在这种情况下,它是对图像的瞬时力量。
期望的方向由转换为给出方向部分的向量的x和y速度组成。
一旦设置了推动行为,就将其添加到动画序列中。

4、在指定的时间间隔之后,动画会通过将图像发送回目的地重置,因此它会拉出并返回屏幕 - 就像一个球从墙上弹起!
效果如下:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容