发布于 2016-02-24 05:35:06 | 202 次阅读 | 评论: 0 | 来源: 分享

这里有新鲜出炉的精品教程,程序狗速度看过来!

UIKIt 轻量级的JS的UI框架

UIkit是YOOtheme团队开发的一款轻量级开源的前端框架,可以帮助你快速的开发和创建前端UI界面,支持LESS、模块化、自定义主题、及响应式设计。


创作我们自己的星球大战续集,对于我们最强的两种原力:设计和开发,都是个挑战。

设计星球大战动画

by Kostya Trundayev

在我开始制作动画的时候,我想对标准开关控件创作一种独一无二的交互逻辑,并扩展影响到整个屏幕。我想到了一个有趣的想法,让用户通过点击该开关,进行两种不同的外观的切换。但我该使用什么界面来让两种设定显得有意义呢?

我记得星球大战,尤其是星球大战系列游戏,用户可以加入光明或黑暗的一方。天行者与黑武士。光明与黑暗。没错!这个矛盾人格的想法是多么出色,实在无法用言语形容。

我已经花了几个小时研究界面,我为每个设定档创建了两种图片拼贴,并绘制自己的界面。我使用 Photoshop 创建设定档,然后在 Adobe After Effects 中添加动画。

在两种屏幕都准备好了后,我觉得若发布在 Dribbble 它们看起太朴素了。我瞥了一眼屏幕中的黑武士,我终于想到了!画面中黑武士试图用他的手触碰十字星座。我想,“要是屏幕不只是接近,而是碎成小块,就像被原力击中一样?”这听起来很酷!我研究了在 After Effects 中如何实现,并做出了正如我想象的效果。我使用了粉碎效果,它能让我通过运用许多不同的设置实现摇摇欲坠的效果。

所以,剩下来唯一要做的事情是循环动画,因为该组件在动画结束的后,没有可供用户着陆的屏幕,并且从那里可以通过设定档的设置回到屏幕。这就是为什么我用星球大战标志创建第三个屏幕的原因,一个“设置你的个人资料”的按钮和群星璀璨的天空。我在 CC 球状动作特效的帮助下制作了该星空。

我将视频放入设备模型中,并为 Dribbble 做了个短片。但故事还没有结束。你还是可以学到更多内容的,因为伟大的设计加上天才的开发才是真正的原力觉醒。

使用 Swift 开发星球大战动画

by Artem Sydorenko

有两件事情在星球大战动画中似乎很难实现(在 Github 上浏览):在主屏幕中满天飞的星星和碎成片片的视图。我在 CAEmitterLayer 的帮助下解决了第一个挑战,它是一个提供粒子发射系统的类。然后,我有一段相当艰苦的时间,就是试图将视图破碎的 4000 个碎片以不同的方向降落。

如何将星球大战击成碎片

为了将 UIView 打破成碎片,我用了下面的方法:snapshotViewAfterScreenUpdates()resizableSnapshotViewFromRect (afterScreenUpdates:withCapInsets:)。我也使用了中间快照,它能让我更快创建创建小碎片(从快照创建快照比从原来视图制作非常小的快照要快得多):


let fromViewSnapshot = fromView.snapshotViewAfterScreenUpdates(false)

for x in CGFloat(0).stride(through: size.width, by: width) {
    for y in CGFloat(0).stride(through: size.height, by: height) {

        let snapshotRegion = CGRect(x: x, y: y, width: width, height: height)

        let snapshot = fromViewSnapshot.resizableSnapshotViewFromRect(snapshotRegion, afterScreenUpdates: false, withCapInsets: UIEdgeInsetsZero)

        containerView.addSubview(snapshot)
        snapshot.frame = snapshotRegion
        snapshots.append(snapshot)
    }
}

有 3 种方式可以实现向星球大战那样的动画:通过使用 UIDynamicsCore Animation (UIKit)OpenGL。我们用了全部这些方法来制作了动画,让我们来看看结果。

扩展阅读:如何在 iOSAndroid 上创建铡刀菜单动画。

