QQ中未讀氣泡拖拽消失的實現分析

源地址:http://kittenyang.com/drawablebubble/ 

QQ中未讀氣泡拖拽消失的實現分析

QQ中針對強迫症有個很棒的交互,對於那些暫時不想理會的未讀信息氣泡,可以直接手指拖拽去掉。

今天我們就來重現一下這個功能。最終用到一個項目中的效果類似這樣。

說到實時的形變,我立馬想到的還是 CADisplayLink + UIBezierPath 的神奇組合!具體細節可以參考一下我之前的一篇博文

這個交互中,難點在於如何繪製貝塞爾曲線。而線又是由點組成的。所以最終歸根結底我們還是要找個關鍵點的座標。一圖勝千言。下面,我繪製了一幅分析圖,這樣一來問題就轉化成了一個高中數學求點座標的題目了。

Tips: OA ⊥ AB, PB ⊥ AB ,且 OA=PB=d/2.

現在我們已經有了數學表達式,接下來就是要把數學表達式轉化成代碼了。

我們需要創建一系列變量:

    CGFloat r1; // backView
    CGFloat r2; // frontView
    CGFloat x1;
    CGFloat y1;
    CGFloat x2;
    CGFloat y2;
    CGFloat centerDistance;
    CGFloat cosDigree;
    CGFloat sinDigree;

    CGPoint pointA; //A
    CGPoint pointB; //B
    CGPoint pointD; //D
    CGPoint pointC; //C
    CGPoint pointO; //O
    CGPoint pointP; //P

接下來我們需要一個毫秒級定時器 CADisplayLink

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkAction:)];  

根據數學公式,在 displayLink 綁定的方法 displayLinkAction 中把每個座標點用代碼表達出來:

    x1 = backView.center.x;
    y1 = backView.center.y;
    x2 = self.frontView.center.x;
    y2 = self.frontView.center.y;

    //d
    centerDistance = sqrtf((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));

    //sinΘ 和 cosΘ
    if (centerDistance == 0) {
        cosDigree = 1;
        sinDigree = 0;
    }else{
        cosDigree = (y2-y1)/centerDistance;
        sinDigree = (x2-x1)/centerDistance;
    }


    pointA = CGPointMake(x1-r1*cosDigree, y1+r1*sinDigree);  // A
    pointB = CGPointMake(x1+r1*cosDigree, y1-r1*sinDigree); // B
    pointD = CGPointMake(x2-r2*cosDigree, y2+r2*sinDigree); // D
    pointC = CGPointMake(x2+r2*cosDigree, y2-r2*sinDigree);// C
    pointO = CGPointMake(pointA.x + (centerDistance / 2)*sinDigree, pointA.y + (centerDistance / 2)*cosDigree);
    pointP = CGPointMake(pointB.x + (centerDistance / 2)*sinDigree, pointB.y + (centerDistance / 2)*cosDigree);

通過這些點,就可以畫出貝塞爾曲線了:

-(void)drawRect{


    backView.center = oldBackViewCenter;
    backView.bounds = CGRectMake(0, 0, r1*2, r1*2);
    backView.layer.cornerRadius = r1;


    cutePath = [UIBezierPath bezierPath];
    [cutePath moveToPoint:pointA];
    [cutePath addQuadCurveToPoint:pointD controlPoint:pointO];
    [cutePath addLineToPoint:pointC];
    [cutePath addQuadCurveToPoint:pointB controlPoint:pointP];
    [cutePath moveToPoint:pointA];


    if (backView.hidden == NO) {
        shapeLayer.path = [cutePath CGPath];
        shapeLayer.fillColor = [fillColorForCute CGColor];
        [self.containerView.layer insertSublayer:shapeLayer below:self.frontView.layer];
    }

}

大致實現思路還是很清晰的,無非在分析如何計算6個關鍵點的時候需要花點時間。


demo下載地址

https://github.com/KittenYang/KYCuteView

發佈了74 篇原創文章 · 獲贊 17 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章