How to change color of CAGradientLayer like screensaver?

旧时模样 提交于 2019-12-12 12:11:17

问题


I was created UIView with applying CAGradientLayer color effect as i attached Image Bellow. Now in this i want to change it's gradient color change top to bottom side smoothly like screensaver. I have Been tried using NStimer that bit Done but its changing color in CAGradientLayer look like jerk.

For above I have use Bellow method of Code:-

Timer =  [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(TIMER) userInfo:nil repeats:NO];

-(void)TIMER
{
        Count++;
        [view_Color1 removeFromSuperview];

        view_Color1 = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 341)];
        CAGradientLayer *gradient = [CAGradientLayer layer];
        gradient.frame = self.view_Color.bounds;

        if (Count == 1)
        {
            gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor greenColor] CGColor], (id)[[UIColor  colorWithRed:44/255.0 green:255/255.0 blue:255/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:0/255.0 green:0/255.0 blue:254/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:252/255.0 green:0/255.0 blue:255/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:252/255.0 green:0/255.0 blue:6/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:253/255.0 green:131/255.0 blue:6/255.0 alpha:1.0f]CGColor], (id)[[UIColor  colorWithRed:255/255.0 green:237/255.0 blue:10/255.0 alpha:1.0f]CGColor], nil];
        }
        else if (Count == 2)
        {
            gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor  colorWithRed:255/255.0 green:237/255.0 blue:10/255.0 alpha:1.0f]CGColor],(id)[[UIColor greenColor] CGColor], (id)[[UIColor  colorWithRed:44/255.0 green:255/255.0 blue:255/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:0/255.0 green:0/255.0 blue:254/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:252/255.0 green:0/255.0 blue:255/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:252/255.0 green:0/255.0 blue:6/255.0 alpha:1.0f] CGColor], (id)[[UIColor  colorWithRed:253/255.0 green:131/255.0 blue:6/255.0 alpha:1.0f]CGColor],nil];
        }
        //and so on still count is 7 then again its 1 to continue here are count use for chagen 7 color gradient use and repeat.

        [self.view addSubview:view_Color1];
        [self.view_Color1.layer addSublayer:gradient];

        [myappdelegare sharedinstance].str_LastColorClick = [[NSString alloc]initWithFormat:@"MultiColor"];
        Timer =  [NSTimer scheduledTimerWithTimeInterval:0.30 target:self selector:@selector(TIMER) userInfo:nil repeats:NO];

}

Can you please help me?

Thanks


回答1:


I did not noticed first that you are "jumping" with colors at every step.

Here is a code which does the animation:

- (void) initGradient
{
    if ( !gradient ) {
        gradient = [CAGradientLayer layer];
        gradient.frame = self.view.bounds;
        [self.view.layer addSublayer:gradient];

        NSArray *baseColors = [NSArray arrayWithObjects:(id)[UIColor yellowColor].CGColor, (id)[UIColor redColor].CGColor, (id)[UIColor blueColor].CGColor, (id)[UIColor greenColor].CGColor, nil];
        NSMutableArray *colors = [NSMutableArray arrayWithArray:baseColors];
        [colors addObjectsFromArray:baseColors];
        gradient.colors = colors;

        cnt = [baseColors count];

        NSMutableArray *locations = [NSMutableArray array];
        CGFloat step = 1. / (cnt - 1.);
        CGFloat loc = 0;
        for ( NSUInteger i = 0; i < [colors count]; i++ ) {
            [locations addObject:@(loc)];
            loc += step;
        }
        gradient.locations = [locations copy];
    }
}

-(void)TIMER
{
    NSMutableArray *locations = [NSMutableArray array];
    CGFloat step = 1. / (cnt - 1.);
    static const CGFloat speed = 3;
    CGFloat initialStep = speed / gradient.bounds.size.height;
    CGFloat loc = [gradient.locations[0] floatValue] - initialStep;
    if ( loc <= -1 - step )
        loc = initialStep;
    for ( NSUInteger i = 0; i < [gradient.locations count]; i++ ) {
        [locations addObject:@(loc)];
        loc += step;
    }

    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue
                     forKey:kCATransactionDisableActions];
    gradient.locations = [locations copy];
    [CATransaction commit];

    Count++;
    if ( Count >= [gradient.colors count] )
        Count = 0;

    [self performSelector:@selector(TIMER) withObject:nil afterDelay:0.04];
}

It still has an small issue, that the top pixel of the view gets a mixed color but animates nicely. You can adjust the speed as well (static CGFloat speed). I leave it up to you to solve - maybe clip.




回答2:


If you want to animate layer properties do not use NSTimer, use one of the classes of CAAnimation 'family'. In your case if you want to animate between several different gradients then CAKeyFrameAnimation is the right choice. Sample code to add layer animation to gradient layer:

- (void) addColorsAnimationToGradientLayer:(CAGradientLayer*)glayer {
    NSMutableArray *colors = [glayer.colors mutableCopy];
    NSMutableArray *animationColors = [@[] mutableCopy];
    for (int i = 0; i < colors.count; ++i) {
        [animationColors addObject:[colors copy]];
        id lastColor = [colors lastObject];
        [colors removeObjectAtIndex:colors.count-1];
        [colors insertObject:lastColor atIndex:0];
    }

    CAKeyframeAnimation *kfAnimation = [CAKeyframeAnimation animationWithKeyPath:@"colors"];
    kfAnimation.values = animationColors;
    kfAnimation.duration = 5.0f;
    kfAnimation.repeatCount = HUGE_VALF;
    kfAnimation.autoreverses = YES;
    [glayer addAnimation:kfAnimation forKey:@"colors"];
}

In the code listed above I create infinitely looping animation where gradient colors are obtained using cyclic permutation of colors in initial gradient:

KeyFrame0: [color0, color1, color2,…, colorN]
KeyFrame1: [colorN, color0, color1, color2,…, colorN-1]
…
KeyFrame(N-1): [color1, color2, color3,…, color0]


来源:https://stackoverflow.com/questions/20016213/how-to-change-color-of-cagradientlayer-like-screensaver

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!