iOS折線圖

object-c折線,效果如圖


折線圖
- (void)viewDidLoad {
    [super viewDidLoad];
    //x y 軸上的標注數(shù)值
    NSArray *xArr = @[@"0",@"5",@"10",@"15",@"20",@"25",@"30",];
    NSArray *yArr = @[@"0",@"2",@"4",@"6",@"8",@"10",@"12",];
    //要畫的折線圖的各個點
    NSMutableArray *pointArr = [NSMutableArray array];
    for (int i=0; i<=20; i++)
    {
        CGPoint point = CGPointMake(i*1.5, random()%12);
        NSValue *value = [NSValue valueWithCGPoint:point];
        [pointArr addObject:value];
    }
    //傳入數(shù)值,畫折線圖
    BrokenLineDemo *demo = [[BrokenLineDemo alloc]initWithFrame:CGRectMake(50, 100, 300, 300) andXValue:xArr YValueArr:yArr andPointArr:pointArr];
    [self.view addSubview:demo];
}

主要其實就是畫線白修。重寫drawRect,再用CGContextRef重斑。

#define kChartLineColor         [UIColor grayColor]
#define kLightFrayColor         [UIColor colorWithWhite:0.8 alpha:1]
#define kChartTextColor         [UIColor lightGrayColor]

#define k_Space 10
#import "BrokenLineDemo.h"
@interface BrokenLineDemo()
@property(nonatomic,strong)NSArray *xValueArr;//x軸上的標注值
@property(nonatomic,strong)NSArray *yValueArr;//y軸上的標注值

@property(nonatomic,assign)float xSpace;//x軸每個標注之間相隔的frame距離
@property(nonatomic,assign)float ySpace;//y軸每個標注之間相隔的frame距離
@property(nonatomic,assign)float xValueSpace;//x軸每個標注之間相隔的數(shù)值 0 5 10 15
@property(nonatomic,assign)float yValueSpace;//y軸每個標注之間相隔的數(shù)值 0 2 4 6 8

@property(nonatomic,assign)CGPoint startPoint;//坐標起始點

@property(nonatomic,strong)NSMutableArray *pointArr;//要畫的點的數(shù)組
@property(nonatomic,strong)NSMutableArray *lastPointArr;//將要畫的點轉(zhuǎn)化為此坐標軸上的點(傳過來的點的坐標軸原點在左上方兵睛,轉(zhuǎn)為此坐標軸的原點在左下方)
@end

重寫init

-(instancetype)initWithFrame:(CGRect)frame andXValue:(NSArray *)xValueArr YValueArr:(NSArray *)yValueArr andPointArr:(NSMutableArray *)pointArr
{
    if (self=[super initWithFrame:frame])
    {
        self.xValueArr = xValueArr;//x軸的標注
        self.yValueArr = yValueArr;//y軸的標注
        self.pointArr = pointArr;//要畫的點的數(shù)值
        self.lastPointArr = [NSMutableArray array];//存放轉(zhuǎn)化坐標軸之后的點
        
        
        float xMin = [[xValueArr firstObject]floatValue];
        float xMax = [[xValueArr lastObject]floatValue];
        float yMin = [[yValueArr firstObject]floatValue];
        float yMax = [[yValueArr lastObject]floatValue];
        // x y 軸上每格的frame間距
        self.xSpace = (frame.size.width-k_Space*3)/(xValueArr.count-1);
        self.ySpace = (frame.size.height-k_Space*3)/(yValueArr.count-1);
        // x y 軸上每格的標注間隔數(shù)值,此x軸為5窥浪,y軸為2
        self.xValueSpace = (xMax-xMin)/(self.xValueArr.count-1);
        self.yValueSpace = (yMax-yMin)/(self.yValueArr.count-1);
        //畫圖的起點祖很,原點
         self.startPoint = CGPointMake(k_Space*2, frame.size.height-k_Space*2);
        //轉(zhuǎn)化坐標 例:傳入數(shù)值是(0,0)漾脂,原點在左上方假颇;轉(zhuǎn)化后因為原點在左下方上面一點點,因此點要畫在(k_Space*2, frame.size.height-k_Space*2)處
        for (int i=0; i<self.pointArr.count; i++)
        {
            NSValue *value = self.pointArr[i];
            CGPoint point = value.CGPointValue;
            CGPoint lastPoint = CGPointMake((point.x/_xValueSpace)*(_xSpace)+_startPoint.x, _startPoint.y-(point.y/_yValueSpace)*(_ySpace));
            [_lastPointArr addObject:[NSValue valueWithCGPoint:lastPoint]];
        }
    }
    return self;
}

