对layui layer setwin或精灵做setRotation3D旋转后,触摸需要特殊处理吗

新人求助!!!!!!!高手快来帮忙哈!NavMeshAgent类【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:74,947贴子:
看英保通的 98讲 代码: using UnityEusing System.Cpublic class Ac_agent : MonoBehaviour {public GameObject particle =//要引用实例化的粒子物体protected NavMeshA//引用角色中的组件protected Aprotected Object partcicleC //引用实例化的粒子物体// Use this for initializationvoid Start () {agent = GetComponent&NavMeshAgent& (); //初始化agent.updateRotation = //旋转更新 关闭animator = GetComponent&Animator& ();//partcicleClone =//粒子克隆物体}protected void SetDestination () //角色寻径功能设置{var ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit = new RaycastHit ();if (Physics.Raycast (ray,out hit)){/*if(partcicleClone!= null){GameObject.Destroy(partcicleClone);partcicleClone =}*/Quaternion q = new Quaternion();q.SetLookRotation (hit.normal,Vector3.forward);partcicleClone = Instantiate (particle,hit.point,q);agent.destination = hit.}}// Update is called once per framevoid Update () {if (Input.GetButtonDown (&Fire1&)) SetDestination();}}地图也生成了Nvaigation ,角色也添加了组件nav mesh agent,粒子物体用的是跟教程一样的,结果提示错误: NullReferenceException: Object reference not set to an instance of an object Ac_agent.SetDestination () (at Assets/allanimators/Ac_agent.cs:19) Ac_agent.Update () (at Assets/allanimators/Ac_agent.cs:38) 大神帮忙给看看那哈 多谢多谢!!!
学游戏开发多长时间 unity游戏开发 从零开始学习精选网校课程,满足你的学习兴趣.
查看一下Player的Tag是否已经正确选择为“Player”
登录百度帐号推荐应用(Note: ‘Minimalist’ example artwork is
If you’ve been working on a 2D tile-based game in the last couple of years then there’s a decent chance you’re familiar with Thorbj?rn Lindeijer’s excellent . It’s what I used when creating the maps for
and I’ve now retooled and de-hacked my Tiled-to-Unity exporter (called Tiled2Unity Utility because naming things is hard) for general consumption by my fellow game developers  – free of charge under the . I sincerely hope others find it useful.
You can download the Tiled2Unity Utility from the .
Builds a Unity prefab out of your TMX map file
Supports all TMX layer formats (XML, CSV, Base64, gzip/zlib compressed)
Multiple layers and tilesets supported
Exports Object Layer as polygons, polylines, rectangles, circles
Tile Layer collisions supported (with slopes, odd-shaped polygons)
Polygon colliders can be concave, have holes, and be composed of separate polygons
Can assign Tag, Sorting Layer, Order in Layer, and (Physics) Layer of exported GameObjects through properties in Tiled
Support for customized creation of Unity Prefabs
Easy to use: In most cases, you simply export a TMX file into your Unity project and place the automatically generated prefab in your scene – no further edits needed
Limitations:
Orthographic map support only (Isometric and hexagonal map support in version 0.9.10.0)
Ellipse objects are ignored unless they are circular (there is no ellipse collider in Unity)
Object rotation is currently not supported (Object rotation added in version 0.9.9.0)
Tiled2Unity only runs on Windows out of the box (Prefabs exported into Unity will work on all devices though) (Note: See
for support on other platforms)
Note that I made a purposeful decision not to support isometric maps*. It adds far too much complexity for something that I think is a bit of a hack. I feel orthographic maps should be used at all times and the illusion of top-down or side-scroller or isometric should come from the art, not some weirdo coordinate system. (Your mileage may vary but it’s not like the Nintendo Entertainment System had an isometric mode.)
*(Edit to add: Okay, I relent. Isometric and hexagonal map support has been added as of version 0.9.10.0.)
Tiled2Unity Uses Newer Features of the Tiled Map Editor
In order to assign collision data to tiles you will need to use the new Tile Collision Editor in Tiled.
This Tiled feature is currently in beta* so you’ll need to get a version of the program from the daily builds here:
For my development and testing I’ve used the May 23rd, 2014 build. (Builds older than April 24th, 2014 will crash if you have collision data in external tilesets.)
*(Edit to add: Not in beta anymore. Just download latest version of Tiled)
Getting Started with Tiled2Unity
Before you begin exporting Tiled data into Unity, your project needs to be aware of how it will import the *.unity2tiled.xml files that Tiled2Unity spits out. The scripts for this are part of the Tiled2Unity.unitypackage file found in the install directory.
There are two ways to import this package into your Unity project:
From the Tiled2Unity install folder: Double click on the Tiled2Unity.unitypackage file
From within Tiled2Unity: Just select the “Import Unity Package to Project” menu item
In both cases, Unity will take you through the steps of installing the package into your Unity project. There’s a number of scripts and folders here. You’ll need them all.
Now we’re ready to export some Tiled maps into Unity.
Using Tiled2Unity Examples
Your Tiled2Unity install contains a couple of TMX file examples. We’re going to open the minimalist.tmx file in Unity …
We don’t need to run Tiled in order to export a TMX file into Unity, but I’ve set up a command in Tiled that will run Tiled2Unity for me.  This allows me to make my map edits in Tiled and then quickly export to Unity by pressing F5.
&c:\Program Files (x86)\Tiled2Unity\Tiled2Unity.exe& %mapfile c:\MyUnity\Test
The command is made up of 3 parts:
The path to your Tiled2Unity install
The %mapfile macro (this will be the same for all users)
The path to your Unity project (you can leave this blank and use the Tiled2Unity GUI instead)
Hitting F5, now Tiled2Unity pops up with our map already loaded and ready to export to our Unity project …
Now, pressing the Big Ass Export Button will export an XML file (in this case, minimalist.tiled2unity.xml) to our Unity project where our importer scripts will create the meshes, textures, and materials needed and roll them all up into a prefab named after our TMX file.
Now we can place the prefab into our scene hierarchy. (If our map was to be purely decorative then we’d be done.)
Adding Collision Geometry
Chances are most maps we make in Tiled for use in video games will require some collision geometry on them for sprites to interact with. Other solutions I’ve found on the internet or the Unity Asset Store require you to hand-place collision objects by hand in Tiled which I think is a total PITA. I’m going to show you how we can easily add complicated collision geometry (with holes, slopes, concave shapes, etc.) to our tile layers that are exported to Unity as PolygonCollider2Ds.
With Tiled still open on our minimalist map, bring up the Tiled Collision Editor an add a Rectangle or Polygon object that fully encloses the solid dark grey tile of our mini-tile tileset …
Let’s leave the other tiles alone for now and see how we’re doing. Press F5 again to bring up our Tiled2Unity exporter and press the Preview Exported Map button to see how the geometry would appear in Unity …
Here we can see how the geometry of just one tile will be combined into a polygon collider as the tile is repeated throughout the map. Note that, in the resulting collision mesh, there is actually four shapes here — two of which are rather awkward. Except for not matching the visuals, that’s actually okay, the PolygonCollider2D in Unity would handle this fine.
Let’s go back to Tiled and add polygons to our sloped tiles …
(I recommend that Snap to Grid and/or Snap to Fine Grid is enabled when placing polygons in Tiled)
Previewing again we can see how sloped geometry will be added to the collision mesh …
Again, this geometry could be exported into our Unity project and the PolygonCollider2D created from it would just work.
Going over all our darker tiles and adding polygons/rectangles I get a final preview that I’m pretty happy with …
The best part of this is as we edit the map the collisions assigned to each tile move along with them. You add the geometry to your tiles once, create all the map data you like, and let the exporter take care of the rest.
Here’s the final exported prefab with our PolygonCollider2D in Unity …
And there you go, a 2D tile-based map, authored in Tiled, with collision, in your Unity scene.
Find any bugs? Is something not working as expected? Got a feature request that makes sense and won’t kill my social life? Feel free to .
Leave a Comment当前位置:
& Swift - 动画效果的实现方法总结(附样例)
Swift - 动画效果的实现方法总结(附样例)
发布:hangge
阅读:18012
在iOS中,实现动画有两种方法。一个是统一的animateWithDuration,另一个是组合出现的beginAnimations和commitAnimations。这三个方法都是类方法。
一,使用animateWithDuration来实现动画
(1)此方法共有5个参数:
duration:动画从开始到结束的持续时间,单位是秒
delay:动画开始前等待的时间
options:动画执行的选项。里面可以设置动画的效果。可以使用UIViewAnimationOptions类提供的各种预置效果
anmations:动画效果的代码块
completion:动画执行完毕后执行的代码块
(2)UIView支持动画效果的属性
frame:此属性包含一个矩形,即边框矩形,此值确定了当前视图在其父视图坐标系中的位置与尺寸
bounds:也是矩形,边界矩形,它指的是视图在其自己的坐标系中的位置和尺寸,左上角坐标永远是(0,0)
center:确定视图的中心点在其父视图坐标系中的位置坐标。即定义当前视图在父视图中的位置
alpha:视图的透明度。(但视图完全透明时,不能响应触摸消息)
backgroundColor:背景色
transform:这是一种3×3的变化矩阵。通过这个矩阵我们可以对一个坐标系统进行缩放、平移、旋转以及这两者的任意组操作。
(3)Transform(变化矩阵)的四个常用的变换方法
CGAffineTransformMake():返回变换矩阵
CGAffineTransformMakeTranslation():返回平移变换矩阵
CGAffineTransformMakeScale():返回缩放变换矩阵
CGAffineTransformMakeRotation():返回旋转变换矩阵
(4)样例1:方块初始缩小为原始尺寸1/10。在1秒的动画中复原到完整大小,同时还伴随旋转效果。
import UIKit
class ViewController: UIViewController {
//游戏方格维度
var dimension:Int = 4
//数字格子的宽度
var width:CGFloat = 50
//格子与格子的间距
var padding:CGFloat = 6
//保存背景图数据
var backgrounds:Array&UIView&!
override func viewDidLoad()
super.viewDidLoad()
self.backgrounds = Array&UIView&()
setupGameMap()
playAnimation()
func setupGameMap()
var x:CGFloat = 50
var y:CGFloat = 150
for i in 0..&dimension
for _ in 0..&dimension
//初始化视图
let background = UIView(frame:CGRectMake(x, y, width, width))
background.backgroundColor = UIColor.darkGrayColor()
self.view.addSubview(background)
//将视图保存起来,以备后用
backgrounds.append(background)
y += padding + width
x += padding+width
func playAnimation()
for tile in backgrounds{
//先将数字块大小置为原始尺寸的 1/10
tile.layer.setAffineTransform(CGAffineTransformMakeScale(0.1,0.1))
//设置动画效果,动画时间长度 1 秒。
UIView.animateWithDuration(1, delay:0.01,
options:UIViewAnimationOptions.TransitionNone, animations:
()-& Void in
//在动画中,数字块有一个角度的旋转。
tile.layer.setAffineTransform(CGAffineTransformMakeRotation(90))
completion:{
(finished:Bool) -& Void in
UIView.animateWithDuration(1, animations:{
()-& Void in
//完成动画时,数字块复原
tile.layer.setAffineTransform(CGAffineTransformIdentity)
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
(5)样例2:只有从小变大的效果
func playAnimation()
for tile in backgrounds{
//先将数字块大小置为原始尺寸的 1/10
tile.layer.setAffineTransform(CGAffineTransformMakeScale(0.1,0.1))
//设置动画效果,动画时间长度 1 秒。
UIView.animateWithDuration(1, delay:0.01,
options:UIViewAnimationOptions.TransitionNone, animations:
()-& Void in
tile.layer.setAffineTransform(CGAffineTransformMakeScale(1,1))
completion:{
(finished:Bool) -& Void in
UIView.animateWithDuration(0.08, animations:{
()-& Void in
tile.layer.setAffineTransform(CGAffineTransformIdentity)
(6)样例3:方块从不透明到透明的效果
func playAnimation()
for tile in backgrounds{
tile.alpha = 0;
//设置动画效果,动画时间长度 1 秒。
UIView.animateWithDuration(1, delay:0.01,
options:UIViewAnimationOptions.CurveEaseInOut, animations:
()-& Void in
completion:{
(finished:Bool) -& Void in
UIView.animateWithDuration(1, animations:{
()-& Void in
tile.alpha = 1
二,使用beginAnimations和commitAnimations方法来实现动画
beginAnimations:此方法开始一个动画块,调用commitAnimations结束一个动画块,并且动画块是允许嵌套的。
commitAnimations:此方法用于结束一个动画块,动画是在一个独立的线程中运行的,动画在生效时,所有应用程序不会中断。
在beginAnimations和commitAnimations中间的代码中,我们可以设置各种动画的属性。比如持续时间,使用哪种预置的动画效果等。
(1)淡入,淡出,移动,改变大小动画
//淡出动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.alpha = 0.0
mitAnimations()
//淡入动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.alpha = 1.0
mitAnimations()
//移动动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.center = CGPointMake(250, 250)
UIView.setAnimationCurve(UIViewAnimationCurve.EaseOut) //设置动画相对速度
mitAnimations()
//大小调整动画
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(2.0)
imageView.frame = CGRectMake(100,180,50,50)
mitAnimations()
(2)两个视图切换的过渡动画
& UIViewAnimationTransition定义了5种过渡动画类型:
None:无过渡动画效果
FlipFromLeft:从左侧向右侧翻转
FlipFromRight:从右侧向左侧翻转
CurlUp:向上卷数翻页
CurlDown:向下翻页
import UIKit
class ViewController: UIViewController {
override func viewDidLoad()
super.viewDidLoad()
//创建一个按钮,用来点击播放动画
let button:UIButton = UIButton(type:.System)
button.frame=CGRectMake(10, 20, 100, 30)
button.setTitle("播放动画", forState:UIControlState.Normal)
button.addTarget(self,action:Selector("play"),forControlEvents:.TouchUpInside)
self.view.addSubview(button);
//添加两个红蓝视图
let redView:UIView = UIView(frame: CGRectMake(50,50,150,400))
redView.backgroundColor = UIColor.redColor()
self.view.insertSubview(redView, atIndex: 0)
let blueView:UIView = UIView(frame: CGRectMake(50,50,150,400))
blueView.backgroundColor = UIColor.blueColor()
self.view.insertSubview(blueView, atIndex: 1)
//切换视图并播放动画
func play(){
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(3.0)
UIView.setAnimationTransition(.CurlUp, forView: self.view, cache: true)
self.view.exchangeSubviewAtIndex(1, withSubviewAtIndex: 0)
mitAnimations()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
(3)页面或元件翻转效果
import UIKit
class ViewController: UIViewController {
override func viewDidLoad()
super.viewDidLoad()
//创建一个按钮,用来点击播放动画
let button:UIButton = UIButton(type:.System)
button.frame=CGRectMake(10, 20, 100, 30)
button.setTitle("播放动画", forState:UIControlState.Normal)
button.addTarget(self,action:Selector("play"),forControlEvents:.TouchUpInside)
self.view.addSubview(button);
//切换视图并播放动画
func play(){
//将整个主视图面板实现一个翻转效果
UIView.beginAnimations("animation", context: nil)
UIView.setAnimationDuration(2)
UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut)
UIView.setAnimationTransition(.FlipFromLeft, forView: self.view, cache: false)
mitAnimations()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()如果想在底层做一些改变,想实现一些特别的动画,这时除了学习Core Animation之外,别无选择。
最近在看《iOS Core Animation:Advanced Techniques》这本书籍,尚有所收获,并将之记录下来。
&CALayer如果将UIView说成是视图,那么CALayer就是图层了。每一个 UIView 的身后对应一个 Core Animation 框架中的 CALayer;每一个 CALayer 都是 UIView 的代理。可以尝试运行下面的代码,会发现打印是一样的内存地址:
let testView = UIView()
print("\(testView)")
print("\(testView.layer.delegate!)")
&在iOS开发中,处理的一个又一个UIView,实际是在操作CALayer。那么为什么不直接对CALayer进行编程呢?那是因为CALayer继承自NSObject,主要是用于图层的处理以及动画,而UIView继承自UIResponder,可以处理交互事件。由此,可以认为UIView就是对CALayer的一个简单封装,图像绘制、动画都是CALayer做的。有过开发经验的朋友都知道,苹果在UIView里面封装了一套动画接口,但是利用这些接口,只是可以做一些简单、不灵活的动画。如果想在底层做一些改变,想实现一些特别的动画,这是除了学习Core Animation之外,别无选择。A. CALayer的简单使用& & 这一部分内容开发中经常用到,可以说是基础的东西。代码:& &&
let testView = UIView(frame: CGRectMake(100, 100, 100, 100))
testView.backgroundColor = UIColor.blueColor()
self.view.addSubview(testView)
//设置圆角
testView.layer.cornerRadius = testView.frame.width / 2.0
testView.layer.masksToBounds = true
//设置边框
testView.layer.borderWidth = 5
testView.layer.borderColor = UIColor.redColor().CGColor
//设置阴影,这里需要注意,如果masksToBounds为true,阴影会被裁剪掉(所以,一般如果你既想要圆形图片,又想要阴影,那么是需要将图片进行裁剪的)
testView.layer.shadowOpacity = 0.5
testView.layer.shadowOffset = CGSizeMake(0, 2)
testView.layer.shadowRadius = 5
//需要注意的是这个属性: shadowPath
它是CGPathRef类型,可以用自定义阴影样式,比如说,它默认是圆形的阴影,现在将之变成方形阴影
let path = CGPathCreateMutable()
CGPathAddRect(path, nil, testView.bounds)
testView.layer.shadowPath = path
//如果是oc的话,需要注意释放path,因为它是core Graphics的东西,OC的ARC机制并不会对它进行内存管理,但是Swift对它自动进行了,所以在Swift中不需要写这个代码
CGPathRelease(path)
&B. 自定义CALayer& & CALayer有一个contents属性,它在OC中是id类型,在Swift中是AnyObject类型,这意味着它可以是任何类型对象。但在实践中,如果给这个属性赋值的不是CGImage类型,图层会是一片空白。它的这个奇怪的现象是因为MAC OS原因造成的,在MAC OS系统上,给它赋值CGImage或者NSImage都是起作用的,但是在iOS系统,如果将UIImage赋值给它,图层只会是一片空白。(注意,视图指的是UIView,图层指的是CALayer)& & &在OC中,如果直接将这么做,会产生编译错误:
UIImage *image = [UIImage imageNamed:@"1"];
self.view.layer.contents = image.CGI
& & &正确的写法是:
UIImage *image = [UIImage imageNamed:@"1"];
self.view.layer.contents = (__bridge id _Nullable)(image.CGImage);
& & 在OC中,事实上真正要赋值的类型应该是CGImageRef,它是一个指向CGImage的指针,而CGImageRef并不是Cocoa对象,而是一个Core Foundation类型,所以需要进行桥接转换。& & 但是在Swift中没必要这么麻烦,直接用CGImage赋值即可,我猜想这是苹果在底层帮忙转换了,代码:& &&
func drawImageOnLayer() {
let image = UIImage(named: "1")
self.blueView.layer.contents = image?.CGImage
相当于UIImageView的contentMode属性,可以设置图片显示样式
kCAGravityCenter
kCAGravityTop
kCAGravityBottom
kCAGravityLeft
kCAGravityRight
kCAGravityTopLeft
kCAGravityTopRight
kCAGravityBottomLeft
kCAGravityBottomRight
kCAGravityResize
kCAGravityResizeAspect
kCAGravityResizeAspectFill
//相当于UIImageView的contentMode属性,可以设置图片显示样式
self.blueView.layer.contentsGravity = kCAGravityResizeAspect
//contentsScale定义了CGImage的像素尺寸和视图大小比例,默认情况下为1.0
//如何理解这句话,我是这么理解的,屏幕有非retina屏幕(像素和尺寸是1:1)
//还有retina屏幕,像素和尺寸比是2:1
//现在还出现了@3x图片,像素和尺寸比理论上是3:1,但实际上在显示的时候,苹果进行了调整(具体可以看ios9的新特性)
//那么,像我下面这么写,就是说像素点按照屏幕来调整,如果是非retaina,那么就是1:1,如果是retina,就是2:1
self.blueView.layer.contentsScale = UIScreen.mainScreen().scale
self.blueView.layer.masksToBounds = true
&& & 其实自定义CALayer也是很简单的事情,代码如下:
func drawCircleOnLayer() {
let layer = CALayer()
layer.frame = CGRectMake(50.0, 50.0, 100.0, 100.0)
layer.backgroundColor = UIColor.blueColor().CGColor
layer.delegate = self
layer.contentsScale = UIScreen.mainScreen().scale
self.view.layer.addSublayer(layer)
layer.display()
//MARK:- CALayerDelegate
override func drawLayer(layer: CALayer, inContext ctx: CGContext) {
CGContextSetLineWidth(ctx, 10)
CGContextSetStrokeColorWithColor(ctx, UIColor.redColor().CGColor)
CGContextAddEllipseInRect(ctx, layer.bounds)
CGContextStrokePath(ctx)
& & &上面的代码通过使用Core Graphics来绘图。CALayer有一个delegate属性,实现了CALayerDelegate协议,但是这个协议是个非正式的协议,可以看到CALayer的这个属性的声明:
weak public var delegate: AnyObject?
& & &然后在这个方法里面绘制想要的图像,从而达到自定义CALayer的效果:
override func drawLayer(layer: CALayer, inContext ctx: CGContext) {
CGContextSetLineWidth(ctx, 10)
CGContextSetStrokeColorWithColor(ctx, UIColor.redColor().CGColor)
CGContextAddEllipseInRect(ctx, layer.bounds)
CGContextStrokePath(ctx)
& & UIView有一个drawRect:方法,在这个方法里面拿到当前的CGContext,进行绘画。它的底层还是通过调用CALayer的一系列方法绘制东西。&C. CALayer的布局 &&
& & UIView有frame、bounds、center这三个重要的布局属性,对应的CALayer也有frame、bounds、position这三个布局属性。layer的position与view的center代表的是同样的值。& & 如下图的关系:& &&& & anchorPoint(锚点)这个属性必须要好好说说。anchorPoint决定了view和layer的显示位置,它的取值是CGPoint(0~~1, 0~~1)。默认是为(0.5, 0.5),默认意味着它就在中点。那么,如果它不在中点呢?如下图:& & 注意到,当anchorPoint发生改变的时候,frame改变了,但是position并不会发生变化。也就是说,anchorPoint决定了view和layer的位置如何显示。& & 那么,在生命场合需要改变anchorPoint呢?& &&& & 加入现在需要做一个钟表的应用,有三根针,时针、分针、秒针,他们需要转动,转动过程中需要动画。如果anchorPoint为默认值,也就是中点的话,会如下面这样旋转:& & 围绕着三根针的重点旋转,这明显不是我们所想要。但如果将anchorPoint设置为(0.5, 0.9)就不一样了,它会这么旋转:代码:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var hourView: UIImageView!
@IBOutlet weak var minuteView: UIImageView!
@IBOutlet weak var secondView: UIImageView!
@IBOutlet weak var imageView: UIImageView!
var timer: NSTimer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.insertSubview(imageView, atIndex: 0)
self.hourView.layer.anchorPoint = CGPointMake(0.5, 0.9)
self.minuteView.layer.anchorPoint = CGPointMake(0.5, 0.9)
self.secondView.layer.anchorPoint = CGPointMake(0.5, 0.9)
self.addTimer()
func addTimer() {
self.updateWithAnimate(false)
self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("tick"), userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(self.timer!, forMode: NSRunLoopCommonModes)
func removeTimer() {
self.timer!.invalidate()
self.timer = nil
func tick() {
self.updateWithAnimate(true)
@objc func updateWithAnimate(animated: Bool) {
let calendar = NSCalendar.currentCalendar()
let unit: NSCalendarUnit = [NSCalendarUnit.Hour, NSCalendarUnit.Minute, NSCalendarUnit.Second]
let nowComponent = ponents(unit, fromDate: NSDate())
let hourAngle = CGFloat(nowComponent.hour) / 12.0 * CGFloat(M_PI) * 2.0
let minuteAngle = CGFloat(nowComponent.minute) / 60.0 * CGFloat(M_PI) * 2.0
let secondAngle = CGFloat(nowComponent.second) / 60.0 * CGFloat(M_PI) * 2.0
print("\(hourAngle)
\(minuteAngle)
\(secondAngle)
self.setAngle(hourAngle, forView: hourView, animated: animated)
self.setAngle(minuteAngle, forView: minuteView, animated: animated)
self.setAngle(secondAngle, forView: secondView, animated: animated)
func setAngle(angle: CGFloat, forView view: UIView, animated: Bool) {
var transform: CATransform3D = CATransform3DMakeRotation(angle, 0, 0, 1)
if (animated) {
let basicAnimate = CABasicAnimation(keyPath: "transform")
basicAnimate.toValue = NSValue(CATransform3D: transform)
self.updateWithAnimate(false)
basicAnimate.duration = 0.5
basicAnimate.delegate = self
basicAnimate.fillMode = kCAFillModeForwards
basicAnimate.removedOnCompletion = false
basicAnimate.setValue(view, forKeyPath: "view")
view.layer.addAnimation(basicAnimate, forKey: nil)
view.layer.transform = transform
override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
print("animationDidStop")
let view = anim.valueForKeyPath("view") as! UIView
let tempAnim = anim as? CABasicAnimation
view.layer.transform = (tempAnim?.toValue?.CATransform3DValue)!
self.removeTimer()
& & &(它的github地址:/wzpziyi1/Core-Animation-Test-One)
& & 这个Demo里面的所用到的动画,在后面会详细提及。在这里,主要是需要知道anchorPoint在做动画时的巨大价值。D. CALayer处理事件& & 与UIView类似,CALayer也提供了一系列的坐标转换方法,使用这些方法,可以使得我们可以较为方便的处理layer层面的事件响应:& &&
public func convertPoint(p: CGPoint, fromLayer l: CALayer?) -& CGPoint
public func convertPoint(p: CGPoint, toLayer l: CALayer?) -& CGPoint
public func convertRect(r: CGRect, fromLayer l: CALayer?) -& CGRect
public func convertRect(r: CGRect, toLayer l: CALayer?) -& CGRect
&需要着重提下hitTest:方法,它使得layer可以进行事件处理,这么说吧,正是因为它的存在,才可以判断,一个点击或者触摸等事件是发生在哪个layer上面。示例代码如下:
import UIKit
class ViewController: UIViewController, UIAlertViewDelegate {
weak private var redLayer: CALayer!
weak private var blueLayer: CALayer!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let redLayer = CALayer()
redLayer.frame = CGRectMake(100, 50, 100, 100)
redLayer.backgroundColor = UIColor.redColor().CGColor
self.view.layer.addSublayer(redLayer)
self.redLayer = redLayer
let blueLayer = CALayer()
blueLayer.frame = CGRectMake(100, 200, 100, 100)
blueLayer.backgroundColor = UIColor.blueColor().CGColor
self.view.layer.addSublayer(blueLayer)
self.blueLayer = blueLayer
override func touchesBegan(touches: Set&UITouch&, withEvent event: UIEvent?) {
let touch = touches.first
let point = touch?.locationInView(self.view)
let layer = self.view.layer.hitTest(point!)
if (layer == self.redLayer) {
let alertView = UIAlertView(title: "点击了redLayer", message: "", delegate: self, cancelButtonTitle: nil, otherButtonTitles: "确定")
alertView.show()
else if (layer == self.blueLayer) {
let alertView = UIAlertView(title: "点击了blueLayer", message: "", delegate: self, cancelButtonTitle: nil, otherButtonTitles: "确定")
alertView.show()
动画的基础知识这里会说一些动画轨迹的具体实现,补充UIBezierPath的使用。如果想要你的动画沿着所写的曲线运动,那么这些基础知识是不可缺少的。A.&UIBezierPath& & 如果熟悉Core Graphics,那么就可以很快掌握它的用法,实际上它就是对Core Graphics的一个封装。示例代码:
import UIKit
class ZYView: UIView {
override func drawRect(rect: CGRect) {
let path = UIBezierPath()
path.addArcWithCenter(CGPointMake(150, 150), radius: 50, startAngle: 0, endAngle: CGFloat(M_PI * 2.0), clockwise: true)
path.lineWidth = 5
UIColor.blueColor().setStroke()
UIColor.redColor().setFill()
path.stroke()
path.fill()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
redView.backgroundColor = UIColor.redColor()
self.view.addSubview(redView)
self.view.addSubview(ZYView(frame: CGRectMake(100, 100, 300, 300)))
&可以得到下面的界面:
& & 那么,现在加入有一个需求,一张图片想要绕着圆转一圈的动画,如何实现?其实只需要定义好运动的轨迹,然后告诉animate给我按照这个轨迹进行运动即可。代码:
import UIKit
class ViewController: UIViewController {
var redView: UIView = UIView(frame: CGRectMake(40, 200, 50, 50))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
redView.backgroundColor = UIColor.redColor()
self.view.addSubview(redView)
override func touchesBegan(touches: Set&UITouch&, withEvent event: UIEvent?) {
self.animate1()
func animate1() {
redView.layer.cornerRadius = redView.frame.width / 2
redView.layer.anchorPoint = CGPointMake(0.5, 0.5)
let keyFrameAnimate = CAKeyframeAnimation(keyPath: "position")
let path = UIBezierPath()
path.addArcWithCenter(CGPointMake(150, 150), radius: 100, startAngle: 0, endAngle: CGFloat(M_PI * 2.0), clockwise: true)
keyFrameAnimate.path = path.CGPath
keyFrameAnimate.duration = 3
keyFrameAnimate.fillMode = kCAFillModeForwards
keyFrameAnimate.delegate = self
keyFrameAnimate.removedOnCompletion = false
keyFrameAnimate.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
self.redView.layer.addAnimation(keyFrameAnimate, forKey: "aaa")
& & 可以看到这样的代码:
let path = UIBezierPath()
path.addArcWithCenter(CGPointMake(150, 150), radius: 100, startAngle: 0, endAngle: CGFloat(M_PI * 2.0), clockwise: true)
keyFrameAnimate.path = path.CGPath
& & &正是上面提到的,给animate提供了一条运动轨迹。& & &类似的,沿着圆运动的轨迹已经可以定义了,那么沿着四边形运动的轨迹也是相似的。那么,沿着曲线运动的轨迹如何定义呢?B. 贝塞尔曲线& & 如果你想要定义曲线运动的轨迹,那么这个知识点是必须学习的。
& & 这是我看到的一份总结贝塞尔曲线很好的博客:& & 下面的关于曲线的总结也是转载自上面的博客。B&zier curve(贝塞尔曲线)是应用于二维图形应用程序的。&曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。&1962年,法国数学家Pierre B&zier第一个研究了这种绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。
& & 以下公式中:B(t)为t时间下&点的坐标;
& & P0为起点,Pn为终点,Pi为控制点一阶贝塞尔曲线:
& & 意义:由 P0 至 P1 的连续点, 描述的一条线段二阶贝塞尔曲线:& &原理:由 P0 至 P1 的连续点 Q0,描述一条线段。&&&&&& 由 P1 至 P2 的连续点 Q1,描述一条线段。&&&&&& 由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。& & &&经验:P1-P0为曲线在P0处的切线。& & 三阶贝塞尔曲线:
CGAffineTransform与CATransform3D已经知道了运动轨迹的定义,那么该如何让layer沿着动画轨迹运动呢,如果在运动过程中,还有能缩放、旋转呢?A.&CGAffineTransform& & 从CG就可以看出它是属于Core Graphics的东西,实际上UIView的transform属性就是CGAffineTransform类型,用它可以做二维平面上的缩放、旋转、平移。
& & 下面的这几个函数都创建了一个CGAffineTransform实例:
//平移,输入需要平移的x,y值即可
public func CGAffineTransformMakeTranslation(tx: CGFloat, _ ty: CGFloat) -& CGAffineTransform
//缩放x方向缩放的倍数,y方向的缩放倍数,默认都为1
public func CGAffineTransformMakeScale(sx: CGFloat, _ sy: CGFloat) -& CGAffineTransform
//旋转,angle放弧度
public func CGAffineTransformMakeRotation(angle: CGFloat) -& CGAffineTransform
& & 当然还有一些其他的接口,并不都一一写出,下面是一份简单的实例代码,一边缩放、一边平移:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var redView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
override func touchesBegan(touches: Set&UITouch&, withEvent event: UIEvent?) {
self.transformTest2D()
func transformTest2D() {
UIView.animateWithDuration(2) { () -& Void in
let transform = CGAffineTransformMakeScale(2, 2)
//注意,本意只是想平移200的,但是由于是先缩放后平移的,如果不除以缩放系数的话,会达不到本意
self.redView.transform = CGAffineTransformTranslate(transform, 200 / 2, 200 / 2)
B.&CATransform3D& & 它可以做到让图层在三维空间内平移、旋转等。& & CATransform3D是一个4*4的矩阵:& & 与CGAffineTransform类似,它也提供了一系列的接口让我们得以实例化一个CATransform3D实例:
public func CATransform3DMakeTranslation(tx: CGFloat, _ ty: CGFloat, _ tz: CGFloat) -& CATransform3D
public func CATransform3DMakeScale(sx: CGFloat, _ sy: CGFloat, _ sz: CGFloat) -& CATransform3D
public func CATransform3DMakeRotation(angle: CGFloat, _ x: CGFloat, _ y: CGFloat, _ z: CGFloat) -& CATransform3D
& & 多了一个z值。同样的,它也提一系列用来做混合动画的接口:
public func CATransform3DTranslate(t: CATransform3D, _ tx: CGFloat, _ ty: CGFloat, _ tz: CGFloat) -& CATransform3D
public func CATransform3DScale(t: CATransform3D, _ sx: CGFloat, _ sy: CGFloat, _ sz: CGFloat) -& CATransform3D
@available(iOS 2.0, *)
public func CATransform3DRotate(t: CATransform3D, _ angle: CGFloat, _ x: CGFloat, _ y: CGFloat, _ z: CGFloat) -& CATransform3D
& & &示例代码:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var redView: UIView!
@IBOutlet weak var imageView1: UIImageView!
@IBOutlet weak var imageView2: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
override func touchesBegan(touches: Set&UITouch&, withEvent event: UIEvent?) {
self.transformTest3D()
func transformTest3D() {
UIView.animateWithDuration(2, animations: { () -& Void in
//绕Y轴旋转四分之三PI
self.imageView1.layer.transform = CATransform3DMakeRotation(CGFloat(M_PI * 3.0 / 4.0), 0, 1, 0)
//绕Y轴旋转四分之一PI
self.imageView2.layer.transform = CATransform3DMakeRotation(-CGFloat(M_PI_4), 0, 1, 0)
}) { (finish: Bool) -& Void in
dispatch_after(dispatch_time_t(dispatch_time(DISPATCH_TIME_NOW, (Int64)(2 * NSEC_PER_SEC))), dispatch_get_main_queue(), { () -& Void in
//旋转完成2s之后,将他们各自的transform恢复原始值
//需要注意,CGAffineTransform也有这个CGAffineTransformIdentity,前面忘说了,效果是一样的
self.imageView1.layer.transform = CATransform3DIdentity
self.imageView2.layer.transform = CATransform3DIdentity
CATransform3D还有一个很有意思的m34属性,我们通过调整这个属性可以做一些很nice的视觉。恩,就是通过设置它的值,可以做出一些很好的透视效果。m34的默认值是0,我们可以设置m34的值为(-1/d)来做相应的透视效果,d的值一般在500.0~~1000.0之间效果就很不错了,用它写了一个打开门的动画,设置m34与不设置m34的区别简直就是天差地别。& & 代码(代码太少了,上传到github实在浪费时间,我的建议是,百度一张门的图片,然后尝试注释掉m34的设置与不注释m34的视觉区别):
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) CALayer *doorL
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
self.doorLayer = [CALayer layer];
self.doorLayer.frame = CGRectMake(0, 0, 128, 256);
self.doorLayer.position = CGPointMake(150 - 64, 300);
self.doorLayer.anchorPoint = CGPointMake(0, 0.5);
self.doorLayer.contents = (__bridge id)[UIImage imageNamed:@"Door.png"].CGI
[self.view.layer addSublayer:self.doorLayer];
CATransform3D perspective = CATransform3DI
//设置m34,可以尝试注释掉,看看与不注销的视觉差距
perspective.m34 = -1.0 / 500.0;
self.view.layer.sublayerTransform =
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] init];
[pan addTarget:self action:@selector(pan:)];
[self.view addGestureRecognizer:pan];
self.doorLayer.speed = 0.0;
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform";
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-M_PI_2, 0, 1, 0)];
animation.duration = 1.0;
[self.doorLayer addAnimation:animation forKey:nil];
- (void)pan:(UIPanGestureRecognizer *)pan
CGFloat x = [pan translationInView:self.view].x;
x /= 200.0f;
CFTimeInterval timeOffset = self.doorLayer.timeO
timeOffset = MIN(0.999, MAX(0.0, timeOffset - x));
self.doorLayer.timeOffset = timeO
[pan setTranslation:CGPointZero inView:self.view];
& & oc代码,没有改写成Swift代码,这是可以手势控制门打开或者关闭动画的代码。图片:
动画在学习动画之前,有一副图是必须提到的:
CAAnimation的继承结构。而我这次所深入学习的是CABasicAnimation、CAKeyFrameAnimation、CAAnimationGroup、CATransition。
CAAnimation:
& & 所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
& & duration:动画的持续时间& & repeatCount:动画的重复次数& & repeatDuration:动画的重复时间& & removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards& & fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后& & beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间 && & timingFunction:速度控制函数,控制动画运行的节奏& & delegate:动画代理& & keyPath: 通过指定CALayer的一个属性名称达到相应的动画效果,比如说,指定"position"为keyPath,就修改CALayer的position属性值,以达到平移的动画效果
A. &CABasicAnimation
CAPropertyAnimation的子类
fromValue:keyPath相应属性的初始值
toValue:keyPath相应属性的结束值
随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
import UIKit
class ViewController: UIViewController {
weak private var contentView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let view = UIView(frame: CGRectMake(100, 100, 100, 100))
view.backgroundColor = UIColor.redColor()
self.view.addSubview(view)
self.contentView = view
self.contentView.layer.anchorPoint = CGPointZero
override func touchesBegan(touches: Set&UITouch&, withEvent event: UIEvent?) {
self.animateOfTransform3D()
func animateOfTransform3D() {
let animate = CABasicAnimation(keyPath: "transform")
animate.toValue = NSValue(CATransform3D: CATransform3DMakeRotation(CGFloat(M_PI_4), 0, 1, 0))
animate.duration = 2
animate.removedOnCompletion = false
animate.fillMode = kCAFillModeForwards
animate.delegate = self
self.contentView.layer.addAnimation(animate, forKey: "aaa")
//缩放动画
func animateOfScale() {
let animate = CABasicAnimation(keyPath: "bounds")
animate.toValue = NSValue(CGRect: CGRectMake(100, 100, 200, 200))
animate.duration = 2
animate.removedOnCompletion = false
animate.fillMode = kCAFillModeForwards
animate.delegate = self
self.contentView.layer.addAnimation(animate, forKey: "bcd")
//平移动画
func animateOfTranslation() {
//keyPath放需要执行怎么样的动画
let animate = CABasicAnimation(keyPath: "position")
//layer从哪里来
animate.fromValue = NSValue(CGPoint: CGPointMake(100, 100))
animate.toValue = NSValue(CGPoint: CGPointMake(200, 200))
在当前位置的基础上增加多少
animate.byValue = [NSValue valueWithCGPoint:CGPointMake(0, 300)];
animate.duration = 1
//设置动画执行完毕之后不删除动画
animate.removedOnCompletion = false
//设置保存动画的最新状态
animate.fillMode = kCAFillModeForwards
animate.delegate = self
self.contentView.layer.addAnimation(animate, forKey: "abc")
override func animationDidStart(anim: CAAnimation) {
print("animationDidStart")
override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
print("animationDidStop")
B. CAKeyFrameAnimation
CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
属性解析:
values:就是上述的NSArray对象。里面的元素称为&关键帧&(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略
keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的
CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var redView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.redView.layer.anchorPoint = CGPointZero
override func touchesBegan(touches: Set&UITouch&, withEvent event: UIEvent?) {
self.animateTest2()
@IBAction func clickBtn(sender: AnyObject) {
self.redView.layer.removeAnimationForKey("aaa")
//无限摇摆
func animateTest2() {
self.redView.layer.anchorPoint = CGPointMake(self.redView.frame.width / 2, self.redView.frame.height / 2)
let keyAnimate = CAKeyframeAnimation(keyPath: "transform.rotation")
keyAnimate.values = [ -2.14 / 20, 2.14 / 20, -2.14 / 20];
keyAnimate.removedOnCompletion = false
keyAnimate.fillMode = kCAFillModeForwards
keyAnimate.duration = 0.05
keyAnimate.delegate = self
keyAnimate.repeatCount = Float(CGFloat.max)
self.redView.layer.addAnimation(keyAnimate, forKey: "aaa")
//围绕一个圆进行动画
func animateTest1() {
let keyAnimate = CAKeyframeAnimation(keyPath: "position")
var path = CGPathCreateMutable()
CGPathAddEllipseInRect(path, nil, CGRectMake(0, 100, 200, 200))
keyAnimate.path = path
//设置动画的进度快慢,可以先快后慢,先慢后快等
keyAnimate.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
keyAnimate.removedOnCompletion = false
keyAnimate.fillMode = kCAFillModeForwards
keyAnimate.duration = 2
keyAnimate.delegate = self
self.redView.layer.addAnimation(keyAnimate, forKey: "aaa")
func animateTest() {
let keyAnimate = CAKeyframeAnimation(keyPath: "position")
let v1 = NSValue(CGPoint: CGPointMake(self.redView.frame.origin.x, self.redView.frame.origin.y))
let v2 = NSValue(CGPoint: CGPointMake(100, 200))
let v3 = NSValue(CGPoint: CGPointMake(0, 200))
let v4 = NSValue(CGPoint: CGPointMake(0, 100))
let v5 = NSValue(CGPoint: CGPointMake(self.redView.frame.origin.x, self.redView.frame.origin.y))
keyAnimate.values = [v1, v2, v3, v4, v5]
//设置动画的进度快慢,可以先快后慢,先慢后快等
keyAnimate.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
keyAnimate.removedOnCompletion = false
keyAnimate.fillMode = kCAFillModeForwards
keyAnimate.duration = 2
keyAnimate.delegate = self
self.redView.layer.addAnimation(keyAnimate, forKey: "aaa")
override func animationDidStart(anim: CAAnimation) {
print("animationDidStart")
override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
print("animationDidStop")
前面提到了,沿着贝塞尔曲线的动画:
func animateTestThree() {
let path = UIBezierPath()
path.moveToPoint(CGPointMake(0, 150))
//这是二次贝塞尔曲线的接口,利用此接口,可以定义一条贝塞尔曲线轨迹
path.addCurveToPoint(CGPointMake(400, 150), controlPoint1: CGPointMake(75, 0), controlPoint2: CGPointMake(225, 300))
let plane = UIImageView(frame: CGRectMake(0, 0, 85, 60))
//这里可以放一张飞机图片
plane.image = UIImage(named: "F5000000")
plane.center = CGPointMake(0, 150)
plane.layer.anchorPoint = CGPointMake(0.5, 0.5)
self.view.addSubview(plane)
let animate = CAKeyframeAnimation(keyPath: "position")
animate.duration = 4
animate.path = path.CGPath
animate.fillMode = kCAFillModeForwards
animate.removedOnCompletion = false
animate.delegate = self
//设置此属性,可以使得飞机在飞行时自动调整角度
animate.rotationMode = kCAAnimationRotateAuto
animate.setValue(plane.layer, forKey: "plane.layer")
plane.layer.addAnimation(animate, forKey: "animateTestThree")
C. CAAnimationGroup
CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行
属性解析:
animations:用来保存一组动画对象的NSArray
默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var redView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// 平移动画
CABasicAnimation *a1 = [CABasicAnimation animation];
a1.keyPath = @"transform.translation.y";
a1.toValue = @(100);
// 缩放动画
CABasicAnimation *a2 = [CABasicAnimation animation];
a2.keyPath = @"transform.scale";
a2.toValue = @(0.0);
// 旋转动画
CABasicAnimation *a3 = [CABasicAnimation animation];
a3.keyPath = @"transform.rotation";
a3.toValue = @(M_PI_2);
override func touchesBegan(touches: Set&UITouch&, withEvent event: UIEvent?) {
let basicAnimate = CABasicAnimation(keyPath: "transform.scale")
basicAnimate.toValue = 1.5
let keyFrameAnimate = CAKeyframeAnimation(keyPath: "position")
let path = CGPathCreateMutable()
CGPathAddEllipseInRect(path, nil, CGRectMake(100, 200, 150, 150))
keyFrameAnimate.path = path
let animateGroup = CAAnimationGroup()
animateGroup.animations = [basicAnimate, keyFrameAnimate]
animateGroup.duration = 2
animateGroup.fillMode = kCAFillModeForwards
animateGroup.removedOnCompletion = false
self.redView.layer.addAnimation(animateGroup, forKey: "aaa")
D. CATransition
CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点
UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果
type:动画过渡类型
subtype:动画过渡方向
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)
& & & 代码:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
var index: Int = 0
private var _images: Array&UIImage&?
var images: Array&UIImage&? {
if (_images == nil) {
_images = Array&UIImage&()
for(var i = 1; i &= 7; i++) {
let image = UIImage(named: "\(i)")
_images?.append(image!)
return _images
_images = newValue
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.imageView.image = self.images![0]
@IBAction func next(sender: AnyObject) {
self.index++
if (self.index == 7) {
self.index = 0
self.imageView.image = self.images![self.index]
let transition = CATransition()
//动画过渡类型
transition.type = "cube"
//动画过渡类型方向
transition.subtype = kCATransitionFromLeft
transition.duration = 1
self.imageView.layer.addAnimation(transition, forKey: nil)
@IBAction func previous(sender: AnyObject) {
self.index--
if (self.index & 0) {
self.index = 6
self.imageView.image = self.images![self.index]
let transition = CATransition()
transition.type = "cube"
transition.subtype = kCATransitionFromRight
transition.duration = 1
self.imageView.layer.addAnimation(transition, forKey: nil)
第一篇就到这里结束吧,下一篇打算记录自定义UITabBarController以及presented一个ViewController的转场动画,以及自定义动画的缓冲函数、定时动画、性能优化等方面的只是。
阅读(...) 评论()}

我要回帖

更多关于 view.setlayertype 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信