iOS - 用UIBezierPath實現(xiàn)果凍效果

最近在網(wǎng)上看到一個很酷的下拉刷新效果(http://iostuts.io/2017/10/17/elastic-bounce-using-uibezierpath-and-pan-gesture/)验残。自己試著實現(xiàn)了一下其中的果凍回彈效果。

效果

elasticDemo.gif

DEMO由于文筆不太好-.- 督怜,建議先下載demo,再結(jié)合下面的分析先紫,會好理解點巷燥。地址https://github.com/Resory/RYCuteView邏輯

下圖p1,藍色部分圖形是一個CAShapeLayer,他的形狀由UIBezierPath的路徑組成的候址。

這個路徑是由r1,r2,r3,r4,r5這5個紅點確定的。其中r1,r2,r3,r4都是不動點庭敦,唯一可以動的是r5點匿情。

根據(jù)上面的動態(tài)圖可以看出,CAShapeLayer的形狀是隨著r5紅點的移動而相應變化的兰迫,所以只要獲得r5的坐標變化就可以用UIBezierPath做出相應的路徑,然后就可以形成相應的形狀炬称。

p1.jpg

實現(xiàn)初始化CAShapeLayer

- (void)configShapeLayer{     _shapeLayer = [CAShapeLayer layer];    _shapeLayer.fillColor = [UIColor colorWithRed:57/255.0 green:67/255.0 blue:89/255.0 alpha:1.0].CGColor;    [self.layer addSublayer:_shapeLayer];}

初始化r5點

- (void)configCurveView{    // _curveView就是r5點    _curveX = SYS_DEVICE_WIDTH/2.0;       // r5點x坐標    _curveY = MIN_HEIGHT;                 // r5點y坐標    _curveView = [[UIView alloc] initWithFrame:CGRectMake(_curveX, _curveY, 3, 3)];    _curveView.backgroundColor = [UIColor redColor];    [self addSubview:_curveView];}

添加移動手勢&CADisplayLink

- (void)configAction{    _mHeight = 100;                       // 手勢移動時相對高度    _isAnimating = NO;                    // 是否處于動效狀態(tài)    // 手勢    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanAction:)];    self.userInteractionEnabled = YES;    [self addGestureRecognizer:pan];    // calculatePath方法是算出在運行期間_curveView的坐標汁果,從而確定_shapeLayer的形狀    _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(calculatePath)];    [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];    // 在手勢結(jié)束的時候才調(diào)用calculatePath方法,所以一開始是暫停的    _displayLink.paused = YES;    }

手勢解析手勢移動時玲躯,r5紅點跟著手勢移動据德,_shapeLayer則根據(jù)r5的坐標來擴大自己的區(qū)域 手勢結(jié)束時,r5紅點通過UIView的動畫方法來改變r5的坐標,同時_shapeLayer根據(jù)r5的坐標縮小自己的區(qū)域并最終返回原形跷车。

- (void)handlePanAction:(UIPanGestureRecognizer *)pan{    if(!_isAnimating)    {        if(pan.state == UIGestureRecognizerStateChanged)        {            // 手勢移動時棘利,_shapeLayer跟著手勢向下擴大區(qū)域            CGPoint point = [pan translationInView:self];            // 這部分代碼使r5紅點跟著手勢走            _mHeight = point.y*0.7 + MIN_HEIGHT;            _curveX = SYS_DEVICE_WIDTH/2.0 + point.x;            _curveY = _mHeight > MIN_HEIGHT ? _mHeight : MIN_HEIGHT;            _curveView.frame = CGRectMake(_curveX,                                          _curveY,                                          _curveView.frame.size.width,                                          _curveView.frame.size.height);            // 根據(jù)r5坐標,更新_shapeLayer形狀            [self updateShapeLayerPath];        }        else if (pan.state == UIGestureRecognizerStateCancelled ||                 pan.state == UIGestureRecognizerStateEnded ||                 pan.state == UIGestureRecognizerStateFailed)        {            // 手勢結(jié)束時,_shapeLayer返回原狀并產(chǎn)生彈簧動效            _isAnimating = YES;            _displayLink.paused = NO;           //開啟displaylink,會執(zhí)行方法calculatePath.            // 彈簧動效            [UIView animateWithDuration:1.0                                  delay:0.0                 usingSpringWithDamping:0.5                  initialSpringVelocity:0                                options:UIViewAnimationOptionCurveEaseInOut                             animations:^{                // 曲線點(r5點)是一個view.所以在block中有彈簧效果.然后根據(jù)他的動效路徑,在calculatePath中計算彈性圖形的形狀                _curveView.frame = CGRectMake(SYS_DEVICE_WIDTH/2.0, MIN_HEIGHT, 3, 3);            } completion:^(BOOL finished) {                if(finished)                {                    _displayLink.paused = YES;                    _isAnimating = NO;                }            }];        }    }}

根據(jù)r5的位置,更新_shapeLayer形狀

- (void)updateShapeLayerPath{    // 更新_shapeLayer形狀    UIBezierPath *tPath = [UIBezierPath bezierPath];    [tPath moveToPoint:CGPointMake(0, 0)];  //r1點    [tPath addLineToPoint:CGPointMake(SYS_DEVICE_WIDTH, 0)];// r2點    [tPath addLineToPoint:CGPointMake(SYS_DEVICE_WIDTH,  MIN_HEIGHT)]; //r4點    [tPath addQuadCurveToPoint:CGPointMake(0, MIN_HEIGHT)                  controlPoint:CGPointMake(_curveX, _curveY)]; // r3,r4,r5確定的一個弧線    [tPath closePath];    _shapeLayer.path = tPath.CGPath;}

計算彈簧效果坐標

- (void)calculatePath{    // 由于手勢結(jié)束時,r5執(zhí)行了一個UIView的彈簧動畫,把這個過程的坐標記錄下來,并相應的畫出_shapeLayer形狀    CALayer *layer = _curveView.layer.presentationLayer;    _curveX = layer.position.x;    _curveY = layer.position.y;    [self updateShapeLayerPath];}

r5點的作用非常重要,因為直接對CAShapeLayer實現(xiàn)動效不太好實現(xiàn)朽缴。所以通過對r5點實現(xiàn)彈簧動效善玫,記錄r5點的坐標,再用UIBezierPath形成路徑密强,最后賦予CAShapeLayer茅郎,間接的完成了CAShapeLayer的彈簧動效。

如果你有疑問或者發(fā)現(xiàn)錯誤請留言給我或渤。3Q~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末只洒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子劳坑,更是在濱河造成了極大的恐慌,老刑警劉巖成畦,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件距芬,死亡現(xiàn)場離奇詭異涝开,居然都是意外死亡,警方通過查閱死者的電腦和手機框仔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門舀武,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人离斩,你說我怎么就攤上這事银舱。” “怎么了跛梗?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵寻馏,是天一觀的道長。 經(jīng)常有香客問我核偿,道長诚欠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任漾岳,我火速辦了婚禮轰绵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尼荆。我一直安慰自己左腔,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布捅儒。 她就那樣靜靜地躺著液样,像睡著了一般。 火紅的嫁衣襯著肌膚如雪野芒。 梳的紋絲不亂的頭發(fā)上蓄愁,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音狞悲,去河邊找鬼撮抓。 笑死,一個胖子當著我的面吹牛摇锋,可吹牛的內(nèi)容都是我干的丹拯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼荸恕,長吁一口氣:“原來是場噩夢啊……” “哼乖酬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起融求,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤咬像,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體县昂,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡肮柜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了倒彰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片审洞。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖待讳,靈堂內(nèi)的尸體忽然破棺而出芒澜,到底是詐尸還是另有隱情,我是刑警寧澤创淡,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布痴晦,位于F島的核電站,受9級特大地震影響辩昆,放射性物質(zhì)發(fā)生泄漏阅酪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一汁针、第九天 我趴在偏房一處隱蔽的房頂上張望术辐。 院中可真熱鬧,春花似錦施无、人聲如沸辉词。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瑞躺。三九已至,卻和暖如春兴想,著一層夾襖步出監(jiān)牢的瞬間幢哨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工嫂便, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捞镰,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓毙替,卻偏偏與公主長得像岸售,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子厂画,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容