畫線其實很簡單骨稿,調(diào)用CGContextRef的方法就好笨鸡,難點在于坐標的轉(zhuǎn)化。傳入的數(shù)值坦冠,都是以原點在左上方的坐標軸為標準的數(shù)值形耗。如圖,(0辙浑,0)激涤,(0,1)判呕,(0倦踢,2)等,你要是直接用此數(shù)值佛玄,那點就直接畫在最上邊的那條線上硼一,顯然是不對的累澡。如圖
傳入數(shù)值的坐標原點

我們要以左下方的那個點為坐標原點梦抢,進行轉(zhuǎn)換坐標。假如傳入的坐標是(10愧哟,6)奥吩,顯然x軸上標注數(shù)值相隔為5哼蛆,y軸標注數(shù)值相隔為2;設x軸每小格frame的間距為xSpace(即:x軸上每單元格在屏幕上的長度)霞赫,y軸上每小格的間距為ySpace(這兩個值都可以計算出來腮介,請看源碼);現(xiàn)原點(0端衰,0)距離重寫的view左邊間距為為20叠洗,下邊距為20;則
傳入為(10旅东,6)應該畫在屏幕上的點為:
X為


x

Y為(frame是重寫的view的frame)


y

以下方為坐標原點

坐標轉(zhuǎn)化后就可以直接畫點了灭抑,再講所有的點連線,over抵代。
思路就是這樣下面貼drawRect重寫腾节。(源碼地址:https://pan.baidu.com/s/1qYwrpBA
重寫drawRect

- (void)drawRect:(CGRect)rect
{
    CGContextRef context =UIGraphicsGetCurrentContext();
    //x軸上的值
    for (int i=0; i<_xValueArr.count; i++)
    {
        //x軸上的值
        NSString *xTitle = _xValueArr[i];
        [[UIColor blackColor]set];
        NSDictionary *attr =@{NSFontAttributeName:[UIFont systemFontOfSize:10]};
        CGSize labelSize = [xTitle sizeWithAttributes:attr];
        float originX = k_Space*2+(_xSpace)*i;
        CGRect xTitleRect  = CGRectMake(originX-labelSize.width/2, rect.size.height-k_Space-5, labelSize.width, labelSize.height);
         [self drawStr:xTitle withRect:xTitleRect textFontSize:10 textColor:kChartTextColor];
        //x軸上的豎線
        [self drawLine:context
            startPoint:CGPointMake(originX, rect.size.height-k_Space*2)
              endPoint:CGPointMake(originX, rect.size.height-k_Space*2-5)
             lineColor:kChartLineColor
             lineWidth:1];
    }
    //X軸
    [self drawLine:context
        startPoint:CGPointMake(k_Space*2, rect.size.height-k_Space*2)
          endPoint:CGPointMake(self.frame.size.width, rect.size.height-k_Space*2)
         lineColor:kChartLineColor
         lineWidth:1];
    for (int i=0; i<_yValueArr.count; i++)
    {
        //y軸上的值
        NSString *yTitle = _yValueArr[i];
        [[UIColor blackColor]set];
        NSDictionary *attr =@{NSFontAttributeName:[UIFont systemFontOfSize:10]};
        CGSize labelSize = [yTitle sizeWithAttributes:attr];
        
        float yOrigin =  _startPoint.y-(_ySpace*i);
        CGRect yTitleRect  = CGRectMake(k_Space, yOrigin-labelSize.height/2, labelSize.width, labelSize.height);
         [self drawStr:yTitle withRect:yTitleRect textFontSize:10 textColor:kChartTextColor];
         //畫y軸上的橫線
        if (i>0)
        {
            [self drawLine:context
                startPoint:CGPointMake(_startPoint.x,yOrigin)
                  endPoint:CGPointMake(rect.size.width,yOrigin)
                 lineColor:kLightFrayColor
                 lineWidth:1];
        }
    }
    //y軸
    [self drawLine:context
        startPoint:_startPoint
          endPoint:CGPointMake(_startPoint.x,0)
         lineColor:kChartLineColor
         lineWidth:1];
    
    //畫point
    for (int i=0; i<self.pointArr.count; i++)
    {
        NSValue *value = self.lastPointArr[i];
        CGPoint point = value.CGPointValue;
        //畫點
        [self drawPointWithContext:context point:point color:[UIColor lightGrayColor]];
        
        //畫點上的值
        NSValue *oldValue = self.pointArr[i];
        CGPoint oldPoint = oldValue.CGPointValue;
        NSString *valueStr = [NSString stringWithFormat:@"%.2f",oldPoint.y];
        CGSize labelSize = [valueStr sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:10]}];
        CGRect valueStrRect  = CGRectMake(point.x-labelSize.width/2, point.y-5-labelSize.height, labelSize.width, labelSize.height);
        [self drawStr:valueStr withRect:valueStrRect textFontSize:10 textColor:kChartTextColor];
        //畫折線
        if (i<_lastPointArr.count-1)
        {
            NSValue * endValaue = _lastPointArr[i+1];
            CGPoint endPoint =[endValaue CGPointValue];
            //畫折線
              [self drawLine:context startPoint:point endPoint:endPoint lineColor:[UIColor colorWithRed:26/255.0 green:135/255.0 blue:254/255.0 alpha:1] lineWidth:1];
        }
    }
}
//畫文字
- (void)drawStr:(NSString *)titleStr  withRect:(CGRect)rect textFontSize:(float)fontSize textColor:(UIColor *)textColor
{
    UIFont *font =  [UIFont systemFontOfSize:fontSize];
      [titleStr drawInRect:rect withAttributes:@{NSFontAttributeName :font,NSForegroundColorAttributeName:textColor}];
}

