在网上看到了这篇文章,写得很好,于是便把它翻译出来,这是我第一次翻译,翻得不好请轻喷,毕竟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
如果你想不同的动画就去改变instanceCount
,instanceTransform
和instanceDelay
。很酷,不是吗?
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项目,开始在一个贪吃蛇游戏呢?:]
网友评论
UIBezierPath *bezierPath = [UIBezierPath new];
[bezierPath moveToPoint:(CGPointMake(31.5, 78.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 closePath];
但是不知道为什么,最后一条线和closePath的方法是不是重复的?