CALayer、CGAffineTransform

CALayer、CGAffineTransform
可以看做显示图像的实际上是layer层。CALayer其中的三个动画的类:

1.CAAnimation创建一个CALayer层的动画,并且可以被layer调用addAnimation: forKey添加到自己的CALayer层动画,还可以设置动画开始和结束的代理方法。
2.CAPropertyAnimation这个类继承于CAAnimation,所以集成所有方法,并且有自己的方法,其中animationWithKeyPath:用于创建一个对于某一个特定layer属性变换的动画效果。
3.CABasicAnimation继承于CAPropertyAnimation同时增加了属性fromValue/toValue/byValue,可以用来修改比如透明度和扩张大小

-(void)doOpacity

{

    //需要使用CABasicAnimation

    CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"opacity"];

    [animation setFromValue:[NSNumber numberWithFloat:1.0]];

    [animation setToValue:[NSNumber numberWithFloat:0.5]];

    [animation setDuration:0.1];

     animation.repeatCount=50;

    [animation  setAutoreverses:YES];//回到最初状态

    [animation setRemovedOnCompletion:YES];//动画结束的时候移除,默认就是YES

    [bigImage.layer addAnimation:animation forKey:@"abc"];

}

扩张大小的时候使用[NSValue valueWithCGSize:]来代替[NSNumber numberWithFloat:]就可以
4.CAKeyframeAnimation关键帧,继承于CAPropertyAnimation,并且有自己的属性。其中有values和keyTimes可以存放关键帧的数据信息和时间信息。例如在网页里面乱飞的小广告可以使用这个

-(void)doFly

{


    CAKeyframeAnimation *animation=[CAKeyframeAnimation animationWithKeyPath:@"position"];

    NSArray *values=[NSArray arrayWithObjects:[NSValue valueWithCGPoint:CGPointMake(10020)],[NSValue valueWithCGPoint:CGPointMake(4080)],[NSValue valueWithCGPoint:CGPointMake(300260)],[NSValue valueWithCGPoint:CGPointMake(2040)],[NSValue valueWithCGPoint:CGPointMake(220100)], nil];

    [animation setValues:values];

    

    

    NSArray *times=[NSArray arrayWithObjects:[NSNumber numberWithFloat:0.3],[NSNumber numberWithFloat:0.5],[NSNumber numberWithFloat:0.6],[NSNumber numberWithFloat:0.7],[NSNumber numberWithFloat:0.3], nil];

    [animation setKeyTimes:times];

    [animation setDuration:5];

    [bigImage.layer addAnimation:animation forKey:@"iiuih"];



}


CAAnimationGroup动画允许几个动画同时发生,有一个属性animations,可以添加若干个动画,这些动画会同时发生,也是属于图层动画。
关键帧动画有一个属性是path,路径属性,UIBezierPath是贝塞尔曲线路径,可以把这个路径赋值给关键帧路径,它有属性fromPoint和toPoint具体使用的时候还要用到 – addQuadCurveToPoint:controlPoint:函数,具体用法参见API。

CGAffineTransform
iphone 中2d的仿射变换共有3种形式:
1 .Translate 位移对应方法有:CGAffineTransform CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty);       CGAffineTransform CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty);注:t 代表相对变换,tx,ty 代表相对位移
2 .Scale 缩放对应方法有:CGAffineTransform CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy);   CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy);注:t代表相对变换,sx,sy代表缩放倍数
3 .Rotate 旋转对应方法有:CGAffineTransform CGAffineTransformRotate(CGAffineTransform t, CGFloat angle);     CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle);注:t代表相对变换,angle代表相对弧度(角度)

2d仿射变换是相对于UIView来说的,在UIView.CALayer中则会使用到3d的仿射变换,用来实现3d的效果。

UIView 中,默认的反射变换值是:
const  CGAffineTransform CGAffineTransformIdentity;
当调用如下语句是,UIView 会还原到初始状态UIView.transform 
=  CGAffineTransformIdentity 一般来说,做第一次仿射变换时,都是相对于UIView当前的状态,那么第一次创建的时候应该:CGAffineTransform transform  =  CGAffineTransformTranslate(self.transform,tx,ty);

