QQ上黏黏的小紅點很好玩有木有,因而本身也想完成一番,看到IOS完成的人比擬少,Android的比擬多,因而這個就用IOS來完成哈~
後果圖:
調試圖:
其實從完成來說,我是先完成第二張圖的後果的。
本站小編給年夜家說下完成思緒
1.懂得道理,和若何繪制“黏黏”外形(即繪制兩圓加兩條貝塞爾曲線)。
2.新建UIView(AZMetaBallCanvas),作為零丁畫布用來繪制“黏黏”外形,用法式完成算法,並繪制出來。
3.給畫布(AZMetaBallCanvas)添加attach:(UIView *)辦法,並添加手勢監聽,重繪,使得隨意率性 view 都可以或許被在畫布上具有“黏黏”後果。
4.依據連心線的間隔加上斷定能否要斷開,用戶手指分開時也要依據間隔來斷定是爆炸動畫照樣回彈動畫。
具體進程
起首必需要懂得小紅點拖拽的進程外形是甚麼,其實就是相似元球後果(MetaBall)。細心不雅察可剖析發明,就是兩個年夜小紛歧樣的圓加上兩條貝塞爾曲線組成的。
關於算法部門,我曾經分化成了別的一篇博文,激烈建議不清晰該外形是怎樣畫出來的同窗先看一下《【算法剖析】QQ“一鍵退朝”之具體盤算辦法》
1.繪制拖拽
既然怎樣求坐標點畫出來我們曾經曉得了,如今便可以去完成了。
起首新建一個“畫布”,繼續自UIView
//AZMetaBallCanvas.h @interface AZMetaBallCanvas : UIView @property(nonatomic,strong) Circle *centerCircle; @property(nonatomic,strong) Circle *touchCircle; @end
Circle為自界說實體類,外面界說了一些圓的根本屬性,如圓心坐標、半徑等。
為何要新建一個畫布?
由於小紅點是可以或許全屏拖動的,別看QQ上它存在某一行Cell,但其實你可以把它拉到其余Cell上去,這就須要給小紅點足夠的地位來繪制,就爽性新建一個畫布專門用來繪制小紅點的舉措好了。
AZMetaBallCanvas今朝包括兩個屬性,兩個圓,一個中間圓,一個觸摸圓,依照需求來看,中間圓應當是地位不變的,觸摸圓會追隨手指觸摸屏幕的地位而轉變,前面須要在兩個圓之間畫上貝塞爾曲線來組成元球後果。
接上去開端寫AZMetaBallCanvas的完成
//AZMetaBallCanvas.m #define RADIUS 40.0 @interface AZMetaBallCanvas() { UIBezierPath *_path; CGPoint _touchPoint; } @end @implementation AZMetaBallCanvas - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; NSLog(@"initWithCorder"); if (self) { [self initData]; } return self; } - (void)initData { _touchCircle = [Circle initWithcenterPoint:self.center radius:RADIUS]; _centerCircle = [Circle initWithcenterPoint:self.center radius:RADIUS]; _touchPoint = self.center; NSLog(@"self.center (%f, %f)", self.center.x, self.center.y); } @end
先初始化兩個圓的地位,默許在View的中間,並在init、initWithFrame、initWithCoder等父類結構函數中參加自界說初始化辦法initData。
重寫繪制辦法
好像Android中的onDraw(),IOS中的drawRect可以或許被重寫繪制,然後挪用[view setNeedsDisplay]來告訴重繪。
- (void)drawRect:(CGRect)rect { _path = [[UIBezierPath alloc] init]; [self drawCenterCircle]; [self drawTouchCircle:_touchPoint]; [self drawBezierCurveWithCircle1:_centerCircle Circle2:_touchCircle]; }
好像算法剖析中所講,在繪制的時刻,我們只須要繪制兩個圓(drawCenterCircle、drawTouchCircle)和銜接兩圓的貝塞爾曲線(drawBezierCurve),算法其實就是照抄《【算法剖析】QQ“一鍵退朝”之具體盤算辦法》
iOS自帶貝塞爾曲線UIBezierPath,其自帶畫圓辦法addArcWithCenter: radius: startAngle: endAngle: clockwise:,所以我們只需挪用就好啦!
#pragma mark draw circle --- 畫圓 - (void) drawCenterCircle { [self drawCircle:_path circle:_centerCircle]; } - (void) drawTouchCircle:(CGPoint)center { _touchCircle.centerPoint = center; [self drawCircle:_path circle:_touchCircle]; } - (void)drawCircle:(UIBezierPath *)path circle:(Circle *)circle { [_path addArcWithCenter:circle.centerPoint radius:circle.radius startAngle:0 endAngle:360 clockwise:true]; [_path fill]; [_path stroke]; [_path removeAllPoints]; } #pragma mark draw curve --- 畫貝塞爾曲線 - (void)drawBezierCurveWithCircle1:(Circle *)circle1 Circle2:(Circle *)circle2 { float circle1_x = circle1.centerPoint.x; float circle1_y = circle1.centerPoint.y; float circle2_x = circle2.centerPoint.x; float circle2_y = circle2.centerPoint.y; //連心線的長度 float d = sqrt(powf(circle1_x - circle2_x, 2) + powf(circle1_y - circle2_y, 2)); //連心線x軸的夾角 float angle1 = atan((circle2_y - circle1_y) / (circle1_x - circle2_x)); //連心線和公切線的夾角 float angle2 = asin((circle1.radius - circle2.radius) / d); //切點到圓心和x軸的夾角 float angle3 = M_PI_2 - angle1 - angle2; float angle4 = M_PI_2 - angle1 + angle2; float offset1_X = cos(angle3) * circle1.radius; float offset1_Y = sin(angle3) * circle1.radius; float offset2_X = cos(angle3) * circle2.radius; float offset2_Y = sin(angle3) * circle2.radius; float offset3_X = cos(angle4) * circle1.radius; float offset3_Y = sin(angle4) * circle1.radius; float offset4_X = cos(angle4) * circle2.radius; float offset4_Y = sin(angle4) * circle2.radius; float p1_x = circle1_x - offset1_X; float p1_y = circle1_y - offset1_Y; float p2_x = circle2_x - offset2_X; float p2_y = circle2_y - offset2_Y; float p3_x = circle1_x + offset3_X; float p3_y = circle1_y + offset3_Y; float p4_x = circle2_x + offset4_X; float p4_y = circle2_y + offset4_Y; CGPoint p1 = CGPointMake(p1_x, p1_y); CGPoint p2 = CGPointMake(p2_x, p2_y); CGPoint p3 = CGPointMake(p3_x, p3_y); CGPoint p4 = CGPointMake(p4_x, p4_y); CGPoint p1_center_p4 = CGPointMake((p1_x + p4_x) / 2, (p1_y + p4_y) / 2); CGPoint p2_center_p3 = CGPointMake((p2_x + p3_x) / 2, (p2_y + p3_y) / 2); [self drawBezierCurveStartAt:p1 EndAt:p2 controlPoint:p2_center_p3]; [self drawLineStartAt:p2 EndAt:p4]; [self drawBezierCurveStartAt:p4 EndAt:p3 controlPoint:p1_center_p4]; [self drawLineStartAt:p3 EndAt:p1]; [_path moveToPoint:p1]; [_path closePath]; [_path stroke]; }
2.監聽手勢
簡略版
最簡略的其實就是直接在AZMetaBallCanvas中重寫touchXXX等一系列辦法,然後在個中挪用setNeedsDisplay告訴UIView重繪。
#pragma mark touch event - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; _touchPoint = [touch locationInView:self]; [self setNeedsDisplay]; } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; _touchPoint = [touch locationInView:self]; [self setNeedsDisplay]; }
如今其實差不多第二張圖的後果曾經出來了,差的就是更改兩圓的半徑辦法。
轉變半徑的辦法就異常簡略了
#pragma 轉變半徑 -(void)changeCenterCircleRadiusTo:(float)radius { _centerCircle.radius = radius; [self setNeedsDisplay]; } -(void)changeTouchCircleRadiusTo:(float)radius { _touchCircle.radius = radius; [self setNeedsDisplay]; }
通俗版
依據景象發明,我們須要經由過程拖拽小紅點來挪動它,而不是我們手指導哪,小紅點就在哪,所以我們須要給小紅點增長手勢監聽,而不是“畫布”。
因而我們改成在畫布添加辦法- (void)attach:(UIView *)item;,然後再給傳入的view添加Pan手勢。
- (void)attach:(UIView *)item { UIPanGestureRecognizer *drag = [[UIPanGestureRecognizer alloc] initWithtarget:self action:@selector(drag:)]; item.userInteractionEnabled = YES; [item addGestureRecognizer:drag]; } - (void)drag:(UIPanGestureRecognizer *)recognizer { //獲得觸摸點 _touchPoint = [recognizer locationInView:self]; //獲得觸摸的view UIView *touchView = recognizer.view; switch (recognizer.state) { case UIGestureRecognizerStateBegan:{ //touch開端:在畫布上繪制一個touchView的正本 //...此部門參看源碼 break; } case UIGestureRecognizerStateChanged:{ //挪動中:記載觸摸地位,更改touchView和touchCircle的坐標地位 [self resetTouchCenter:_touchPoint]; break; } case UIGestureRecognizerStateEnded: { //touch停止:依據連心線長度斷定是履行爆炸動畫照樣彈簧動畫 //...此部門參看源碼 break; } default: break; } [self setNeedsDisplay]; //重繪 }
以上內容是小編給年夜家引見的IOS設置QQ小紅點清除的辦法(一鍵退朝),願望對年夜家有所贊助。
【IOS設置QQ小紅點清除的辦法(一鍵退朝)】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!