用 UIDymanics 制作动画

UIDynamics 是我们第一只小白鼠。我认为这个工具可以帮我实现物体自然下落的效果。它是这样子的:


animator = UIDynamicAnimator(referenceView: containerView)
for snapshot in snapshots {                
    let push = UIPushBehavior(items: [snapshot], mode: .Instantaneous)
    push.pushDirection = CGVector(dx: randomFloatBetween(-0.15 , and: 0.15), dy: randomFloatBetween(-0.15 , and: 0))
    push.active = true
    animator.addBehavior(push)
}
let gravity = UIGravityBehavior(items: snapshots)
animator.addBehavior(gravity)

但是事实证明物体物理运动计算是很耗 CPU 的(我们有大量的物体)。我们不得不同时移动 4000 个对象,UIDynamics 很难维持这样的负荷。

下面是我们的计算结果:

使用 UIKit (Core Animation) 制作动画

由于使用 UIDynamics 制作星球大战动画是低效的,我决定使用 UIView 将动画重写一遍:


UIView.animateWithDuration(duration,  animations: {
    for view in snapshots {
        view.frame = view.frame.offsetBy(dx: randomFloatBetween(-200 , and: 200), 
            dy: randomFloatBetween(fromView.frame.height, and: fromView.frame.height * 1.3)
        )
    }
})

在这种情况下,只有当我们将动画切割成碎片 CPU 才受到影响,这样会在动画开始时有个小延迟。但是,由于在 GPU 负荷,FPS(帧每秒)不能同时显示超过 1500 个视图。FPS 会被降到 26,但不能使动画达到我想要的 60 FPS 流畅度。

由于我们仍不能得到满意的结果,我们决定使用 OpenGL 制作星球大战动画。

使用 OpenGL 制作动画

多数 iOS 教程都是用 Objective-C 设计的,所以我决定用它来开始,如果成功实现,我会使用 Swift 再重写一遍动画(我做到了)。

结果是惊人的,我可以在 iPhone 6 上以 60 帧每秒播放视图碎片动画,而且没有任何中断或延迟。

我想:如果我把动画切碎成 40,000 块而不是 4,000 块呢?OpenGL 能应对这种负荷吗?通过实验该数字,我得到了 4 FPS。为了跟踪代码表现不佳的部分,我用 time profiler 来运行动画。这能让我看到负载并显示花费最长时间实现的方法。

在 time profiler 下,动画运行在 23 FPS,但这很容易解释。Time profiler 执行的是发布配置,这意味着它可以优化正在编译的代码。

我重写了关键代码(我将 BlowSprite 的改成结构体并替换了映射周期)后,我可以在发布版本配置上达到 60 FPS。我让动画快了两倍有多!(在没有编译优化的调试配置上, 我得到 11 FPS)。

扩展阅读:如何开发 Android 上的 Instagram 视频

在实现了 3 种类型的动画后,我们可以从下面的统计图看到 UIDynamicsUIKit (Core Animation)OpenGL 的实验结果。只有 OpenGL 动画可以应付负载需求,所以选择他来实现我们的组件。

我们对 CPU 的实验结果如下所示。

在帧每秒的表现上:

如何在你的项目中添加星球大战?

单实现 UIViewControllerTransitioningDelegate 类,可以返回我们的动画构成方法 animationControllerForDismissedController,然后赋值给 viewController 你想排除的 transitioningDelegate


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let destination = segue.destinationViewController
    destination.transitioningDelegate = self
}

func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return StarWarsGLAnimator()
}

如何自定义组件

在星球大战动画中有两件事情你可以自定义:持续时间和碎片尺寸。让我们来看看你可以怎么做。

持续时间的部分代码:


func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    let animator = StarWarsGLAnimator()
    animator.duration = 2
    return animator
}

碎片尺寸,改变各部分点的尺寸:


func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    let animator = StarWarsGLAnimator()
    animator.spriteWidth = 8
    return animator
}

你可以在这些地方查阅我们的星球大战组件:

愿原力与你同在!



最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务