新浪微博的紅包加載動(dòng)畫澳骤,過年在家里搶紅包看到這個(gè)效果,就順手仿照著寫了一下为肮。主要還是利用余弦函數(shù)曲線的特性實(shí)現(xiàn)的。
具體原理是圓球在從左向右移動(dòng)時(shí)時(shí)先縮小再放大颊艳,圓球從右向左移動(dòng)時(shí)先放大在縮小棋枕;然后再加上另一個(gè)圓球就實(shí)現(xiàn)了這樣遠(yuǎn)近交換的效果。
GitHub地址:https://github.com/mengxianliang/XLDotLoading
XLDot.h
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger,DotDitection)
{
DotDitectionLeft = -1,
DotDitectionRight = 1,
};
@interface XLDot : UIView
//移動(dòng)方向 就兩種 左重斑、右
@property (nonatomic,assign) DotDitection direction;
//字體顏色
@property (nonatomic,strong) UIColor *textColor;
@end
XLDot.m
#import "XLDot.h"
@interface XLDot ()
{
UILabel *_label;
}
@end
@implementation XLDot
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self buildUI];
}
return self;
}
-(void)buildUI
{
self.layer.cornerRadius = self.bounds.size.width/2.0f;
self.layer.masksToBounds = true;
_label = [[UILabel alloc] initWithFrame:self.bounds];
_label.textAlignment = NSTextAlignmentCenter;
_label.font = [UIFont boldSystemFontOfSize:20];
_label.text = @"¥";
_label.adjustsFontSizeToFitWidth = true;
[self addSubview:_label];
}
-(void)setTextColor:(UIColor *)textColor
{
_textColor = textColor;
_label.textColor = textColor;
}
@end
XLDotLoading.h
#import <UIKit/UIKit.h>
@interface XLDotLoading : UIView
//顯示方法
+(void)showInView:(UIView*)view;
//隱藏方法
+(void)hideInView:(UIView*)view;
-(void)start;
-(void)stop;
@end
XLDotLoading.m
#import "XLDotLoading.h"
#import "XLDot.h"
@interface XLDotLoading ()
{
NSMutableArray *_dots;
CADisplayLink *_link;
UIView *_dotContainer;
}
@end
@implementation XLDotLoading
//初始化方法
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self buildUI];
[self buildData];
}
return self;
}
//豆的寬度
-(CGFloat)dotWidth
{
CGFloat margin = _dotContainer.bounds.size.width/5.0f;
CGFloat dotWidth = (_dotContainer.bounds.size.width - margin)/2.0f;
return dotWidth;
}
-(CGFloat)speed
{
return 2.0f;
}
//初始化兩個(gè)豆
-(void)buildUI
{
//初始化存放豆豆的的容器
_dotContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 80, 50)];
_dotContainer.center = self.center;
[self addSubview:_dotContainer];
//一個(gè)豆放左 一個(gè)豆放右
_dots = [NSMutableArray new];
NSArray *dotBackGroundColors = @[[self R:255 G:218 B:134 A:1],[self R:245 G:229 B:216 A:1]];
NSArray *textColors = @[[self R:255 G:197 B:44 A:1],[self R:237 G:215 B:199 A:1]];
for (NSInteger i = 0; i<textColors.count; i++) {
CGFloat dotX = i==0 ? 0 : _dotContainer.bounds.size.width - [self dotWidth];
//初始化開始運(yùn)動(dòng)的方向 左邊的方向是向右 右邊的方向是向左
DotDitection direction = i==0 ? DotDitectionRight : DotDitectionLeft;
XLDot *dot = [[XLDot alloc] initWithFrame:CGRectMake(dotX, 0, [self dotWidth],[self dotWidth])];
dot.center = CGPointMake(dot.center.x, _dotContainer.bounds.size.height/2.0f);
dot.layer.cornerRadius = dot.bounds.size.width/2.0f;
dot.backgroundColor = dotBackGroundColors[i];
dot.direction = direction;
dot.textColor = textColors[i];
[_dotContainer addSubview:dot];
[_dots addObject:dot];
}
}
//初始化定時(shí)刷新
-(void)buildData
{
_link = [CADisplayLink displayLinkWithTarget:self selector:@selector(reloadView)];
}
//開始動(dòng)畫
-(void)start
{
[_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
//停止動(dòng)畫
-(void)stop
{
[_link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
//刷新UI
-(void)reloadView
{
XLDot *dot1 = _dots.firstObject;
XLDot *dot2 = _dots.lastObject;
//改變移動(dòng)方向祖很、約束移動(dòng)范圍
//移動(dòng)到右邊距時(shí)
if (dot1.center.x >= _dotContainer.bounds.size.width - [self dotWidth]/2.0f) {
CGPoint center = dot1.center;
center.x = _dotContainer.bounds.size.width - [self dotWidth]/2.0f;
dot1.center = center;
dot1.direction = DotDitectionLeft;
dot2.direction = DotDitectionRight;
[_dotContainer bringSubviewToFront:dot1];
}
//移動(dòng)到左邊距時(shí)
if (dot1.center.x <= [self dotWidth]/2.0f) {
dot1.center = CGPointMake([self dotWidth]/2.0f, dot2.center.y);
dot1.direction = DotDitectionRight;
dot2.direction = DotDitectionLeft;
[_dotContainer sendSubviewToBack:dot1];
}
//更新第一個(gè)豆的位置
CGPoint center1 = dot1.center;
center1.x += dot1.direction * [self speed];
dot1.center = center1;
//顯示放大效果
[self showAnimationsOfDot:dot1];
//根據(jù)第一個(gè)豆的位置確定第二個(gè)豆的位置
CGFloat apart = dot1.center.x - _dotContainer.bounds.size.width/2.0f;
CGPoint center2 = dot2.center;
center2.x = _dotContainer.bounds.size.width/2.0f - apart;
dot2.center = center2;
[self showAnimationsOfDot:dot2];
}
//顯示放大漾脂、縮小動(dòng)畫
-(void)showAnimationsOfDot:(XLDot*)dot
{
CGFloat apart = dot.center.x - _dotContainer.bounds.size.width/2.0f;
//最大距離
CGFloat maxAppart = (_dotContainer.bounds.size.width - [self dotWidth])/2.0f;
//移動(dòng)距離和最大距離的比例
CGFloat appartScale = apart/maxAppart;
//獲取比例對(duì)應(yīng)余弦曲線的Y值
CGFloat transfomscale = cos(appartScale * M_PI/2.0);
//向右移動(dòng)則 中間變大 兩邊變小
if (dot.direction == DotDitectionLeft) {
dot.transform = CGAffineTransformMakeScale(1 + transfomscale/4.0f, 1 + transfomscale/4.0f);
//向左移動(dòng)則 中間變小 兩邊變大
}else if (dot.direction == DotDitectionRight){
dot.transform = CGAffineTransformMakeScale(1 - transfomscale/4.0f,1 - transfomscale/4.0f);
}
}
-(UIColor*)R:(CGFloat)r G:(CGFloat)g B:(CGFloat)b A:(CGFloat)a
{
return [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a];
}
#pragma mark -
#pragma mark 功能方法
+(XLDotLoading *)getLoadingInView:(UIView *)view {
XLDotLoading *loading = nil;
for (XLDotLoading *subview in view.subviews) {
if ([subview isKindOfClass:[XLDotLoading class]]) {
loading = subview;
}
}
return loading;
}
+(void)showInView:(UIView*)view
{
XLDotLoading *loading = [[XLDotLoading alloc] initWithFrame:view.bounds];
[view addSubview:loading];
[loading start];
}
+(void)hideInView:(UIView *)view
{
XLDotLoading *loading = [XLDotLoading getLoadingInView:view];
if (loading) {
[loading removeFromSuperview];
[loading stop];
}
}
@end
Simulator Screen Shot 2017年5月8日 下午7.55.45.png
Simulator Screen Shot 2017年5月8日 下午7.55.49.png