澎湃iPad上线版本

RubberBandView.m 7.7KB

    // // RubberBandView.m // RubberBandView // // Created by JianYe on 14-7-1. // Copyright (c) 2014年 XiaoZi. All rights reserved. // #import "RubberBandView.h" #import <QuartzCore/QuartzCore.h> static CFTimeInterval defaultDuration = 0.3; //加速度 static float acceleration(float time,float space) { return space*2/(time*time); } @interface RubberBandView () { CFTimeInterval _beginTime; CFTimeInterval _animationRegisteredTime; CADisplayLink *_link; RubberBandProperty _currentProperty; RubberBandProperty _beginProperty; BOOL isHorizontal; } @property (nonatomic,strong)CAShapeLayer *drawLayer; @end @implementation RubberBandView - (void)dealloc { if (_link) [_link invalidate]; } #pragma mark - #pragma mark init - (void)awakeFromNib { [super awakeFromNib]; [self _init]; } - (id)initWithFrame:(CGRect)frame layerProperty:(RubberBandProperty)property { if (self = [super initWithFrame:frame]) { [self _init]; self.property = property; } return self; } - (void)_init { self.drawLayer = [CAShapeLayer layer]; [self.layer addSublayer:_drawLayer]; _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeUpdate:)]; _link.paused = YES; [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } #pragma mark - #pragma mark attributes - (void)setProperty:(RubberBandProperty)property { _property = property; [self resetDefault]; } - (void)setFillColor:(UIColor *)fillColor { _fillColor = fillColor; if (_drawLayer) _drawLayer.fillColor = fillColor.CGColor; [self resetDefault]; } - (void)resetDefault { _beginProperty = CopyRBProperty(_property); UIBezierPath *path = [self pullPathWithOffset:0 toOut:YES]; [self redrawWithPath:path.CGPath]; } #pragma mark - #pragma mark action - (void)pullWithOffSet:(CGFloat)offSet { UIBezierPath *path = [self pullPathWithOffset:offSet toOut:YES]; [self redrawWithPath:path.CGPath]; } - (void)recoverStateAnimation { _beginProperty = CopyRBProperty(_currentProperty); if (_duration == 0) _duration = defaultDuration; _beginTime = 0; _animationRegisteredTime = [_drawLayer convertTime:CACurrentMediaTime() fromLayer:nil]; if (_link) _link.paused = NO; } #pragma mark - #pragma mark path - (UIBezierPath *)pullPathWithOffset:(CGFloat)currentOffset toOut:(BOOL)toOut{ if (_beginProperty.width<=0||_beginProperty.height<=0) return nil; CGFloat width,orignX; if (toOut) { width = _beginProperty.width + fabs(currentOffset); orignX = _beginProperty.x + ((currentOffset<0)?currentOffset:0); }else { width = _property.width + currentOffset; orignX = _beginProperty.x; } CGFloat height = _beginProperty.height * fabs(_beginProperty.width/width); CGFloat orignY = _beginProperty.y + (_beginProperty.height - height); CGFloat radius = height/2; _currentProperty = MakeRBProperty(orignX, orignY, width, height, _beginProperty.maxOffSet); UIBezierPath *path; path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(orignX, orignY, width, height) byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; return path; } - (UIBezierPath *)bounceInPathWithOffset:(CGFloat)currentOffset { if (_beginProperty.width<=0||_beginProperty.height<=0|| _property.width<=0||_property.height<=0) return nil; CGFloat width = _beginProperty.width - currentOffset; CGFloat x = fabs(_property.width/width); if (x>1.5) x = 1.2; CGFloat height = _property.height * x; CGFloat orignX = _beginProperty.x + currentOffset; CGFloat orignY = _property.y + (_property.height - height); CGFloat radius = height/2; _currentProperty = MakeRBProperty(orignX, orignY, width, height, _property.maxOffSet); CGRect rect = CGRectMake(orignX, orignY, width, height); UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; return path; } #pragma mark - #pragma mark animation - (void)render { CFTimeInterval time = [_drawLayer convertTime:CACurrentMediaTime() fromLayer:nil]; if (time - _animationRegisteredTime < _beginTime)return; float runtime = time - _beginTime - _animationRegisteredTime; if (runtime >= _duration) { _link.paused = YES; [self animationStop]; return; } if (_startAction) _startAction(); CGPathRef path; float partTime1 = _duration/2; float partTime2 = (_duration - partTime1)/2; float partTime3 = (_duration - partTime1 - partTime2); float partSpace1 = 0 , partSpace2 = 0 , partSpace3 = 0, partOrign = 0; float offSet = (_beginProperty.width - _property.width);//拉伸距离 float offOrign = _beginProperty.x - _property.x; float x = offSet/_property.width;//内缩倍数 if (x>1) x = 1; float inset = x * (_property.width/2);//对比正常内缩距离,系数 * 正常宽度的一半 if ((offSet >= _property.maxOffSet && offOrign >= 0) || (offSet < _property.maxOffSet && offOrign < 0)) { partSpace1 = _beginProperty.width - (_property.width - inset);//总回弹距离 partSpace2 = inset + x*(_property.width/3);//第二次弹出距离 partSpace3 = x*(_property.width/3);//回到正常的距离 partOrign = (_beginProperty.width - _property.width - partSpace3); if(runtime<=partTime1)//拉倒极限后反弹 { float time = runtime; float a = acceleration(partTime1,partSpace1); float space = a*time*time/2; path = [self bounceInPathWithOffset:space].CGPath; }else if(runtime <= partTime1+partTime2) { float time = runtime-partTime1; float a = acceleration(partTime2,partSpace2); float space = a*time*time/2; path = [self bounceInPathWithOffset:partSpace1 - space].CGPath; }else { float time = runtime-partTime1-partTime2; float a = acceleration(partTime3,partSpace3); float space = a*time*time/2; path = [self bounceInPathWithOffset:partOrign + space].CGPath; } }else { partSpace1 = _beginProperty.width - _property.width + inset;//总回弹距离 partSpace2 = inset + x*(_property.width/3);//第二次弹出距离 partSpace3 = x*(_property.width/3);//回到正常的距离 if(runtime<=partTime1)//拉倒极限后反弹 { float time = runtime; float a = acceleration(partTime1,partSpace1); float space = a*time*time/2; path = [self pullPathWithOffset:offSet - space toOut:NO].CGPath; }else if(runtime <= partTime1+partTime2) { float time = runtime-partTime1; float a = acceleration(partTime2,partSpace2); float space = a*time*time/2; path = [self pullPathWithOffset:- inset + space toOut:NO].CGPath; }else { float time = runtime-partTime1-partTime2; float a = acceleration(partTime3,partSpace3); float space = a*time*time/2; path = [self pullPathWithOffset:partSpace3 - space toOut:NO].CGPath; } } [self redrawWithPath:path]; } - (void)animationStop { _beginProperty = CopyRBProperty(_currentProperty); _property.x = _beginProperty.x; if(_stopAction) _stopAction(); } #pragma mark - #pragma mark redraw - (void)redrawWithPath:(CGPathRef)path { _drawLayer.path = path; } #pragma mark - #pragma mark animation transaction for ftp - (void)timeUpdate:(CADisplayLink *)link { [self updateLayer]; } - (void)updateLayer { [self render]; } @end