淘寶我的界面波浪線
先看圖片
模仿淘寶.gif
demo沒進行封裝,內(nèi)容的實現(xiàn)主要使用了CADisplayLink定時器,UIBezierPath結(jié)合CAShaperLayer 實現(xiàn)的雙波浪效果,用了Model轉(zhuǎn)場動畫實現(xiàn)的下拉跳轉(zhuǎn)界面
整體來說不是太難 難的地方在于用UIBezierPath繪制下面的弧形時需要手動計算弧形的坐標。
實現(xiàn)方法 :
一、 首先要知道下面這個公式:
y = Asin(wx+Q) + S;
55969228-C38F-42FC-8B4D-25D49C54EE4F.png
對應(yīng)的曲線是這樣的
u=2166549996,3486693099&fm=23&gp=0.jpg
A 表示峰值,忘記數(shù)學(xué)怎么稱呼了(知道的大咖給說下,謝謝) 及最大值和最小值 由于sin(wx + Q)的區(qū)間是[-1,1];所以Asin(wx + Q)的區(qū)間就是[-A,A];聽朋友說叫振幅
W 表示周期 w越大周期T越小 我取的是0.04;
Q 是用來調(diào)整曲線的左右位置
S 是用來調(diào)整上下的位置
二、繪制波浪線
- (UIBezierPath *)getWavePath:(CGFloat)A W:(CGFloat)w d:(CGFloat)d dong:(CGFloat)dong{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 0)];
[path addLineToPoint:CGPointMake(0, 50)];
for (int i = 0; i < [UIScreen mainScreen].bounds.size.width; i++) {
// 這個是波浪線繪制的主要代碼
CGFloat y = A*sinf(i*w +dong+self.dong)+d;
[path addLineToPoint:CGPointMake(i, y)];
}
[path addLineToPoint:CGPointMake([UIScreen mainScreen].bounds.size.width, 0)];
[path closePath];
return path;
}
接著先創(chuàng)建一個TableView的頭視圖View
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 260)];
view.backgroundColor = [UIColor whiteColor];
self.headerView = view;
self.tableView.tableHeaderView = self.headerView;
創(chuàng)建CAShaperLayer 添加到TableView的頭視圖上 這樣就創(chuàng)建了一個波浪線
CAShapeLayer *layer = [CAShapeLayer layer];
layer.fillColor = [UIColor whiteColor].CGColor;
layer.frame = view.bounds;
layer.opacity = 0.3; // 透明度
layer.shouldRasterize = YES; // 加個注釋 這個是讓曲線能平滑過渡,防止有鋸齒狀
layer.path = [self getWavePath:8 W:0.04 d:25+60 dong:0].CGPath;
self.shapeLayer = layer;
[view.layer addSublayer:layer];
因為淘寶有兩個波浪線 還需要創(chuàng)建一個 沒封裝 所以又粘貼了一遍
CAShapeLayer *layer1 = [CAShapeLayer layer];
layer1.fillColor = [UIColor whiteColor].CGColor;
layer1.frame = view.bounds;
layer1.opacity = 0.3;
layer1.shouldRasterize = YES;
layer1.path = [self getWavePath:8 W:0.04 d:29+60 dong:10].CGPath;
self.shapeLayer1 = layer1;
[view.layer addSublayer:layer1];
但是淘寶的波浪會動啊 怎么辦? 這個時候我們就需要定時器 CADisplayLink 來控制波浪的波動,這個主要用來動畫的處理,NSTimer精準度沒這么高,具體的區(qū)別請看:(CADisplayLink)
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(disPlayLink:)];
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
- (void)disPlayLink:(CADisplayLink *)displayLink {
self.dong = self.dong+0.05;
self.shapeLayer.path = [self getWavePath:8 W:0.04 d:25+60 dong:0].CGPath;
self.shapeLayer1.path = [self getWavePath:8 W:0.04 d:29+60 dong:10].CGPath;
}
這樣你會神器的發(fā)現(xiàn)雙波浪動畫就實現(xiàn)了
三、繪制下面的圓弧(具體點的位置可以根據(jù)自己的方法計算)
5550717FD6EF24BA22462D927FD0F25D.jpg
代碼
- (UIBezierPath *)getLayerBezierPath {
CGFloat width = [UIScreen mainScreen].bounds.size.width;
CGFloat R = 25+pow(width, 2)/400.0f;
CGPoint centerArc = CGPointMake(width/2.0f,260-R);
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:CGPointMake(0, 0)];
[bezierPath addLineToPoint:CGPointMake(0, 210)];
// acos() 這個就是數(shù)學(xué)里面的arccos();
[bezierPath addArcWithCenter:centerArc radius:R startAngle:acos(width/(2*R)) endAngle:(M_PI-acos(width/(2*R))) clockwise:YES];
[bezierPath addLineToPoint:CGPointMake(width, 210)];
[bezierPath addLineToPoint:CGPointMake(width, 0)];
[bezierPath closePath];
return bezierPath;
}
創(chuàng)建一個layer扔到headerView上
CAShapeLayer *layer2 = [CAShapeLayer layer];
layer2.fillColor = [UIColor orangeColor].CGColor;
layer2.frame = view.bounds;
layer2.shouldRasterize = YES;
layer2.path = [self getLayerBezierPath].CGPath;
[view.layer addSublayer:layer2];
四、下面開始做轉(zhuǎn)場動畫
1、創(chuàng)建一個類、繼承NSObject 下面是.h中的代碼
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, CLImitationTaoBaoModelType) {
CLImitationTaoBaoModelTypePresent,
CLImitationTaoBaoModelTypeDismiss
};
@interface CLImitationTaoBao : NSObject <UIViewControllerAnimatedTransitioning>
+ (CLImitationTaoBao *)imitationTaoBao:(CLImitationTaoBaoModelType)modelType;
@end
2、實現(xiàn)兩個協(xié)議
// 具體動畫在這里面操作
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext;
// 動畫跳轉(zhuǎn)時長
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
3、轉(zhuǎn)場動畫的操作過程()
// 跳轉(zhuǎn)時的方法
- (void)present:(id<UIViewControllerContextTransitioning>)transitionContext {
UIView *fromeView = [transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
UIView *containerView = [transitionContext containerView];
[containerView addSubview:fromeView];
[containerView addSubview:toView];
fromeView.frame = containerView.frame;
toView.frame = CGRectMake(0, -containerView.frame.size.height, containerView.frame.size.width, containerView.frame.size.height);
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromeView.frame = CGRectMake(0, containerView.frame.size.height*4/5.0f, containerView.frame.size.width, containerView.frame.size.height);
toView.frame = CGRectMake(0, 0, containerView.frame.size.width, containerView.frame.size.height);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
// 返回時的方法
- (void)dismiss:(id<UIViewControllerContextTransitioning>)transitionContext {
UIView *fromeView = [transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
UIView *containerView = [transitionContext containerView];
[containerView addSubview:fromeView];
[containerView addSubview:toView];
fromeView.frame = containerView.frame;
toView.frame = CGRectMake(0, containerView.frame.size.height, containerView.frame.size.width, containerView.frame.size.height);
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromeView.frame = CGRectMake(0, -containerView.frame.size.height, containerView.frame.size.width, containerView.frame.size.height);
toView.frame = CGRectMake(0, 0, containerView.frame.size.width, containerView.frame.size.height);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
+ (CLImitationTaoBao *)imitationTaoBao:(CLImitationTaoBaoModelType)modelType {
CLImitationTaoBao *imitation = [[CLImitationTaoBao alloc] init];
imitation.modelType = modelType;
return imitation;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
if (self.modelType == CLImitationTaoBaoModelTypePresent) {
[self present:transitionContext];
} else {
[self dismiss:transitionContext];
}
}
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
return 0.5;
}
轉(zhuǎn)場動畫的具體學(xué)習(xí)以后再做筆記。
最后附Demo地址:https://github.com/qcl901028/myTaoBao