看到手機中天氣閃電效果挺炫酷的,就想試著實現(xiàn)其效果,費了一番功夫,實現(xiàn)了大致的效果,還有許多地方需要改進.
使用到的有UIBezierPath,CAShapeLayer,CABasicAnimation,CAAnimationGroup等.
實現(xiàn)的大致思路,就是需要繪制出閃電的路徑,包括主干路徑和分支路徑,最后添加動畫效果.
要想繪制路徑就需要知道路徑的點,在網(wǎng)上搜索到一個方法可以得到閃電的路徑的點.如下:
/**
* ?設(shè)置閃電的主干的點
*/
- (void)setupLightPointArrWithStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint displace:(CGFloat)displace
{
CGFloat midX = startPoint.x;
CGFloat midY = startPoint.y;
[pointArr removeAllObjects];
[pointArr addObject:NSStringFromCGPoint(startPoint)];
while (midY < endPoint.y)
{
if (startPoint.x < ?kScreenWidth/2 )
{
midX += (arc4random()%3 - 0.5)*displace;
midY += (arc4random()%5 - 0.5)*displace;
}else
{
midX -= (arc4random()%3 - 0.5)*displace;
midY += (arc4random()%5 - 0.5)*displace;
}
[pointArr addObject:NSStringFromCGPoint(CGPointMake(midX, midY))];
}
}
其中閃電分支的獲取點也是如此.
注意:其中分支的起點是主干上的點.當(dāng)然也可以不是.
需要的點都已經(jīng)獲取到了,就需要繪制了.
/**
* ?設(shè)置閃電的路徑
*/
- (void)setupLightningPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
[bezierPathArr addObject:path];
CGPoint point ;
for (int i = 0; i < pointArr.count; i ++)
{
point = CGPointFromString(pointArr[i]);
if (i == 0)
{
//畫線,設(shè)置起點
[path moveToPoint:point];
}else
{
//設(shè)置第二個條線的終點,會自動把上一個終點當(dāng)做起點
[path addLineToPoint:point];
}
NSLog(@"-----point%@ ",NSStringFromCGPoint(point));
if ([branchLightningStartPointArr containsObject:NSStringFromCGPoint(point)])
{
NSMutableArray *branchPointArr = [self setupBranchLightningPathPointWithStartPoint:CGPointMake(point.x, point.y) endPoint:CGPointMake(point.x + 100, point.y + 100) displace:1];
UIBezierPath *branchPath = [UIBezierPath bezierPath];
CGPoint branchPoint;
for (int j = 0; j < branchPointArr.count; j ++)
{
branchPoint = CGPointFromString(branchPointArr[j]);
if (j == 0)
{
//畫線,設(shè)置起點
[branchPath moveToPoint:branchPoint];
}else
{
//設(shè)置第二個條線的終點,會自動把上一個終點當(dāng)做起點
[branchPath addLineToPoint:branchPoint];
}
}
[bezierPathArr addObject:branchPath];
}
}
}
閃電的路徑繪制完成以后就需要實現(xiàn)其動畫效果.
/**
* ?設(shè)置閃電的動畫效果
*/
- (void)setupLightningAnimation
{
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 0.2;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
pathAnimation.repeatCount = 1;
//透明度
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.0];
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.duration = 1.0;
groupAnimation.animations = @[[self opacityForever_Animation:0.1], pathAnimation,opacityAnimation];
groupAnimation.autoreverses = YES;
groupAnimation.repeatCount = 1;
for (int i = 0; i < bezierPathArr.count; i ++)
{
UIBezierPath *path = bezierPathArr[i];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [[UIColor whiteColor] CGColor];
pathLayer.fillColor = nil;
pathLayer.lineWidth = (i == 0?1.0f:0.5);
pathLayer.lineJoin = kCALineJoinMiter;
[self.layer addSublayer:pathLayer];
[pathLayer addAnimation:groupAnimation forKey:@"xxx"];
}
}
至此動畫簡單的閃電效果已經(jīng)完成了.還有許多地方需要繼續(xù)完善.
更新了demo效果如下:
上傳到了Github:https://github.com/ITXIN/AnimationShow