這幾天作了一些簡單iOS的效果圖,感受蘋果官方已經幫咱們作了不少了,咱們只是站在巨人的肩膀上編程,這些也沒什麼難的,最難的也就是用到了初中的三角函數,先讓你們看看這幾個動畫吧。先列這幾個把,由上而下分別是 數據緩衝效果 ,粒子動畫,HUD指示效果,QQ未讀消息的粘性效果,圖一把一半遮住就是一種音樂播放器的播放效果,好了圖一,圖二, 圖三都好簡單就好似黃子華講過,我只要一張嘴,兩隻手就能夠把她搞得好嗨皮,而圖一 圖二,圖三就是隻要一個Animation,兩個Layer就搞定了,而圖四也不難,下面詳細說一下圖四編程
思路函數
- 添加控件佈局
- 添加手勢畫線動畫
- 重寫drawRect方法atom
- 添加Layerspa
- 添加動畫code
- 添加layerorm
- 添加動畫blog
- 添加複製圖層ci
- 添加控件
- 添加layer
- 添加動畫
- 添加複製層
--思路
新建自定義UIButton
添加拖動手勢
計算圓的變化
計算圓之間矩形而且填充
回彈
爆炸
先完成空間佈局以及手勢添加
而後計算圓的變化,計算圓之間的矩形面積
效果微調
- 在一個storyBoard裏面拖一個UIButton進去,而後新建一個自定義UIBUtton類 如:ETBUtton類與之對應,好了,一切新建工做完畢,下面,咱們只須要在自定義的UIButton類裏面作功夫就行了,簡單的代碼直接上好
#import "ETStickBtn.h"
@interface ETStickBtn () @property (nonatomic, strong) UIView *smalCirView; @property (nonatomic, assign) NSInteger oriRadius; @property (nonatomic, strong) CAShapeLayer *shapeLayer; @end
@implementation ETStickBtn #pragma mark - 懶加載數據
- (UIView *)smalCirView{ if (!_smalCirView) { // 新建一個圓
UIView *smalCirView = [[UIView alloc] init]; // smalCirView.frame = self.frame;
smalCirView.backgroundColor = self.backgroundColor; [self.superview insertSubview:smalCirView belowSubview:self]; _smalCirView = smalCirView; } return _smalCirView; } - (CAShapeLayer *)shapeLayer{ if (!_shapeLayer) { CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.fillColor = self.backgroundColor.CGColor; [self.superview.layer insertSublayer:shapeLayer below:self.layer]; _shapeLayer = shapeLayer; } return _shapeLayer; } #pragma mark - 系統初始化
- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { [self setUp]; } return self; } - (void)awakeFromNib{ [self setUp]; } #pragma mark - 初始化視圖
- (void)setUp{ CGFloat w = self.bounds.size.width; self.layer.cornerRadius = w / 2; self.smalCirView.layer.cornerRadius = w/2; // 記錄半徑
_oriRadius = w/2; _smalCirView.frame = self.frame; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [self addGestureRecognizer:pan]; }
- (void)pan:(UIPanGestureRecognizer *)pan{ // 移動
CGPoint transPoint = [pan translationInView:self]; CGPoint center = self.center; center.x += transPoint.x; center.y += transPoint.y; self.center = center; [pan setTranslation:CGPointZero inView:self]; }
- (void)pan:(UIPanGestureRecognizer *)pan{ // 移動
CGPoint transPoint = [pan translationInView:self]; CGPoint center = self.center; center.x += transPoint.x; center.y += transPoint.y; self.center = center; [pan setTranslation:CGPointZero inView:self]; // 設置小圓變化的值
CGFloat cirDistance = [self distanceWithPointA:self.center andPointB:self.smalCirView.center]; CGFloat smallCirRadius = _oriRadius - cirDistance/10.0; if(smallCirRadius<0) smallCirRadius = 0; _smalCirView.bounds = CGRectMake(0, 0, smallCirRadius * 2, smallCirRadius * 2); self.smalCirView.layer.cornerRadius = smallCirRadius; } #pragma mark - 獲取圓心距離
- (CGFloat)distanceWithPointA:(CGPoint)pointA andPointB:(CGPoint)pointB{ CGFloat offSetX = pointA.x - pointB.x; CGFloat offSetY = pointA.y - pointB.y; return sqrt(offSetX*offSetX + offSetY*offSetY); }
- (UIBezierPath *)getBezierPathWithSmallCir:(UIView *)smallCir andBigCir:(UIView *)bigCir{ // 獲取最小的圓
if (bigCir.frame.size.width < smallCir.frame.size.width) { UIView *view = bigCir; bigCir = smallCir; smallCir = view; } // 獲取小圓的信息
CGFloat d = [self distanceWithPointA:smallCir.center andPointB:bigCir.center]; CGFloat x1 = smallCir.center.x; CGFloat y1 = smallCir.center.y; CGFloat r1 = smallCir.bounds.size.width/2; // 獲取大圓的信息
CGFloat x2 = bigCir.center.x; CGFloat y2 = bigCir.center.y; CGFloat r2 = bigCir.bounds.size.width/2; // 獲取三角函數
CGFloat sinA = (y2 - y1)/d; CGFloat cosA = (x2 - x1)/d; // 獲取矩形四個點
CGPoint pointA = CGPointMake(x1 - sinA*r1, y1 + cosA * r1); CGPoint pointB = CGPointMake(x1 + sinA*r1, y1 - cosA * r1); CGPoint pointC = CGPointMake(x2 + sinA*r2, y2 - cosA * r2); CGPoint pointD = CGPointMake(x2 - sinA*r2, y2 + cosA * r2); // 獲取控制點,以便畫出曲線
CGPoint pointO = CGPointMake(pointA.x + d / 2 * cosA , pointA.y + d / 2 * sinA); CGPoint pointP = CGPointMake(pointB.x + d / 2 * cosA , pointB.y + d / 2 * sinA); // 建立路徑
UIBezierPath *path =[UIBezierPath bezierPath]; [path moveToPoint:pointA]; [path addLineToPoint:pointB]; [path addQuadCurveToPoint:pointC controlPoint:pointP]; [path addLineToPoint:pointD]; [path addQuadCurveToPoint:pointA controlPoint:pointO]; return path; }
// 獲取最小的圓
if (bigCir.frame.size.width < smallCir.frame.size.width) { UIView *view = bigCir; bigCir = smallCir; smallCir = view; }
- (void)pan:(UIPanGestureRecognizer *)pan{ // 移動
CGPoint transPoint = [pan translationInView:self]; CGPoint center = self.center; center.x += transPoint.x; center.y += transPoint.y; self.center = center; [pan setTranslation:CGPointZero inView:self]; // 設置小圓變化的值
CGFloat cirDistance = [self distanceWithPointA:self.center andPointB:self.smalCirView.center]; CGFloat smallCirRadius = _oriRadius - cirDistance/10.0; if(smallCirRadius<0) smallCirRadius = 0; _smalCirView.bounds = CGRectMake(0, 0, smallCirRadius * 2, smallCirRadius * 2); self.smalCirView.layer.cornerRadius = smallCirRadius; self.shapeLayer.path = [self getBezierPathWithSmallCir:self andBigCir:self.smalCirView].CGPath; }
#pragma mark - 自定義方法 #pragma mark - 手勢觸發方法 #define MaxDistance 90 - (void)pan:(UIPanGestureRecognizer *)pan{ // 移動 CGPoint transPoint = [pan translationInView:self]; CGPoint center = self.center; center.x += transPoint.x; center.y += transPoint.y; self.center = center; [pan setTranslation:CGPointZero inView:self]; // 設置小圓變化的值 CGFloat cirDistance = [self distanceWithPointA:self.center andPointB:self.smalCirView.center]; CGFloat smallCirRadius = _oriRadius - cirDistance/10.0; if(smallCirRadius<0) smallCirRadius = 0; _smalCirView.bounds = CGRectMake(0, 0, smallCirRadius * 2, smallCirRadius * 2); self.smalCirView.layer.cornerRadius = smallCirRadius; // 畫圖 if (cirDistance > MaxDistance) { self.smalCirView.hidden = YES; [self.shapeLayer removeFromSuperlayer]; // self.smalCirView = nil; self.shapeLayer = nil; }else if(self.smalCirView.hidden == NO && cirDistance > 0){ self.shapeLayer.path = [self getBezierPathWithSmallCir:self andBigCir:self.smalCirView].CGPath; }
#pragma mark - 自定義方法
#pragma mark - 手勢觸發方法
#define MaxDistance 90
- (void)pan:(UIPanGestureRecognizer *)pan{ // 移動
CGPoint transPoint = [pan translationInView:self]; CGPoint center = self.center; center.x += transPoint.x; center.y += transPoint.y; self.center = center; [pan setTranslation:CGPointZero inView:self]; // 設置小圓變化的值
CGFloat cirDistance = [self distanceWithPointA:self.center andPointB:self.smalCirView.center]; CGFloat smallCirRadius = _oriRadius - cirDistance/10.0; if(smallCirRadius<0) smallCirRadius = 0; _smalCirView.bounds = CGRectMake(0, 0, smallCirRadius * 2, smallCirRadius * 2); self.smalCirView.layer.cornerRadius = smallCirRadius; // 畫圖
if (cirDistance > MaxDistance) { self.smalCirView.hidden = YES; [self.shapeLayer removeFromSuperlayer]; // self.smalCirView = nil;
self.shapeLayer = nil; }else if(self.smalCirView.hidden == NO && cirDistance > 0){ self.shapeLayer.path = [self getBezierPathWithSmallCir:self andBigCir:self.smalCirView].CGPath; } // 爆炸或還原
if(pan.state == UIGestureRecognizerStateBegan){ NSLog(@"%@",NSStringFromCGRect(self.frame)); } if (pan.state == UIGestureRecognizerStateEnded) { if (cirDistance > MaxDistance){ // 這是動畫的爆炸效果
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.bounds]; NSLog(@"%@",NSStringFromCGRect(self.frame)); NSMutableArray *imageArr = [NSMutableArray array]; for (int i = 1 ; i < 9; i++) { UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d",i]]; [imageArr addObject:image]; } imageView.animationImages = imageArr; imageView.animationDuration = 0.5; imageView.animationRepeatCount = 1; [imageView startAnimating]; [self addSubview:imageView]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 移除控件
[self removeFromSuperview]; }); }else{ // 回彈
[self.shapeLayer removeFromSuperlayer]; self.shapeLayer = nil; [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ self.center = self.smalCirView.center; } completion:^(BOOL finished) { self.smalCirView.hidden = NO; }]; } } }
- (void)viewDidLoad { [super viewDidLoad]; self.view.translatesAutoresizingMaskIntoConstraints = NO; }
#import "ETStickBtn.h"
@interface ETStickBtn () @property (nonatomic, strong) UIView *smalCirView; @property (nonatomic, assign) NSInteger oriRadius; @property (nonatomic, strong) CAShapeLayer *shapeLayer; @end
@implementation ETStickBtn #pragma mark - 懶加載數據
- (UIView *)smalCirView{ if (!_smalCirView) { // 新建一個圓
UIView *smalCirView = [[UIView alloc] init]; // smalCirView.frame = self.frame;
smalCirView.backgroundColor = self.backgroundColor; [self.superview insertSubview:smalCirView belowSubview:self]; _smalCirView = smalCirView; } return _smalCirView; } - (CAShapeLayer *)shapeLayer{ if (!_shapeLayer) { CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.fillColor = self.backgroundColor.CGColor; [self.superview.layer insertSublayer:shapeLayer below:self.layer]; _shapeLayer = shapeLayer; } return _shapeLayer; } #pragma mark - 系統初始化
- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { [self setUp]; } return self; } - (void)awakeFromNib{ [self setUp]; } #pragma mark - 初始化視圖
- (void)setUp{ CGFloat w = self.bounds.size.width; self.layer.cornerRadius = w / 2; self.smalCirView.layer.cornerRadius = w/2; // 記錄半徑
_oriRadius = w/2; _smalCirView.frame = self.frame; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [self addGestureRecognizer:pan]; } #pragma mark - 自定義方法
#pragma mark - 手勢觸發方法
#define MaxDistance 90
- (void)pan:(UIPanGestureRecognizer *)pan{ // 移動
CGPoint transPoint = [pan translationInView:self]; CGPoint center = self.center; center.x += transPoint.x; center.y += transPoint.y; self.center = center; [pan setTranslation:CGPointZero inView:self]; // 設置小圓變化的值
CGFloat cirDistance = [self distanceWithPointA:self.center andPointB:self.smalCirView.center]; CGFloat smallCirRadius = _oriRadius - cirDistance/10.0; if(smallCirRadius<0) smallCirRadius = 0; _smalCirView.bounds = CGRectMake(0, 0, smallCirRadius * 2, smallCirRadius * 2); self.smalCirView.layer.cornerRadius = smallCirRadius; // 畫圖
if (cirDistance > MaxDistance) { self.smalCirView.hidden = YES; [self.shapeLayer removeFromSuperlayer]; // self.smalCirView = nil;
self.shapeLayer = nil; }else if(self.smalCirView.hidden == NO && cirDistance > 0){ self.shapeLayer.path = [self getBezierPathWithSmallCir:self andBigCir:self.smalCirView].CGPath; } // 爆炸或還原
if(pan.state == UIGestureRecognizerStateBegan){ NSLog(@"%@",NSStringFromCGRect(self.frame)); } if (pan.state == UIGestureRecognizerStateEnded) { if (cirDistance > MaxDistance){ // 這是動畫的爆炸效果
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.bounds]; NSLog(@"%@",NSStringFromCGRect(self.frame)); NSMutableArray *imageArr = [NSMutableArray array]; for (int i = 1 ; i < 9; i++) { UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d",i]]; [imageArr addObject:image]; } imageView.animationImages = imageArr; imageView.animationDuration = 0.5; imageView.animationRepeatCount = 1; [imageView startAnimating]; [self addSubview:imageView]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 移除控件
[self removeFromSuperview]; }); }else{ // 回彈
[self.shapeLayer removeFromSuperlayer]; self.shapeLayer = nil; [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ self.center = self.smalCirView.center; } completion:^(BOOL finished) { self.smalCirView.hidden = NO; }]; } } } #pragma mark - 獲取圓心距離
- (CGFloat)distanceWithPointA:(CGPoint)pointA andPointB:(CGPoint)pointB{ CGFloat offSetX = pointA.x - pointB.x; CGFloat offSetY = pointA.y - pointB.y; return sqrt(offSetX*offSetX + offSetY*offSetY); } #pragma mark - 獲取貝塞爾曲線
- (UIBezierPath *)getBezierPathWithSmallCir:(UIView *)smallCir andBigCir:(UIView *)bigCir{ // 獲取最小的圓
if (bigCir.frame.size.width < smallCir.frame.size.width) { UIView *view = bigCir; bigCir = smallCir; smallCir = view; } // 獲取小圓的信息
CGFloat d = [self distanceWithPointA:smallCir.center andPointB:bigCir.center]; CGFloat x1 = smallCir.center.x; CGFloat y1 = smallCir.center.y; CGFloat r1 = smallCir.bounds.size.width/2; // 獲取大圓的信息
CGFloat x2 = bigCir.center.x; CGFloat y2 = bigCir.center.y; CGFloat r2 = bigCir.bounds.size.width/2; // 獲取三角函數
CGFloat sinA = (y2 - y1)/d; CGFloat cosA = (x2 - x1)/d; // 獲取矩形四個點
CGPoint pointA = CGPointMake(x1 - sinA*r1, y1 + cosA * r1); CGPoint pointB = CGPointMake(x1 + sinA*r1, y1 - cosA * r1); CGPoint pointC = CGPointMake(x2 + sinA*r2, y2 - cosA * r2); CGPoint pointD = CGPointMake(x2 - sinA*r2, y2 + cosA * r2); // 獲取控制點,以便畫出曲線
CGPoint pointO = CGPointMake(pointA.x + d / 2 * cosA , pointA.y + d / 2 * sinA); CGPoint pointP = CGPointMake(pointB.x + d / 2 * cosA , pointB.y + d / 2 * sinA); // 建立路徑
UIBezierPath *path =[UIBezierPath bezierPath]; [path moveToPoint:pointA]; [path addLineToPoint:pointB]; [path addQuadCurveToPoint:pointC controlPoint:pointP]; [path addLineToPoint:pointD]; [path addQuadCurveToPoint:pointA controlPoint:pointO]; return path; } @end
好了,一個簡單的粘性效果完成了