Core Animation

Views vs. layers

A layer is a simple model class that exposes a number of properties to represents some image-based content. Every UIView is backed by a layer, so you can think of layers as the lower-level behind the scenes class behind your content.

A layer is different from a view(with respect to animations) for the following reasons:

  • A layer is a model object – it exposes data properties and implements
    no logic. It has no complex Auto Layout dependencies nor does it
    handle user interactions.
  • It has pre-defined visible traits – these traits are a number of data
    properties that affect how the contents is rendered on screen, such
    as border line, border color, position and shadow.
  • Finally, Core Animation optimizes the caching of layer contents and
    fast drawing directly on the GPU.

If you need to choose between views and layers here is my tip: choose view animations any time you can to do the job; you will know when you need more performance or flexibility and have to switch to layer animations instead.

Don’t stress yourself about it though, because you can mix and match view and layer animations freely.

Animatable properties in CALayer

Position and size

  • bounds: modify this to animate the bounding frame of the layer
  • position: modify this to animate the position of the layer within its parent layer. You can animate position.x or position.y separately if you want to control movement on only one axis.
  • transform: modify this to move, scale, and rotate the layer.

Border

  • borderColor: modify this to change the border tint.
  • borderWidth: modify this to grow or shrink the width of the border.
  • cornerRadius: modify this to change the radius of the layer’s rounded
    corners.

Shadow

  • shadowOffset: modify this to make the shadow appear closer to or
    further away from the layer.
  • shadowOpacity: modify this to make the shadow fade in or out.
  • shadowPath: modify this to change the shape of the layer’s shadow.
    You can make different 3D effects to make your layer look like it’s
    floating with different shadow shapes and positions.
  • shadowRadius: modify this to control the blur of the shadow; this is
    especially useful when simulating movement of the view towards or
    away from the surface where the shadow is cast.

Contents

  • contents: modify this to assign raw TIFF or PNG data as the layer
    contents.
  • mask: modify this to establish the shape or image you’ll use to mask
    the visible contents of the layer.
  • opacity – animate the transparency of the layer contents.

CABasicAnimation

Animation objects in Core Animation are simply data models; you create an instance of the model and set its data properties accordingly. Animations are executed based on the properties of the animation objects.

An instance of CABasicAnimation describes a potential layer animation: one that you might choose to run now, at a later time, or not at all.

Since the animation isn’t bound to a specific layer, you can re-use the animation on other layers and each layer will run a copy of the animation independently.

addAnimation(_:forKey:) makes a copy of the animation object and tells Core Animation to run it on the layer. The key argument is for your use only; it lets you identify the animation later on if you need to change or stop the animation.

The beginTime property of CABasicAnimation sets the absolute time the animation should start; you can get the current time with CACurrentMediaTime() and add to it the desired delay in seconds.

Animations vs. real content

When you animate a text field for example, you’re not actually seeing the field itself animated; instead, you’re seeing a cached version of it known as the presentation layer. The presentation layer by default is removed from the screen once the animation completes and the original layer shows itself again.

When the animation starts, a pre-rendered animation object replaces the field and the original text field is temporarily hidden:

You can’t tap the animated field, enter any text or engage any other specific text field functionality, because it’s not the real text field, just a “phantom” visible representation.

By default, as soon as the animation completes, it disappears from the screen and the original
text field is un-hidden.

Using fillMode

The fillMode property lets you control the behavior of your animation at the beginning and end of its sequence. It can has four options:

  • kCAFillModeRemoved: default value. This starts the animation at the defined beginTime – or instantly, if you haven’t set a beginTime – and removes layer change from the screen when the animation completes.

    这里写图片描述

  • kCAFillModeBackwards: display the first frame of your animation instantly on the screen, regardless of the actual start time of the animation, and starts the animation at a later time or instantly.

    这里写图片描述

  • kCAFillModeForwards: play the animation as usual, but retains the final frame of the animation on the screen until you remove the animation.In addition to setting kCAFillModeForwards, you’ll need to make some other changes to the layer to get the last frame to “stick” – we’ll get there later.

    这里写图片描述

  • kCAFillModeBoth: kCAFillModeBoth is a combination of kCAFillModeForwards and kCAFillModeBackwards; as you’d expect, this makes the first frame of the animation appear on the screen immediately and retains the final frame on the screen when the animation is finished.

    这里写图片描述

Make it real after animation completes

removedOnCompletion is true by default, so the animation disappears as soon as it completes. Setting it to false and combining it with the proper fillMode keeps the animation on the screen – and visible as well.

Once you remove a layer animation from the screen, the layer falls back to its current values for position and other properties. This means that you’ll usually need to update the properties of your layer to reflect the final values of your animation.

Although you know how removedOnCompletion works when set to false, you should try to avoid it whenever possible. Leaving animations on the screen is a drag on performance, so you’ll let them be removed automatically and just update the original layer’s position instead.

Animation Keys and Delegates

One of the tricky parts about UIKit animations and the corresponding closure syntax is that once you create and run a view animation you can’t pause it, stop it, or access it in any way.

With Core Animation, however, you can easily inspect animations that are running on a layer and stop them if you need to.