在根据触摸来控制仿射变换时,比如图片的移动,旋转,缩放等时,需要判断手势的移动。这里所有的点均表示相对触发触摸的UIView的位置 即 Point currentPoint 
=  [touch locationInView:touch.view];
1 .位移位移的主要思路是移动后的目标点到起始点的偏移量,这里需要两个信息,起始点和当前点起始点startPoint,当前点currentPoint那么偏移量 CGPoint offset  =  CGPointMake(currentPoint.x – startPoint.x,currentPoint.y – startPoint.y);于是可以调用 CGAffineTransformMakeTranslation(offset.x,offset.y);  1 )单点触摸时startPoint 是在touchBegan中唯一touch的坐标点currentPoint 是在touchMoved中唯一touch的坐标点 2 ) 多点触摸时多点触摸时,一般用2个点来定位,我们需要记录4个点,并且,需要确认2个touch,因为在触摸过程中,touch是随机排序的 touch1.startPoint,touch1.currentPoint,touch2.startPoint,touch2.currentPoint 那么:startPoint.x  = (touch2.startPoint.x + touch1.startPoint.x) /  2 ;     // 中心点 startPoint.y  = (touch2.startPoint.y + touch2.startPoint.y) /  2 ;     // 中心点 currentPoint 与 startPoint相同
2 . 缩放缩放的主要思路是移动后触摸两点的距离(向量)与开始两点的距离比,缩放必须要多点触摸,同样,我们需要记录4个点 touch1.startPoint,touch1.currentPoint,touch2.startPoint,touch2.currentPoint 那么,vector1  = sqrt( (touch2.startPoint.x – touch1.startPoint.x)^ 2  + (touch2.startPoint.y – touch1.startPoint.y)^ 2  );     // 起始向量长度 vector2  = sqrt( (touch2.currentPoint.x – touch1.currentPoint.x)^ 2  + (touch2.currentPoint.y – touch1.currentPoint.y)^ 2  );于是,缩放 float  scale = vector2 / vector1;     // 在这里我们会使用x,y使用同一个缩放值 可以调用 CGAffineTransformMakeScale(scale,scale) 来进行缩放了。
3 . 旋转旋转的主要思路是移动后触摸两点的向量相对于开始两点的偏移角度(弧度),需要必须多点触摸,同样我们需要记录4个点 touch1.startPoint,touch1.currentPoint,touch2.startPoint,touch2.currentPoint 那么:angle1  = atan( (touch2.startPoint.y – touch1.startPoint.y) / (touch2.startPoint.x – touch1.startPoint.x) );     // 求起始向量相对于x轴的角度 angle2  = atan( (touch2.currentPoint.y – touch1. currentPoint.y) / (touch2. currentPoint.x – touch1. currentPoint.x) );     // 求当前向量相对于x轴的角度  那么 偏移角度angle  =  angle2 – angle1;可以调用CGAffineTransformMakeRotation(angle)实现旋转.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为下列代码实现可暂停效果: import UIKit class ViewController: UIViewController { private let radarAnimation = "radarAnimation" private var animationLayer: CALayer? private var animationGroup: CAAnimationGroup? private var opBtn: UIButton! override func viewDidLoad() { super.viewDidLoad() let first = makeRadarAnimation(showRect: CGRect(x: 120, y: 100, width: 100, height: 100), isRound: true) view.layer.addSublayer(first) opBtn = UIButton(frame: CGRect(x: 100, y: 450, width: 80, height: 80)) opBtn.backgroundColor = UIColor.red opBtn.clipsToBounds = true opBtn.setTitle("Hsu", for: .normal) opBtn.layer.cornerRadius = 10 view.addSubview(opBtn) let second = makeRadarAnimation(showRect: opBtn.frame, isRound: false) view.layer.insertSublayer(second, below: opBtn.layer) } @IBAction func startAction(_ sender: UIButton) { animationLayer?.add(animationGroup!, forKey: radarAnimation) } @IBAction func stopAction(_ sender: UIButton) { animationLayer?.removeAnimation(forKey: radarAnimation) } private func makeRadarAnimation(showRect: CGRect, isRound: Bool) -> CALayer { // 1. 一个动态波 let shapeLayer = CAShapeLayer() shapeLayer.frame = showRect // showRect 最大内切圆 if isRound { shapeLayer.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: showRect.width, height: showRect.height)).cgPath } else { // 矩形 shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: showRect.width, height: showRect.height), cornerRadius: 10).cgPath } shapeLayer.fillColor = UIColor.orange.cgColor // 默认初始颜色透明度 shapeLayer.opacity = 0.0 animationLayer = shapeLayer // 2. 需要重复的动态波,即创建副本 let replicator = CAReplicatorLayer() replicator.frame = shapeLayer.bounds replicator.instanceCount = 4 replicator.instanceDelay = 1.0 replicator.addSublayer(shapeLayer) // 3. 创建动画组 let opacityAnimation = CABasicAnimation(keyPath: "opacity") opacityAnimation.fromValue = NSNumber(floatLiteral: 1.0) // 开始透明度 opacityAnimation.toValue = NSNumber(floatLiteral: 0) // 结束时透明底 let scaleAnimation = CABasicAnimation(keyPath: "transform") if isRound { scaleAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DScale(CATransform3DIdentity, 0, 0, 0)) // 缩放起始大小 } else { scaleAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0)) // 缩放起始大小 } scaleAnimation.toValue = NSValue.init(caTransform3D: CATransform3DScale(CATransform3DIdentity, 1.5, 1.5, 0)) // 缩放结束大小 let animationGroup = CAAnimationGroup() animationGroup.animations = [opacityAnimation, scaleAnimation] animationGroup.duration = 3.0 // 动画执行时间 animationGroup.repeatCount = HUGE // 最大重复 animationGroup.autoreverses = false self.animationGroup = animationGroup shapeLayer.add(animationGroup, forKey: radarAnimation) return replicator } }
06-03

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值