由于在工作中需要繪制統(tǒng)計的折線圖數據,在網上搜了很多第三方,都寫的很厲害,但是作為實際需求,這些強大的第三方有兩個弊端,一是體積太大,占用內存都不算小,二是,看到的大部分都是需要各種編譯封裝,再學習他們的api,很麻煩(因為有之前使用linPhone的慘痛經歷)所以想到了為啥不自己寫一個,于是就有了現在這個代碼。
廢話不多說先上代碼核心代碼:
/** ?根據點的數組去設置一個折線統(tǒng)計圖 ?@param LCVFrame 折線圖的位置信息 ?@param MLColor 折線圖的xy軸的顏色 ?@param LCColor 折線圖的折線的顏色 ?@param pointArr 點的數組 ?@return 返回一個折線圖 ?*/ ?
- (CYKlineChartView *)_creatLineChartViewWithFrame:(CGRect)LCVFrame andMainLineColor:(UIColor *)MLColor andLineChartColor:(UIColor *)LCColor andFillColor:(UIColor *)fillColor forPointArray:(NSArray *)pointArr;
- (CYKlineChartView*)_creatLineChartViewWithFrame:(CGRect)LCVFrame andMainLineColor:(UIColor*)MLColor andLineChartColor:(UIColor*)LCColor andFillColor:(nonnullUIColor*)fillColor forPointArray:(nonnullNSArray*)pointArr{
? ? self.frame= LCVFrame;
? ? //先畫一個框
? ? UIBezierPath *bezierPath = [UIBezierPath bezierPath];
? ? CGPointlastPoint = [pointArr.lastObjectCGPointValue];
? ? //然后根據最后一個點 我們可以確定我們x軸點起始點的值
? ? CGPointxStarPoint =CGPointMake(lastPoint.x, LCVFrame.size.height);
? ? //然后根據數組中的第一個點 我們可以確定y軸的起始點的值
? ? CGPointstarPoint = [pointArr.firstObjectCGPointValue];
? ? CGPointyStarPoint =CGPointMake(0, starPoint.y);
? ? //接下來先畫x,y軸的兩條線
? ? [bezierPathmoveToPoint:xStarPoint];
? ? [bezierPathaddLineToPoint:CGPointMake(0, LCVFrame.size.height)];
? ? [bezierPathaddLineToPoint:yStarPoint];
? ? for(NSValue*pointValueinpointArr) {
? ? ? ? CGPointchartPoint = [pointValueCGPointValue];
? ? ? ? [bezierPathaddLineToPoint:chartPoint];
? ? }
? ? //線條填色
? ? CAShapeLayer *layer1 = [CAShapeLayer new];
? ? layer1.strokeColor= LCColor.CGColor;
? ? layer1.fillColor= fillColor.CGColor;
? ? layer1.lineWidth=1;
? ? layer1.path= [bezierPathCGPath];
? ? [self.layeraddSublayer:layer1];
? ? //在畫xy軸將其覆蓋掉
? ? UIBezierPath *bezierPath2 = [UIBezierPath bezierPath];
? ? [bezierPath2moveToPoint:CGPointMake(LCVFrame.size.width,0)];
? ? [bezierPath2addLineToPoint:CGPointMake(0, 0)];
? ? [bezierPath2addLineToPoint:CGPointMake(0, LCVFrame.size.height)];
? ? CGFloaty = LCVFrame.size.height/5;
? ? for(inti =0; i<6; i++) {
? ? ? ? UIBezierPath *bezierPathH = [UIBezierPath bezierPath]; //橫向的網格線
? ? ? ? [bezierPathHmoveToPoint:CGPointMake(0, y*i)];
? ? ? ? [bezierPathHaddLineToPoint:CGPointMake(LCVFrame.size.width, y*i)];
? ? ? ? CAShapeLayer *layerH = [CAShapeLayer new];
? ? ? ? layerH.strokeColor = [UIColor grayColor].CGColor;
? ? ? ? layerH.lineWidth=1;
? ? ? ? layerH.path= [bezierPathHCGPath];
? ? ? ? [self.layeraddSublayer:layerH];
? ? }
? ? //覆蓋y軸
? ? UIBezierPath *bezierPathV = [UIBezierPath bezierPath]; //橫向的網格線
? ? [bezierPathVmoveToPoint:CGPointMake(0,0)];
? ? [bezierPathVaddLineToPoint:CGPointMake(0, LCVFrame.size.height)];
? ? CAShapeLayer *layerV = [CAShapeLayer new];
? ? layerV.strokeColor = [UIColor whiteColor].CGColor;
? ? layerV.lineWidth=1;
? ? layerV.path= [bezierPathVCGPath];
? ? [self.layeraddSublayer:layerV];
? ? //最后再次畫點覆蓋所有的涂層
? ? for(NSValue*pointValueinpointArr) {
? ? ? ? CGPointchartPoint = [pointValueCGPointValue];
? ? ? ? UIBezierPath * bezierPathP = [UIBezierPath bezierPathWithArcCenter:chartPoint radius:2 startAngle:0.f endAngle:M_PI * 2 clockwise:YES];
? ? ? ? CAShapeLayer *layerP = [CAShapeLayer new];
? ? ? ? layerP.strokeColor = [UIColor redColor].CGColor;
? ? ? ? layerP.lineWidth=2;
? ? ? ? layerP.path= [bezierPathPCGPath];
? ? ? ? [self.layeraddSublayer:layerP];
? ? }
? ? return self;
}
解釋一下,這里的側重點有幾個,首先我們會傳入一個有關于我們要顯示的結果值的數組,這個數組我們經過占比計算之后將數值直接轉化為在這個視圖上我們要顯示的點的位置。
其次我們的思路就是一個圖層覆蓋一個圖層的去繪制出最終我們需要的折線圖,這就需要我們清楚的了解我們繪制圖層的順序是什么,這個很重要。
以此為例,我需要去繪制一個帶有填充區(qū)域的折線圖,所以首先我們要畫的就是這個區(qū)域,一個由x軸->y軸->數組中的每個點的一個非閉合區(qū)域。

那么它就會出現如圖中所示的x軸,y軸,折線,填充區(qū)域的第一個圖層
接著我們需要進行第二部分的圖層覆蓋,繪制我們自己所需要的x軸、y軸的圖層,顏色樣式可以自定義,怎么需要怎么畫,那么就會出現上圖中x軸y軸和剩下的輔助線(這里因為項目需要 我直接把y軸做成與底色一致的)。
最后我們要進行第三部分的圖層覆蓋,繪制我們需要的點的樣式,這里我用的是圓點,你可以自定義方形也好,五角星也好,甚至直接插入圖片也可以,這一步一定呀最后做,這樣能夠保證顯示的全面性。
后續(xù)如果還需要添加其他的數值或者是y軸的坐標,都可以再在此基礎上進行添加。
這里要注意一個問題,就是在數組存儲點的位置的時候我們需要先轉化為nsvalue類型的進行操作,結構體是不能直接寫入數組的。
此文到此就告一段落的,后續(xù)會有其他的貝塞爾曲線繪制控件圖層的用法,歡迎大家繼續(xù)探討。