仿微信小视频(UI篇)

之前公司业务需要,功能需求:仿照微信朋友圈,可录制10s小视频,可拍照,并且对视频和图片进行压缩,今天正好有空,对以前的功能做一个记录。
因为时间紧迫,目前刚写出一个按钮,主要功能是点击拍照,长按录制视频。

功能实现分析:首先,按钮在点击的时候会拍照,这个可以使用UITapGestureRecognizer点击手势,并且在长按的时候按钮中间图形放大,外层圆环随着录制时间而变化,长按可以使用UILongPressGestureRecognizer长按手势,圆环变化可以使用核心动画,图层,贝塞尔曲线实现。

效果如下


image

核心代码:

  • 1.首先分成两个图层
       /** outerView外层圆环,长按时会随着时间变化 */
        _outerView = [[UIView alloc] initWithFrame:self.bounds];
        _outerView.layer.cornerRadius = self.width * 0.5;
        _outerView.backgroundColor = RGBColor(175, 175, 175);
        _outerView.alpha = 0.9;
        [self addSubview:_outerView];
        
        /** centerView内层圆环,长按时会缩小 */
        _centerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 55, 55)];
        _centerView.center = _outerView.center;
        _centerView.backgroundColor = [UIColor whiteColor];
        _centerView.layer.cornerRadius = _centerView.width * 0.5;
        [self addSubview:_centerView];
  • 2.添加手势和图层
        /** 长按手势 */
        UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
        [_centerView addGestureRecognizer:longPress];
        
        /** 点按手势 */
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
        
        /** 填充贝塞尔曲线宽度 */
        _width = 5;
        
        /** 添加图层 */
        _progressLayer = [[CAShapeLayer alloc] init];
        [_outerView.layer addSublayer:_progressLayer];
        _progressLayer.fillColor = nil;
        _progressLayer.lineCap = kCALineCapSquare;
        _progressLayer.frame = _outerView.bounds;
        _progressLayer.lineWidth = _width;
        _progressLayer.strokeColor = RGBColor(90, 165, 88).CGColor;
        
        /** 默认录制十秒 */
        self.duration = 10;
  • 3.长按手势动画实现

- (void)longPress:(UILongPressGestureRecognizer *)longPress
{
    /** 根据手势的不同状态,做出响应 */
    switch (longPress.state) {
        case UIGestureRecognizerStateBegan:{
            [UIView animateWithDuration:0.3 animations:^{
                _centerView.transform = CGAffineTransformMakeScale(0.7, 0.7);
                _outerView.transform = CGAffineTransformMakeScale(1.5, 1.5);
            }];
            [self start];
        }
            break;
            
        case UIGestureRecognizerStateEnded:{
            [UIView animateWithDuration:0.3 animations:^{
                _centerView.transform = CGAffineTransformMakeScale(1.0, 1.0);
                _outerView.transform = CGAffineTransformMakeScale(1.0, 1.0);
            }];
            [self stop];
        }
            
            break;
        
        case UIGestureRecognizerStateChanged:
            break;
            
        case UIGestureRecognizerStateCancelled:{
            
            [self stop];
        }
            
            break;
            
        default:
            break;
    }
    
}

//开启定时器
- (void)start
{
    _timer = [NSTimer scheduledTimerWithTimeInterval:_animatetionTime target:self selector:@selector(addProgress) userInfo:nil repeats:YES];
}



- (void)addProgress
{
    dispatch_async(dispatch_get_main_queue(), ^{
       
       //图层增加量
        _progress += _animatetionIncr;
        [self updateProgress];
        if (_progress > 1) {
            [self stop];
        }
    });
}

//在设置录制时间时,会计算图层每秒增加量,以及动画时间
- (void)setDuration:(NSInteger)duration
{
    _duration = duration;
    _animatetionTime = 1 / (CGFloat)(duration * duration);
    _animatetionIncr = 1 / (CGFloat)(duration * duration * duration);
    
}

//更新动画
- (void)updateProgress
{
    //绘制贝塞尔曲线
    UIBezierPath *progessPath = [UIBezierPath bezierPathWithArcCenter:_centerView.center radius:(_outerView.width - (1.5 * _width)) / 3 startAngle:(M_PI_2 * 3) endAngle:(M_PI * 2) *_progress + (-M_PI_2) clockwise:YES];
    
    _progressLayer.path = progessPath.CGPath;
}


- (void)setProgress
{
    _progress = 0;
    UIBezierPath *progessPath = [UIBezierPath bezierPathWithArcCenter:_centerView.center radius:(_outerView.width - (1.5 * _width)) / 3 startAngle:(M_PI_2 * 3) endAngle:-M_PI_2 clockwise:YES];
    
    _progressLayer.path = progessPath.CGPath;
}

//停止录制,废弃定时器
- (void)stop
{
    [_timer invalidate];
    _timer = nil;
    [self setProgress];
}


结尾:功能虽然不难,实现的方式也有很多种,需要注意的是对于手势中可能发生的状态做出相应的响应,以及对于定时器使用完后一定要销毁,下一篇将讲述视频录制以及压缩功能。

你可能感兴趣的:(仿微信小视频(UI篇))