追光动效实现
效果如下:
实现:
如下图,红框为一个UIVIew
,CAGradientLayer
的startPoint
和endPoint
的取值是(0,0)
到(1,1)
。
先实现简单的渐变效果,将红色和蓝色放入colors
,从左上角到右下角渐变:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 150, 300, 188)];
view.layer.cornerRadius = 4.0;
view.layer.masksToBounds = YES;
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = view.bounds;
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,
(__bridge id)[UIColor blueColor].CGColor];
gradientLayer.startPoint = CGPointMake(0.0, 0.0);
gradientLayer.endPoint = CGPointMake(1.0, 1.0);
[view.layer addSublayer:gradientLayer];
[self.view addSubview:view];
效果如下:
为了实现渐变的动态效果,可以将红色和蓝色的坐标以对角线的形式,沿着UIView
的边框顺时针移动坐标:
如:红点移动到(0.5,0)
时,蓝点移动到(0.5,1)
。。。。
为此,顺时针算出所有的坐标:
- (NSArray *)sidePoints {
NSMutableArray *points = [NSMutableArray array];
CGFloat min = 0.0;
CGFloat max = 1.0;
CGFloat spacing = 0.5;
// top side
for (CGFloat x = min; x <= max; x = spacing) {
[points addObject:@[@(x), @(0)]];
}
// right side
for (CGFloat y = min spacing; y <= max; y = spacing) {
[points addObject:@[@(1), @(y)]];
}
// bottom side
for (CGFloat x = max - spacing; x >= min; x -= spacing) {
[points addObject:@[@(x), @(1)]];
}
// left side
for (CGFloat y = max - spacing; y >= min; y -= spacing) {
[points addObject:@[@(0), @(y)]];
}
return [points copy];
}
然后用NSTimer
不停的更换startPoint
和endPoint
的坐标:
__block NSUInteger index = 0;
_timer = [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSUInteger redIndex = index % (points.count - 1);
NSUInteger yelIndex = (index (points.count / 2 1)) % (points.count - 1);
NSArray *redArr = points[redIndex];
NSArray *yelArr = points[yelIndex];
NSNumber *redX = redArr[0];
NSNumber *redY = redArr[1];
NSNumber *yelX = yelArr[0];
NSNumber *yelY = yelArr[1];
gradientLayer.startPoint = CGPointMake(redX.floatValue, redY.floatValue);
gradientLayer.endPoint = CGPointMake(yelX.floatValue, yelY.floatValue);
index ;
index = index % (points.count - 1);
}];
[_timer setFireDate:[NSDate date]];
效果如下:
为了让动效更湿滑,可以把sidePoints
方法里的spacing
改小。
然后将图盖在上面,最终效果如下:
Github Demo 地址