You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

183 lines
5.9 KiB

//
// WXReaderAnimationLayer.m
// WXReader
//
// Created by Andrew on 2018/6/8.
// Copyright © 2018年 Andrew. All rights reserved.
//
#import "WXYZ_ReaderAnimationLayer.h"
#import "TFReaderSettingHelper.h"
#define animationKey @"wxreader_animation_layer_key"
@interface WXYZ_ReaderAnimationLayer () <CAAnimationDelegate>
{
CFTimeInterval _animationDuration;
UIView *_layerView;
}
@property (nonatomic, assign) WXReaderAnimationState state;
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@property (nonatomic, strong) CABasicAnimation *pathAnimation;
@end
@implementation WXYZ_ReaderAnimationLayer
- (instancetype)initWithView:(UIView *)keyView
{
if (self = [super init]) {
_layerView = keyView;
_animationDuration = [[TFReaderSettingHelper sharedManager] getReadSpeed];
}
return self;
}
// 开始动画
- (void)startReadingAnimation
{
self.state = WXReaderAnimationStateRunning;
[self.shapeLayer addAnimation:self.pathAnimation forKey:animationKey];
[_layerView.layer addSublayer:self.shapeLayer];
}
//暂停动画
- (void)pauseAnimation
{
self.state = WXReaderAnimationStatePausing;
CFTimeInterval pausedTime = [self.shapeLayer convertTime:CACurrentMediaTime() fromLayer:nil];
self.shapeLayer.speed = 0.0;
self.shapeLayer.timeOffset = pausedTime;
}
//继续动画
- (void)resumeAnimation
{
if (self.state == WXReaderAnimationStateStoped) {
[self startReadingAnimation];
}
self.state = WXReaderAnimationStateRunning;
CFTimeInterval pausedTime = [self.shapeLayer timeOffset];
self.shapeLayer.speed = 1.0;
self.shapeLayer.timeOffset = 0.0;
self.shapeLayer.beginTime = 0.0;
CFTimeInterval timeSincePause = [self.shapeLayer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
self.shapeLayer.beginTime = timeSincePause;
}
// 停止动画
- (void)stopAnimation
{
self.state = WXReaderAnimationStateStoped;
self.pathAnimation = nil;
[self.shapeLayer removeAnimationForKey:animationKey];
[self.shapeLayer removeFromSuperlayer];
self.shapeLayer = nil;
}
// 重启动画
- (void)resetAnimation
{
if (self.state == WXReaderAnimationStateRunning) {
[self resetDuration:_animationDuration];
}
}
// 重置时间
- (void)resetDuration:(CFTimeInterval)animationDuration
{
_animationDuration = animationDuration;
if (self.state == WXReaderAnimationStatePausing || self.state == WXReaderAnimationStateStoped) {
[self stopAnimation];
return;
}
[self startReadingAnimation];
}
// 动画代理回调
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
if (flag == YES) {
[self.shapeLayer addAnimation:self.pathAnimation forKey:animationKey];
if (self.state == WXReaderAnimationStateRunning && self.readerAutoReadBlock) {
self.readerAutoReadBlock();
}
}
}
- (UIBezierPath *)layerPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
if (is_iPhoneX) {
CGFloat lineWidth = 2;
// 屏幕左上角圆角半径
CGFloat radius1 = 44;
// 刘海顶部圆角半径
CGFloat radius2 = 6;
// 刘海底部圆角半径
CGFloat radius3 = 20;
// 刘海高度
CGFloat hairHeight = 30;
// 刘海顶部宽度
CGFloat hairTopWidth = 209;
// 刘海左侧空隙
CGFloat hairLeftWidth = (SCREEN_WIDTH - hairTopWidth) / 2;
// 刘海右侧空隙
CGFloat hairRightWidth = hairLeftWidth;
[path moveToPoint:CGPointMake(lineWidth, radius1)];
[path addQuadCurveToPoint:CGPointMake(radius1, lineWidth) controlPoint:CGPointMake(lineWidth, lineWidth)];
[path addLineToPoint:CGPointMake(hairLeftWidth - radius2, lineWidth)];
[path addQuadCurveToPoint:CGPointMake(hairLeftWidth - lineWidth, radius2) controlPoint:CGPointMake(hairLeftWidth - lineWidth, lineWidth)];
[path addLineToPoint:CGPointMake(hairLeftWidth - lineWidth, hairHeight - radius3)];
[path addQuadCurveToPoint:CGPointMake(hairLeftWidth + radius3, hairHeight + lineWidth) controlPoint:CGPointMake(hairLeftWidth, hairHeight)];
[path addLineToPoint:CGPointMake(SCREEN_WIDTH - hairRightWidth - radius3, hairHeight + lineWidth)];
[path addQuadCurveToPoint:CGPointMake(SCREEN_WIDTH - hairRightWidth + lineWidth, hairHeight - radius3) controlPoint:CGPointMake(SCREEN_WIDTH - hairRightWidth, hairHeight)];
[path addLineToPoint:CGPointMake(SCREEN_WIDTH - hairRightWidth + lineWidth, radius2)];
[path addQuadCurveToPoint:CGPointMake(SCREEN_WIDTH - hairRightWidth + radius2, lineWidth) controlPoint:CGPointMake(SCREEN_WIDTH - hairRightWidth + lineWidth, lineWidth)];
[path addLineToPoint:CGPointMake(SCREEN_WIDTH - radius1, lineWidth)];
[path addQuadCurveToPoint:CGPointMake(SCREEN_WIDTH - lineWidth, radius1) controlPoint:CGPointMake(SCREEN_WIDTH - lineWidth, lineWidth)];
} else {
[path moveToPoint:CGPointMake(0, 2)];
[path addLineToPoint:CGPointMake(SCREEN_WIDTH,2)];
}
return path;
}
- (CAShapeLayer *)shapeLayer
{
if (!_shapeLayer) {
_shapeLayer = [CAShapeLayer layer];
_shapeLayer.lineWidth = 4;
_shapeLayer.fillColor = [[UIColor clearColor] CGColor];
_shapeLayer.strokeColor = kColorRGBA(255, 102, 0, 1).CGColor;
_shapeLayer.path = [self layerPath].CGPath;
}
return _shapeLayer;
}
- (CABasicAnimation *)pathAnimation
{
if (!_pathAnimation) {
_pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
_pathAnimation.duration = _animationDuration;
_pathAnimation.repeatCount = 1;
_pathAnimation.delegate = self;
_pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
_pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
}
return _pathAnimation;
}
@end