漸變圖層和插值曲線

漸變圖層通常與插值貝塞爾曲線混合使用來繪制各種變化曲線魄揉。剛開始也是公司需求剪侮,要繪制這種光滑的曲線,我也找了很多的第三方洛退,帶動畫的瓣俯、不帶動畫的種種杰标,結(jié)果都不滿意,然后就開始自己搞彩匕,其中同事也給了我很多提示腔剂。
貝塞爾曲線可能都會畫,但是于要求還遠遠不夠驼仪,怎么畫出光滑的曲線掸犬,再加上漸變的圖層,這就是關(guān)鍵了绪爸,下面的代碼主要講解處理插值數(shù)據(jù)湾碎,讓貝塞爾曲線更加光滑,通過貝塞爾曲線繪制漸變圖層毡泻。俗話說授人以魚不如授人以漁胜茧,下面就以代碼來講解實現(xiàn)和使用的方法粘优,讓初學者都能自己寫自己想要的曲線圖仇味。
講解全靠代碼注釋
GradeColorView類,.h文件

#import <UIKit/UIKit.h>


@interface GradeColorView : UIView

@property(strong,nonatomic)UIColor * lineColor;/////線的顏色

@property (nonatomic, strong)NSMutableArray *allPoints;///所有點包括插值點


- (instancetype)initWithFrame:(CGRect)frame;

- (void)updateUIWithPointArray:(NSArray *)pointsArray insertNum:(NSInteger)insertNum withLineColor:(UIColor *)color;

@end

.m文件

#import "GradeColorView.h"
#import "DataGetY.h"

///把對應(yīng)的顏色
#define kSetAlColor(rd,ge,be,al) ([UIColor colorWithRed:rd<=1?rd:rd/255.0 green:ge<=1?ge:ge/255.0 blue:be<=1?be:be/255.0 alpha:al])

//獲取顏色R G B
#define kGetColorRed(color) ([[[CIColor alloc]initWithColor:color] red])
#define kGetColorGreen(color) ([[[CIColor alloc]initWithColor:color] green])
#define kGetColorBlue(color) ([[[CIColor alloc]initWithColor:color] blue])

@interface GradeColorView ()

@property (nonatomic, strong)CAGradientLayer *gradientLayer;////漸變色層

@property (nonatomic, strong)NSArray *pointsArray;////曲線的點數(shù)組

@property (nonatomic, assign)NSInteger insertNum;

@end

@implementation GradeColorView


- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        self.allPoints = [[NSMutableArray alloc]init];
    }
    return self;
}

////傳入數(shù)據(jù) 數(shù)組
- (void)updateUIWithPointArray:(NSArray *)pointsArray insertNum:(NSInteger)insertNum withLineColor:(UIColor *)color
{
    self.lineColor = color;///設(shè)置曲線顏色
    self.insertNum = insertNum;
    self.pointsArray = pointsArray;
    
    ////創(chuàng)建BezierPath
    UIBezierPath *path = [UIBezierPath bezierPath];
    ////對數(shù)據(jù)進行處理雹顺,開始插值丹墨,為漸變色圖層提供范圍
    [self makeDownPointWithInsertNum:insertNum andPointsArray:self.pointsArray withPath:path];
    path.lineWidth = 0;
    [path stroke];
    ///self.gradientLayer為漸變色層
    CAShapeLayer *layer = [CAShapeLayer layer];////創(chuàng)建一個Layer層
    layer.path = [path CGPath];
    layer.lineCap = kCALineCapRound;
    self.gradientLayer.mask = layer;/////layer的背景色選中區(qū)域
    [self.layer addSublayer:self.gradientLayer];
    [self setNeedsDisplay];
}

