使用CAReplicatorLayer创建动画

在网上看到了这篇文章,写得很好,于是便把它翻译出来,这是我第一次翻译,翻得不好请轻喷,毕竟6级都没过的孩子,苦逼啊。
原文链接:http://www.ios-animations-by-emails.com/posts/2015-march#tutorial

这是2015年3月的iOS动画,这个教程将引导您通过使用CAReplicatorLayer创建很酷的动画。你可能从来没有听说过CAReplicatorLayer,那是一个很酷难以理解但强大的CoreAnimation类。
我想借此机会感谢大家谁不停地传播这个词iOS Animations by Emails ,并帮助这最后的一个月中我们的动画界近1,000强劲增长。非常感谢所有谁Tweet宣传我的书的iOS动画教程所 -你们是最棒的!
我希望,当你通过这个月的教程中看到你会很高兴,我把我的甜蜜的时间来准备这些:]享受!

                                    ——- 马林托多罗夫

教程:创建动画与CAReplicatorLayer

-本教程是专为Xcode的6.1.1或兼容的版本。

当我正在iOS的动画教程由 CAReplicatorLayer在我的头脑和我的主题列表了。然而,当我们的计划书,我们意识到并非所有的图层将使其在和CAReplicatorLayer被留下(他一生的故事!)。
然而,这一个月的通讯是所有关于CAReplicatorLayer,我敢肯定,这将让我的技术编辑这本书富特顿很高兴。
在本教程中我将指导您完成创建3个不同的电源动画使用CAReplicatorLayer。
我们将从模仿内置在iOS的音乐中得音量振动条(原文“volume bars”)来开始这个教程。

第二步你将继续创建一个自定义的活动指示灯,最后您将创建一个动画来呈现raywenderlich.com在屏幕上的标志在一个不寻常的方式:

1.基本复制动画

CAReplicatorLayer是一个容器层-你添加内容到其中让复制图层复制其中内容。如果你把一个单一的形状-在复制层将显示在屏幕上几种形状。
很酷的是你可以预先设定复制多少几何图形并且设定副本之间的距离,透明度或颜色都可以发生变化。因此您可以创建很酷的动画效果。
在本教程的第一部分,你会从iOS的音乐应用程序山寨动画:


这个动画设有一个上下移动的红色矩形。副本之间存在位置和时间偏移。让我们开始吧!

创建一个新的Xcode项目,并选择单一视图模板(Single View template)。保存项目后打开ViewController.swift
viewDidLoad中()添加以下代码 :

func animation1() {

}

并添加了一个空方法在ViewController

func animation1() { 

}

让我们开始创建复制层,添加方法 animation1()

let r = CAReplicatorLayer() 
r.bounds = CGRect(x: 0.0, y: 0.0, width: 60.0, height: 60.0) 
r.position = view.center 
r.backgroundColor = UIColor.lightGrayColor().CGColor 
view.layer.addSublayer(r)

这段代码创建了一个CAReplicatorLayer的实例并且设置其边界和位置。为了确定它在哪儿,我们得给它一个浅灰色的背景颜色,然后将其添加到视图控制器的视图层。
现在运行应用程序,你会看到屏幕出现一条浅灰色的方形:


现在,让我们创建的第一个矩形(也可以说成是原始的矩形),在animation1()中添加代码

let bar = CALayer() 
bar.bounds = CGRect(x: 0.0, y: 0.0, width: 8.0, height: 40.0) 
bar.position = CGPoint(x: 10.0, y: 75.0) 
bar.cornerRadius = 2.0 
bar.backgroundColor = UIColor.redColor().CGColor 
r.addSublayer(bar)

这段代码创建一个红色的圆角矩形,并将其定位在复制层的左侧。运行应用程序在看效果:

红色的圆角矩形出现在复制层外面,因为我们会让他上下移动。该动画的起始位置是复制界限之下 - 这就是为什么矩形似乎有点“偏”。
说到动画,接下来添加动画代码如下:

let move = CABasicAnimation(keyPath: "position.y") 
move.toValue = bar.position.y - 35.0 
move.duration = 0.5 
move.autoreverses = true 
move.repeatCount = Float.infinity 
bar.addAnimation(move, forKey: nil)

这将使红条反复的上下移动,这是一个很好的开始,虽然它看起来并不令人印象深刻,现在你是在事实上几乎已经准备好与你最终的动画!
接着来复制!添加以下代码:

r.instanceCount = 3

这告诉你想在屏幕上现实内容的3份拷贝(包括原来的)。如果你运行应用程序,当让,现在你将不会看到任何变化,因为所有的3份拷贝都出现在相同的位置,并在同一时间进行同一动画。为了到达效果我们给每个拷贝加上向右的偏移:

r.instanceTransform = CATransform3DMakeTranslation(20.0,0.0,0.0)

这段代码告诉复制图层执行怎样的变换到内容。您可以设置instanceTransform的值为偏移20每一个,当您运行的应用程序,你应该可以看到3红柱彼此相邻:

原来的红色条和两个克隆都动画都在上下往复运动,酷!最后一步,以实现期望的动画效果是给每个条一比特延迟,使它们不会在一致地移动。加入一个代码最后一行:

r.instanceDelay = 0.33

instanceDelay是时间偏移复制图层渲染。动画将分别会有0.33s延迟0.66s的延迟。
运行应用程序并检查结果 - 你应该看到矩形跳来跳去,就像在原来的动画。
最后,你需要做两个快速的变化:

  • 让红色矩形只显示在灰色矩形里面的内容;
r.masksToBounds = true

  • 删除backgroundColor

如果你想不同的动画就去改变instanceCountinstanceTransforminstanceDelay。很酷,不是吗?

2.活动指示灯

记者我们来做更复杂的复制动画!切换到到viewDidLoad方法中()
替换animation1():

animation2()

正如你想得一样,下一个步骤就是添加一个空的方法:

func animation2(){ 

}

在这部分教程你要创建活动指示器。为了好玩,我们将创建一个比内置的iOS的活动指示器更精细的动画。
首先添加一个复制图层到视图控制器,加入到animation2()

let R = CAReplicatorLayer()
r.bounds = CGRect(0.0,0.0,200.0,200.0)
r.cornerRadius = 10.0 
r.backgroundColor = UIColor(white:0.0,alpha:0.75).CGColor 
r.position = view.center 
view.layer.addSublayer(r)

然后以完全相同的方式添加一个空的复制层灰色背景。这会让我们背景颜色来模拟一个HUD的活动。
接下来添加绘制一个白色矩形屏幕上的一个简单的一层:

let dot = CALayer()
dot.bounds = CGRect(0.0,0.0,14.0,14.0)
dot.position = CGPoint(100.0,40.0)
dot.backgroundColor = UIColor(whilte:0.8,alpha:1.0).CGColor 
dot.borderColor =UIColor(white:1.0,alapha:1.0).CGColor 
dot.borderWidth = 1.0 
dot.cornerRadius = 2.0 
r.addSublayer(dot)

创建一个14×14的矩形,并给它一个2磅圆角半径。在最后你添加dot层的复制。
现在运行应用程序,看看一切看起来就像至今:

现在复制15个点来组成一个圈,每次旋转的角度等于2π/ 15:

let nrDots:INT = 15 

r.instanceCount = nrDots 
let angle= CGFloat(2 * M_PI)/ CGFloat(nrDots)
r.instanceTransform = CATransform3DMakeRotation(agnle : 0.0,0.0,1.0)

设置instanceCount为15,设置了旋转变换使用2π/ 15的角度。
再次运行应用程序,你将会看到这样一个漂亮的画面:

你可以通过改变nrDots 到10,25或者其他值来轻松的达到你想要的效果,复制器乖乖计算几何和渲染点的克隆:

现在,让我们做一段1.5秒的动画。在到原来的点上做缩放变化:

let duration :CFTimeInterval = 1.5 

let shrink = CABasicAnimation(keyPath:"transform.scale")
shrink.fromValue = 1.0 
shrink.toValue = 0.1 
shrink.duration = duration
shrink.repeatCount = Float.infinity 
dot.addAnimation(shrink,forKey:nil)

这样就做出了一个催眠动画,所有的点一遍遍的变大变小。(千万不要盯着太久,以免被催眠哦)
当你希望记住的方法,使动画动起来的秘诀就是给出一点延迟到每一个副本,
就像这样

r.instanceDelay =duration/Double(nrDots)

这将让您的动画旋转很好。动画的第一个旋转有一个有点怪,但是在第一次旋转之后,所有的点就都是可见的
为了解决这个问题,我们可以第一次的点进行缩放,在动画开始之前,加上这个代码最后一行到animation2() :

dot.transform = CATransform3DMakeScale(0.01,0.01,0.01)。

这将使动画变得更加流畅。

做到这,是否感觉做动画比想象中要简单的多,不是吗?如果你尝试了一下基本活动的指标上面的代码,你可以轻松地创建各种效果,给一个试试吧!

3.跟随动画

在本教程中的第三个是有趣的跟随动画,您将指定的动画原始图层上的路径,并让其拷贝在追逐,并视图追第一个点。
切换到viewDidLoad中()

