• 自定义缓冲函数


    基于关键帧的缓冲(keyTimes)

    为了使用关键帧实现反弹动画,我们需要在缓冲曲线中对每一个显著的点创建一个关键帧(在这个情况下,关键点也就是每次反弹的峰值),然后应用缓冲函数把每 段曲线连接起来。同时,我们也需要通过keyTimes来指定每个关键帧的时间偏移,由于每次反弹的时间都会减少,于是关键帧并不会均匀分布。

    清单10.6 使用关键帧实现反弹球的动画

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        doorLayer=[CALayer layer];
        doorLayer.frame=CGRectMake(200, 200, 100, 100);
        doorLayer.backgroundColor=[UIColor redColor].CGColor;
        doorLayer.cornerRadius=50;
        doorLayer.masksToBounds=YES;
        [self.view.layer addSublayer:doorLayer];

    }
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {

        doorLayer.position = CGPointMake(150, 32);
        //create keyframe animation
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
        animation.keyPath = @"position";
        animation.duration = 5.0;
        animation.delegate = self;
        animation.values = @[
                             [NSValue valueWithCGPoint:CGPointMake(150, 32)],
                             [NSValue valueWithCGPoint:CGPointMake(150, 268)],
                             [NSValue valueWithCGPoint:CGPointMake(150, 140)],
                             [NSValue valueWithCGPoint:CGPointMake(150, 268)],
                             [NSValue valueWithCGPoint:CGPointMake(150, 220)],
                             [NSValue valueWithCGPoint:CGPointMake(150, 268)],
                             [NSValue valueWithCGPoint:CGPointMake(150, 250)],
                             [NSValue valueWithCGPoint:CGPointMake(150, 268)]
                             ];
        animation.timingFunctions = @[
                                      [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn],
                                      [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut],
                                      [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn],
                                      [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut],
                                      [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn],
                                      [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut],
                                      [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn]
                                      ];
        animation.keyTimes = @[@0.0, @0.3, @0.5, @0.7, @0.8, @0.9, @0.95, @1.0];
        //apply animation
        doorLayer.position = CGPointMake(150, 268);
        [doorLayer addAnimation:animation forKey:nil];

    }

    流程自动化

    @interface ViewController ()
    {
        CALayer *doorLayer;
    }
    @end
    @implementation ViewController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        doorLayer=[CALayer layer];
        doorLayer.frame=CGRectMake(200, 200, 100, 100);
        doorLayer.backgroundColor=[UIColor redColor].CGColor;
        doorLayer.cornerRadius=50;
        doorLayer.masksToBounds=YES;
        [self.view.layer addSublayer:doorLayer];
        
    }
    float interpolate(float from, float to, float time)
    {
        return (to - from) * time + from;
    }
    - (id)interpolateFromValue:(id)fromValue toValue:(id)toValue time:(float)time
    {
        if ([fromValue isKindOfClass:[NSValue class]]) {
            //get type
            const char *type = [fromValue objCType];
            if (strcmp(type, @encode(CGPoint)) == 0) {
                CGPoint from = [fromValue CGPointValue];
                CGPoint to = [toValue CGPointValue];
                CGPoint result = CGPointMake(interpolate(from.x, to.x, time), interpolate(from.y, to.y, time));
                return [NSValue valueWithCGPoint:result];
            }
        }
        //provide safe default implementation
        return (time < 0.5)? fromValue: toValue;
    }
    - (void)animate
    {
        //reset ball to top of screen
        doorLayer.position = CGPointMake(150, 32);
        //set up animation parameters
        NSValue *fromValue = [NSValue valueWithCGPoint:CGPointMake(150, 32)];
        NSValue *toValue = [NSValue valueWithCGPoint:CGPointMake(200, 268)];
        CFTimeInterval duration = 1;
        //generate keyframes
        NSInteger numFrames = duration * 60;
        NSMutableArray *frames = [NSMutableArray array];
        for (int i = 0; i < numFrames; i++) {
            float time = 1/(float)numFrames * i;
            //apply easing
            time = bounceEaseOut(time);
            //add keyframe
            [frames addObject:[self interpolateFromValue:fromValue toValue:toValue time:time]];
        }
        //create keyframe animation
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
        animation.keyPath = @"position";
        animation.duration = 5.0;
        animation.delegate = self;
        animation.values = frames;
        //apply animation
        doorLayer.position = CGPointMake(200, 268);
        [doorLayer addAnimation:animation forKey:nil];
    }
    float bounceEaseOut(float t)
    {
        if (t < 4/11.0) {
            return (121 * t * t)/16.0;
        } else if (t < 8/11.0) {
            return (363/40.0 * t * t) - (99/10.0 * t) + 17/5.0;
        } else if (t < 9/10.0) {
            return (4356/361.0 * t * t) - (35442/1805.0 * t) + 16061/1805.0;
        }
        return (54/5.0 * t * t) - (513/25.0 * t) + 268/25.0;
    }
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        
        [self animate];
        
    }

  • 相关阅读:
    [OS] 修改屏幕分辨率(用Remote Desktop Connection 或者 用工具:Remote Desktop Connection Manager)
    英文单词通用缩写表
    [Selenium] 怎样判断是否适合自动化测试
    [Selenium] Java代码获取,设置屏幕分辨率
    [Selenium] Java代码获取屏幕分辨率
    [Selenium] 最大化或自定义浏览器的大小
    跟我一起玩Win32开发(7):多边形窗口
    跟我一起玩Win32开发(5):具有单选标记的菜单
    跟我一起玩Win32开发(6):创建右键菜单
    跟我一起玩Win32开发(4):创建菜单
  • 原文地址:https://www.cnblogs.com/jingdizhiwa/p/5526199.html
Copyright © 2020-2023  润新知