//畫點
-(void)drawPointWithContext:(CGContextRef)context point:(CGPoint )point color:(UIColor *)pointColor
{
    CGContextSetFillColorWithColor(context, pointColor.CGColor);//填充顏色
    CGContextAddArc(context, point.x, point.y, 2, 0, 2*M_PI, 0); //添加一個圓
    CGContextDrawPath(context, kCGPathFill);//繪制填充
}
//畫線
- (void)drawLine:(CGContextRef)context startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint lineColor:(UIColor *)lineColor lineWidth:(CGFloat)width {
    
    CGContextSetShouldAntialias(context, YES ); //抗鋸齒
    CGColorSpaceRef Linecolorspace1 = CGColorSpaceCreateDeviceRGB();
    CGContextSetStrokeColorSpace(context, Linecolorspace1);
    CGContextSetLineWidth(context, width);
    CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
    CGContextMoveToPoint(context, startPoint.x, startPoint.y);
    CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
    CGContextStrokePath(context);
    CGColorSpaceRelease(Linecolorspace1);
}

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市荤牍,隨后出現(xiàn)的幾起案子案腺,更是在濱河造成了極大的恐慌,老刑警劉巖康吵,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劈榨,死亡現(xiàn)場離奇詭異,居然都是意外死亡晦嵌,警方通過查閱死者的電腦和手機鞋既,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耍铜,“玉大人邑闺,你說我怎么就攤上這事∽丶妫” “怎么了陡舅?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長伴挚。 經(jīng)常有香客問我靶衍,道長,這世上最難降的妖魔是什么茎芋? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮田弥,結果婚禮上涛酗,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好商叹,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布燕刻。 她就那樣靜靜地躺著,像睡著了一般剖笙。 火紅的嫁衣襯著肌膚如雪卵洗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天弥咪,我揣著相機與錄音过蹂,去河邊找鬼。 笑死聚至,一個胖子當著我的面吹牛榴啸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晚岭,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鸥印,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了坦报?” 一聲冷哼從身側響起库说,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎片择,沒想到半個月后潜的,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡字管,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年啰挪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘲叔。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡亡呵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出硫戈,到底是詐尸還是另有隱情锰什,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布丁逝,位于F島的核電站汁胆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏霜幼。R本人自食惡果不足惜嫩码,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罪既。 院中可真熱鬧铸题,春花似錦铡恕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猩谊。三九已至千劈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間牌捷,已是汗流浹背墙牌。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暗甥,地道東北人喜滨。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像撤防,于是被迫代替她去往敵國和親虽风。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

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

  • PNChart 去年項目中用到了折線圖寄月,當時因為項目趕的緊辜膝,于是下載了GitHub上排行前幾名的圖表框架,看一下哪...
    堂吉訶德灬閱讀 1,760評論 8 12
  • 總結一下最近項目中需要使用到的折線圖的展示漾肮,首先說下折線圖演示的一下幾種情況1 當數(shù)據(jù)出現(xiàn)有正數(shù)和負數(shù)厂抖,那么折現(xiàn)就...
    嘿晴天閱讀 1,304評論 1 2
  • 一、畫出X克懊,Y軸 二忱辅、分別給X坐標和Y坐標添加代表的屬性值 三、畫折線圖 結果圖
    管你愛不愛閱讀 829評論 0 1
  • 從開始使用初始化說起首先初始化個LineGraph視圖谭溉,賦值XY軸數(shù)組墙懂,XY軸的最大值,XY軸的顏色扮念,每條折線所代...
    馬大俊不是啥好人閱讀 1,339評論 2 3
  • 最近一直在斷斷續(xù)續(xù)的搞一些簡單的動畫效果,感覺效果還不錯,其中也有很多道友對效果的實現(xiàn)提出了有意義的建議(十分感謝...
    健健鍋閱讀 25,946評論 21 132