Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create stacked bar graph using uibezierpath in ios with different colors

Please help me to create a stacked bar graph using only one bezier path. I am creating bar by using below code

//creating graph path
UIBezierPath *graph = [[UIBezierPath alloc]init];
[graph setLineWidth:_barWidth - _barWidth*0.1];

//Creating graph layout
self.graphLayout = [CAShapeLayer layer];
self.graphLayout.fillColor = [[UIColor clearColor] CGColor];
self.graphLayout.strokeColor = [[UIColor grayColor] CGColor];
self.graphLayout.lineWidth = _barWidth - _barWidth*0.1;;
self.graphLayout.path = [graph CGPath];
_graphLayout.lineCap = @"round";
_graphLayout.lineJoin = @"round";

[self.layer addSublayer:self.graphLayout];


for (DataSource *dataSource in self.graphCoordinateArray)
{
    [graph moveToPoint:CGPointMake((dataSource.postion*_barWidth) + _barWidth/2, STARTING_Y)];
    [graph addLineToPoint: CGPointMake((dataSource.postion*_barWidth) + _barWidth/2, dataSource.y)];
}

I need some thing like this

like image 704
mahesh.me Avatar asked Oct 18 '22 05:10

mahesh.me


1 Answers

Based on sectors you need, you must create that many UIBezierPaths and CAShapeLayer. So since your stacked bar graph needs 3 sectors, you need 3 UIBeziersPaths and CAShapeLayer

Here is what you need to do:

  • Draw one sector using one UIBezierPath and one CAShapeLayer. After drawing each bar store end points in an array which you will need to for second UIBeziersPath i.e, for the second sector.
  • Draw second sector UIBeziersPath using End point array from first sector and do the same for the 3rd sector.

Following is the code that you can try:

     UIBezierPath *path1 = [[UIBezierPath alloc]init];
     [[UIColor grayColor] setStroke];

     UIBezierPath *path2 = [[UIBezierPath alloc]init];
     [[UIColor redColor] setStroke];

      UIBezierPath *path3 = [[UIBezierPath alloc]init];
     [[UIColor blueColor] setStroke];     

     //CAShapeLayer for graph allocation
     CAShapeLayer *path1GraphLayer = [CAShapeLayer layer];
     path1GraphLayer.frame = CGRectMake(self.frame.size.width*0, 0, self.frame.size.width, self.frame.size.height*0.9);
     path1GraphLayer.fillColor = [[UIColor clearColor] CGColor];
     UIColor *color = [UIColor greenColor];
     path1GraphLayer.strokeColor = color.CGColor;
     path1GraphLayer.lineWidth = 9;

     //CAShapeLayer for graph allocation
     CAShapeLayer *path2GraphLayer = [CAShapeLayer layer];
     path2GraphLayer.frame = CGRectMake(self.frame.size.width*0, 0, self.frame.size.width, self.frame.size.height*0.9);
     path2GraphLayer.fillColor = [[UIColor clearColor] CGColor];
     UIColor *color = [UIColor redColor];
     path2GraphLayer.strokeColor = color.CGColor;
     path2GraphLayer.lineWidth = 9;

     //CAShapeLayer for graph allocation
     CAShapeLayer *path3GraphLayer = [CAShapeLayer layer];
     path3GraphLayer.frame = CGRectMake(self.frame.size.width*0, 0, self.frame.size.width, self.frame.size.height*0.9);
     path3GraphLayer.fillColor = [[UIColor clearColor] CGColor];
     UIColor *color = [UIColor blueColor];
     path3GraphLayer.strokeColor = color.CGColor;
     path3GraphLayer.lineWidth = 9;



    //Data count means the number of stack bars you need
    for(int i=0 ;i<data.count;i++)
    {
    //path1Value, path2Value, path3Value are values of each sector, get these from a data source which you need to create

     float maxTotalValue = path1Value+path2Value+path3Value;
     float path1Percentage = (float)path1Value/ (float)maxTotalValue;
     float path2Percentage = (float)path2Value/ (float)maxTotalValue;
     float path3Percentage = (float)path3Value/ (float)maxTotalValue;

     //_spacing is the space between each bars you want to maintain

     [path1 moveToPoint:CGPointMake((self.frame.size.width*0.1)+_spacing, (self.frame.size.height*0.9))];

     [path1 addLineToPoint:CGPointMake(self.frame.size.width*0.1+_spacing,(self.frame.size.height*0.9)-((self.frame.size.height*0.9)*(1 - path1Percentage)))];

     [path2 moveToPoint:CGPointMake(self.frame.size.width*0.1+_spacing,(self.frame.size.height*0.9)-((self.frame.size.height*0.9)*(1 -path1Percentage)))];

     [path2 addLineToPoint:CGPointMake(self.frame.size.width*0.1+_spacing,(self.frame.size.height*0.9)-((self.frame.size.height*0.9)*(1 -path2StatePercentage - path1StatePercentage )))];

     [path3 moveToPoint:CGPointMake(self.frame.size.width*0.1+_spacing,(self.frame.size.height*0.9)-((self.frame.size.height*0.9)*(1 -path2StatePercentage - path1StatePercentage )))];

     [path3 addLineToPoint:CGPointMake(self.frame.size.width*0.1+_spacing,(self.frame.size.height*0.9)-((self.frame.size.height*0.9)*(1 -path2StatePercentage - path1StatePercentage-path3StatePercentage )))];
    }
like image 57
Basanth Avatar answered Oct 21 '22 05:10

Basanth