animation2()替换为:

func animation3()

正如你可能已经猜到你的下一个步骤就是添加一个空的方法你最终的动画:

func animation3(){ 

}

对于这个动画,您将需要添加另外一个方法。使用PaintCode应用程序,可以快速创建了一个贝塞尔路径,你会用你的动画。加入这个方法的ViewController

func rw() -> CGPath { 
    ////贝齐尔制图
    变种bezierPath = UIBezierPath()
    bezierPath.moveToPoint(CGPointMake(31.5,71.5))
    bezierPath.addLineToPoint(CGPointMake(31.5,23.5))
    bezierPath.addCurveToPoint(CGPointMake(58.5, 38.5),
        controlPoint1:CGPointMake(31.5,23.5),
        controlPoint2:CGPointMake(62.46,18.69))
    bezierPath.addCurveToPoint(CGPointMake(53.5,45.5),
        controlPoint1:CGPointMake(57.5,43.5),
        controlPoint2:CGPointMake(53.5,45.5))
    bezierPath.addLineToPoint(CGPointMake(43.5,48.5))
    bezierPath.addLineToPoint(CGPointMake(53.5,66.5))
    bezierPath.addLineToPoint(CGPointMake(62.5,51.5))
    bezierPath.addLineToPoint(CGPointMake(70.5,66.5))
    bezierPath.addLineToPoint(CGPointMake( 86.5,23.5))
    bezierPath.addLineToPoint(CGPointMake(86.5,78.5))
    bezierPath.addLineToPoint(CGPointMake(31.5,78.5))
    bezierPath.addLineToPoint(CGPointMake(31.5,71.5))
    bezierPath.closePath()

    VAR T = CGAffineTransformMakeScale(3.0, 3.0)
    return CGPathCreateCopyByTransformingPath(bezierPath.CGPath,&T)
}

此方法创建的代码贝塞尔路径,并返回它的CGPath副本 - 这CGPath你会用它来创建一个关键帧动画。
切换到到animation3() ,在里面添加代码:

let r = CAReplicatorLayer()
r.bounds = view.bounds 
r.backgroundColor = UIColor(white:0.0,alapha:0.75).CGColor 
r.position = view.center 
view.layer.addSublayer(R)

这个时候我们创建并添加一个和视图一样大小的空复制层。首先我们需要添加原始层复制层
添加以下代码:

let dot = CALayer()
dot.bounds = CGRect(0.0, 0.0, 10.0, 10.0)
dot.backgroundColor = UIColor(white: 0.8,alpha1.0).CGColor 
dot.borderColor = UIColor(white:1.0,alpha:1.0).CGColor 
dot.borderWidth = 1.0 
dot.cornerRadius = 5.0 
dot.shouldRasterize = true 
dot.rasterizationScale = UIScreen.mainScreen().scale
r.addSublayer(dot)

我们创建一个小银矩形,并设置矩形宽度的一半为圆角半径,所以你得到了一个小圈。我们对它进行复制。运行程序,我们将看到圆圈显示在屏幕的左上角。

让我们的动画沿着路径动起来:

let move = CAKeyframeAnimation(keyPath:"positon")
move.path = rw()
move.repeatCount = Float.infinity 
move.duration = 4.0 
dot.addAnimation(move,forKey:nil)

这个动画沿着由rw()方法绘制的途径,以4秒为周期,不停的运动着。

运行程序,现在我们会看到点像疯了一样乱跑,看不到它所走过的路径。
为了让动画更加清晰,添加以下代码:

r.instanceCount = 20 
r.instanceDelay = 0.1

这将增加的19个圆点,并让他们跟着第一个运行:

酷!动画开始运动就像你最喜欢的raywenderlich.comLogo一样。

我们来模仿的更加像一点,首先让颜色和raywenderlich.com网站的颜色的圆圈一样。添加该代码添加着色到复制的内容:

r.instanceColor = UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0).CGColor

设置instanceColor乘以您所提供的颜色原始内容的颜色。在这种情况下,您将乘颜色鲜艳的绿色,所以如果你运行的应用程序,你会看到一张很绿动画:)))
有趣的是,你还可以改变instanceColor.它非常容易使得绿色的色调变得越来越黑加入这个代码最后一行:

r.instanceGreenOffset = -0.03

这将使复制每次减少了0.03的绿色色调成分。最终的动画看起来是这样的:


会不会有人立刻打开一个新的Xcode项目,开始在一个贪吃蛇游戏呢?:]

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

推荐阅读更多精彩内容