-(void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    
    UIBezierPath *path = [UIBezierPath bezierPath];

    [self makeDownPointWithInsertNum:self.insertNum andPointsArray:self.pointsArray withPath:path];
    [self.lineColor setStroke];
    [path stroke];
}
////對數(shù)據(jù)進行插值處理 params: num參數(shù)表示插值的點數(shù),自己定嬉愧,點數(shù)越多贩挣,曲線越光滑   pointsArray參數(shù)表示要處理的所有點
- (void)makeDownPointWithInsertNum:(NSInteger)num andPointsArray:(NSArray *)pointsArray withPath:(UIBezierPath *)path
{
    /*
     插值法 使用說明 p1 和 p2 之間插值 要計算 p0 和 p3 
     其中 p0 是 p1 前面的一個點(如果p1已經(jīng)是數(shù)組里第一個點了,那p0就是p1點左下方一點,計算如例)
     p3 是p2 后面的一個點(如果p2已經(jīng)是最后一個點了,那p3就是p2正右上方的點)
     
     |
     |
     |
     |          .p2
     |
     |
     |                .p3
     |     .p1
     |
     |.p0
     |
     |__________________________________________________
     
     */
    for (int i = 0; i < pointsArray.count-1; i ++) {
        CGPoint p1 = CGPointFromString(pointsArray[i]);
        CGPoint p0;
        if (i == 0) {
            p0 = CGPointMake(p1.x-2, p1.y-2);
            [path moveToPoint:p1];
        }else{
            [path addLineToPoint:p1];
            p0 = CGPointFromString(pointsArray[i-1]);
        }
        CGPoint p2 = CGPointFromString(pointsArray[i + 1]);
        CGPoint p3 ;
        if (i == pointsArray.count - 2) {
            p3 = CGPointMake(p1.x+2, p1.y+2);
        }else{
            p3 = CGPointFromString(pointsArray[i + 2]);
        }

      ////這個是插值算法,不講了,固定寫法没酣,因為我也不會王财,裝B裝漏了 -_-|
        for (int i = 1; i <= num; i++) {
            float t = i * (1.0f / num);
            float tt = t * t;
            float ttt = tt * t;
            CGFloat pointx_x = (float) (0.5 * (2 * p1.x + (p2.x - p0.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * tt + (3 * p1.x - p0.x - 3 * p2.x + p3.x)
                                               * ttt));
            CGFloat pointx_y = (float) (0.5 * (2 * p1.y + (p2.y - p0.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * tt + (3 * p1.y - p0.y - 3 * p2.y + p3.y)
                                               * ttt));
            [path addLineToPoint:CGPointMake(pointx_x, pointx_y)];
        }
    }
}

#pragma mark -- getter/setter 專門負責添加漸變色

- (CAGradientLayer *)gradientLayer
{
    if (!_gradientLayer) {
        _gradientLayer = [CAGradientLayer layer];
        _gradientLayer.frame = self.bounds;
        _gradientLayer.colors = @[(__bridge id)kSetAlColor(kGetColorRed(_lineColor), kGetColorGreen(_lineColor), kGetColorBlue(_lineColor), 0.8).CGColor,(__bridge id)kSetAlColor(kGetColorRed(_lineColor), kGetColorGreen(_lineColor), kGetColorBlue(_lineColor), 0.1).CGColor];///其中漸變層的顏色種類,alpha表示所占的百分比
        _gradientLayer.startPoint = CGPointMake(0, 0);///表示開始的方位(左 裕便,上)
        _gradientLayer.endPoint = CGPointMake(0, 1);////結(jié)束方位(右绒净,下)
    }
    return _gradientLayer;
}

@end

最后是封裝的曲線類的使用

- (void)viewDidLoad {
    [super viewDidLoad];
    GradeColorView *colorView = [[GradeColorView alloc]initWithFrame:CGRectMake(80, 120, 250, 250)];
    [colorView updateUIWithPointArray:@[NSStringFromCGPoint(CGPointMake(0,250)),NSStringFromCGPoint(CGPointMake(20, 160)),NSStringFromCGPoint(CGPointMake(40, 100)),NSStringFromCGPoint(CGPointMake(60, 20)),NSStringFromCGPoint(CGPointMake(80, 90)),NSStringFromCGPoint(CGPointMake(100, 120)),NSStringFromCGPoint(CGPointMake(120, 80)),NSStringFromCGPoint(CGPointMake(140, 140)),NSStringFromCGPoint(CGPointMake(160, 190)),NSStringFromCGPoint(CGPointMake(250, 250))] insertNum:19 withLineColor:[UIColor orangeColor]];
    [self.view addSubview:colorView];

}

在下面是數(shù)組元素轉(zhuǎn)化便于數(shù)組存取的DataGetY類

.h文件

#import <Foundation/Foundation.h>
#define Str(f)   [NSString stringWithFormat:@"%f",f]

@interface DataGetY : NSObject
- (NSMutableDictionary *)makeDownDataWithDataArray:(NSArray *)points;
@end

.m文件

#import "DataGetY.h"
#import <UIKit/UIKit.h>

@implementation DataGetY

- (NSMutableDictionary *)makeDownDataWithDataArray:(NSArray *)points
{
    if (points.count > 0) {
        NSMutableDictionary *dic;
        for (NSString *pointStr in points) {
            CGPoint point = CGPointFromString(pointStr);
            [dic setObject:Str(point.y) forKey:Str(point.x)];
        }
        return dic;
    }
    return nil;
}
@end

下面是插值曲線的效果:


MyImg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末管钳,一起剝皮案震驚了整個濱河市鲁捏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亚兄,老刑警劉巖下翎,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缤言,死亡現(xiàn)場離奇詭異,居然都是意外死亡视事,警方通過查閱死者的電腦和手機胆萧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俐东,“玉大人鸳碧,你說我怎么就攤上這事盾鳞。” “怎么了瞻离?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵腾仅,是天一觀的道長。 經(jīng)常有香客問我套利,道長推励,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任肉迫,我火速辦了婚禮验辞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喊衫。我一直安慰自己跌造,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布族购。 她就那樣靜靜地躺著壳贪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪寝杖。 梳的紋絲不亂的頭發(fā)上违施,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音瑟幕,去河邊找鬼磕蒲。 笑死,一個胖子當著我的面吹牛只盹,可吹牛的內(nèi)容都是我干的辣往。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼殖卑,長吁一口氣:“原來是場噩夢啊……” “哼站削!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起懦鼠,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤钻哩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肛冶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體街氢,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年睦袖,在試婚紗的時候發(fā)現(xiàn)自己被綠了珊肃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖伦乔,靈堂內(nèi)的尸體忽然破棺而出厉亏,到底是詐尸還是另有隱情,我是刑警寧澤烈和,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布爱只,位于F島的核電站,受9級特大地震影響招刹,放射性物質(zhì)發(fā)生泄漏恬试。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一疯暑、第九天 我趴在偏房一處隱蔽的房頂上張望训柴。 院中可真熱鬧,春花似錦妇拯、人聲如沸幻馁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仗嗦。三九已至,卻和暖如春瞪浸,著一層夾襖步出監(jiān)牢的瞬間儒将,已是汗流浹背吏祸。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工对蒲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贡翘。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓蹈矮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸣驱。 傳聞我的和親對象是個殘疾皇子泛鸟,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 書寫的很好,翻譯的也棒踊东!感謝譯者北滥,感謝感謝! iOS-Core-Animation-Advanced-Techni...
    錢噓噓閱讀 2,292評論 0 6
  • 官網(wǎng)中文版 1 簡易天空替換## 技能:線性擦除闸翅,追蹤運動再芋,用顏色鍵K出人物,用色彩曲線調(diào)色坚冀。(1)天空圖片素材放...
    朱細細閱讀 10,664評論 4 82
  • 如何你想某事正確济赎,自己動手做吧。——Charles-Guillaume étienne 前一章介紹了隱式動畫的概念...
    liril閱讀 1,291評論 0 3
  • 欲買桂花同載酒司训,終不似构捡,少年游。 許是霧霾的原因壳猜,突然間抽瘋用電腦進空間把留言板從第一條翻了個遍勾徽。第一...
    劉太陽閱讀 812評論 6 18
  • 1-始源 故事發(fā)生于11月5號闪幽,某商場三名工作人員對著一名懷有三個月身孕的孕婦進行推搡期間啥辨,還對她進行掌摑。這時候...
    林大白不白閱讀 1,687評論 0 0