Search code examples
iosobjective-cgraphbubble-chart

Draw Bubble Graph in iOS?


hope you guys are doing well.

How can I draw graph similar to below image?

enter image description here

To be more specific, my graph will have low, normal and high risk with orange, green and red colours respectively. Each containing bubble with info in x- axis.

I wanna make exactly like above image any help would be appreciated and also please be specific while posting some third party libs and all.

How can I achieve the above graph?

Note- In X- axis (dates) and Y- axis [(values) in bubbles] are there.

EDIT y-axis is fixed with some range by x-axis is from server took in NSMutableArray

Thanks in advance.


Solution

  • First step in drawing graph is to create X-Y axis layout. You can draw X and Y axis line using UIBezierPath and CAShapeLayer.

        UIBezierPath *graphPath = [[UIBezierPath alloc]init];
        [graphPath setLineWidth:GRAPH_LAYOUT_LINE_WIDTH];
        [[UIColor blackColor] setStroke];
        [graphPath moveToPoint:CGPointMake(ORIGN_X, ORIGN_Y)];
        [graphPath addLineToPoint:CGPointMake((ORIGN_X + TOTAL_X_DIST),ORIGN_Y)];
        [graphPath stroke]; // drawing path
    
        //Creating graph layout
        CAShapeLayer *graphLayout = [CAShapeLayer layer];
        graphLayout.fillColor = [[UIColor clearColor] CGColor];
        graphLayout.strokeColor = [GRAPH_LAYOUT_COLOR CGColor];
        graphLayout.lineWidth = GRAPH_LAYOUT_LINE_THICKNESS;
        graphLayout.path = [graphPath CGPath];
        [self.layer addSublayer:graphLayout];
    

    Repeat the above code for drawing Y axis

    Second you need to create X and Y axis scale

        float minX = 0;
        float maxX = 10;
        float minY = 0;
        float maxY = 100;
    
        float x1Unit = 1;
        float y1Unit = 1;
    
        self.spacingX = TOTAL_X_DIST/((maxX - minX)/x1Unit);
        self.spacingY = TOTAL_Y_DIST/((maxY - minY+1)/y1Unit);
    

    Now you need to get the values(cartesian coordinate) of X and Y axis in an array, here i am just hard coding the points

    //Enter the co-ordinates
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(0, 50)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(1, 20)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(2, 35)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(3, 55)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(4, 80)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(5, 60)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(6, 85)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(7, 50)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(8, 30)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(9, 10)]];
        [self.pointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(10, 05)]];
    

    Next we need to convert cartesian coordinate values to values of x and y with respect to parent view.

    // Creating (x,y) points based on superview coordinate system
        for (NSValue *point in self.pointsArray)
        {
            CGPoint coordinate;
            coordinate.x = (STARTING_X*x1Unit + ([point CGPointValue].x * self.spacingX) + self.spacingX/1.5)/x1Unit;
            coordinate.y = (STARTING_Y*y1Unit - ([point CGPointValue].y * self.spacingY))/y1Unit;
    
            [self.coordinateArray addObject:[NSValue valueWithCGPoint:coordinate]];
    
        }
    

    Now it's time to add beautiful bubbles

    for (int a = 0; a < [self.coordinateArray count]; a++)
    {
        CGPoint point = [[self.coordinateArray objectAtIndex:a] CGPointValue];
    
    //Creating bubble for points on the graph.
    UIView *bubble = [[UIView alloc] initWithFrame:BUBBLE_FRAME];
    bubble.Layer.cornerRadius = BUBBLE_FRAME_WIDTH/2;
    
    //Giving the color for the bubble based on the Y-Axis value
    if (point.y <= 50)
    {
        bubble.backgroundColor = RED_COLOR;
    }
    else if (point.y > 50 && point.y <= 80)
    {
        bubble.backgroundColor = YELLOW_COLOR;
    }
    else
    {
        bubble.backgroundColor = GREEN_COLOR;
    }
    
    [self addSubview:bubble]; 
    }
    

    Hope this helps you