Furthermore, you can even set a delegate object on your animations and react to animation events. In contrast to the completion block you’ve seen in UIView animations, you can receive delegate callbacks for when an animation begins and ends (or is interrupted).

Introducing animation delegates

CAAnimation and its subclass CABasicAnimation implement the delegate pattern and let you respond to animation events.

CAAnimation doesn’t have a specific protocol that its delegates must implement; rather, every instance of NSObject already implements the following two animation delegate methods that you can override as needed:

func animationDidStart(anim: CAAnimation!)
func animationDidStop(anim: CAAnimation!, finished flag: Bool)

This isn’t the usual way of handling delegation in UIKit or Cocoa, but in this case this is just the way things work. Check the headers of the CoreAnimation module and you’ll see that it defines the two above delegate methods in an extension to NSObject.

Key-value coding compliance

The CAAnimation class and its subclasses are key-value coding compliant, which means you can treat them like dictionaries and add new properties to them at run time.

Animation Keys

You’ve probably noticed that addAnimation(_:key:) has two parameters; so far, you’ve only been using the first to pass in the animation object itself.

The key parameter is a string identifier that lets you access and control the animation after it’s been started.

You can call animationKeys() on the layer to get all animation keys on the layer. Once you know which animations are running, you can do several things with them:

  1. Call removeAllAnimations() on the layer to stop all running
    animations or removeAnimationForKey(_:) to remove just one.
  2. Enumerate over the list of animations returned by animationKeys().
    The animation objects are immutable, so you can’t modify the
    animation while they’re in progress.
  3. Fetch an animation by key using animationForKey(_:). As before, the
    returned animation object will be immutable.

Groups and Advanced Timing

When some animations need to work in step with each other with the same duration, beginTime, fillMode and so on, you can use CAAnimatioinGroup to group them, and set the properties for that group only once rather to set them separately.

Grouping animations results in simplified code, and ensures that all your animations will synchronize as one, solid unit.

CAAnimationGroup inherits from CAAnimation, so you can work with the same properties you already know and love such as beginTime, duration, fillMode, delegate, and removedOnCompletion.

Since these values will be the same for all animations in the group, you’ll set them on the group as a whole instead of on each animation separately.

To group animations, you simply add them to an array and assign that array as the value of the animations property of the group, just as you would with an ordinary CABasicAnimation.

Note: Since animations is an immutable array, you can’t add the animations one by one; you need to create them all first and then assign them in the array all at once.

Animation easing

CAMediaTimingFunction has a few pre-defined easing functions, which you can use by name:

  • kCAMediaTimingFunctionLinear runs the animation with an equal pace throughout its whole duration.
  • kCAMediaTimingFunctionEaseIn alters the animation so it starts slower and finishes at a faster pace.

这里写图片描述

  • kCAMediaTimingFunctionEaseOut produces the opposite effect of kCAMediaTimingFunctionEaseIn; the animations starts out faster and slows down as it finishes.

这里写图片描述

  • kCAMediaTimingFunctionEaseInEaseOut slows the animation in the beginning and at the end, but increases the pace during the middle section.

这里写图片描述

Setting timingFunction of a CAAnimation object to make layer animations easing.

animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)

More timing options

  • repeatCount lets you repeat your animation a specified number of times. You can run half an animation cycle, for example, set the repeatCount to 2.5.
  • If you want to set the total repeat time in seconds, instead of setting the number of repeats, use the repeatDuration property instead of repeatCount.
  • autoreverse property can make the animation to reverse. If it is true, then a whole cycle of the animation counts as one time.
  • You can set the speed property of CALayer or CAAnimation to control the duration of an animation.When speed for a CAAnimation set to 2.0, if the animation duration is set to 5 seconds, the animation will complete in just 2.5 seconds since it runs at double the speed.You can set the speed of an animation on its own, but you can also set the speed of a layer as well. The layer conforms to the same timing protocol as an animation.
  • Speeds multiply hierarchically. First if you set a speed of 2.0 on the layer, and then you set the speed of an animation on the layer to 2.0 as well! You end up with the animation running at 2.0 x 2.0 = 4.0 times the normal speed.Just for fun, you can make everything on the screen run super fast by adjusting the speed property of the top-level view controller’s layer.

Keyframe Animations & Struct Properties

Keyframe animations on layers are a bit different than view keyframe animations. View keyframe animations are a simple way to combine independent simple animations together; they can animate different views and properties, and the animations can overlap or have gaps in between.

In contrast, CAKeyframeAnimation lets you animate a single property on a given layer. You can define different key points of the animation, but you can’t have any gaps or overlaps in your animation. Even though that sounds restrictive at first, you can create some very compelling effects with CAKeyframeAnimation.

Think for a moment how a basic animation works. Using fromValue and toValue, Core Animation progressively modifies a particular layer property between those values over a specified duration.

While CAKeyframeAnimation uses an array named values, instead of fromValue and toValue. The elements of values are the measured milestones of your animation. You’ll also need to supply the time that the animation should reach each value’s key point.

In essence, animating layers with keyframes requires you to provide key values for the property you’re animating, along with a corresponding number of number of relative key times that progress between 0.0 and 1.0.

Animating struct values is almost the same as the object values, except that you can not set the fromValue or toValue or values to the struct straightly, you should box that struct value in a NSValue object before you assign it.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值