Objective C核心图固定Y轴的条形图

时间:2014-03-07 17:26:04

标签: ios objective-c graph core-plot

我正在尝试使用Core Plot库为iOS应用程序创建一个可用于创建条形图,饼图和折线图的类。我想在这个类中创建一些标准化,这样我只需为每个继承我的图类的视图控制器更改一些选项。我的饼图按照我想要的方式工作,但我对条形图有问题。我想要一个水平的条形图,根据有多少个图,每个图的Y轴都是固定的。

代码:

enum
{
    PieGraph = 0,
    LineGraph,
    BarGraph
};

Graph.h:

#import "CorePlot-CocoaTouch.h"
#import "BaseViewController.h"

CPTGraphHostingView *hostView;

CPTTheme *selectedTheme;

/*************** graphing options *******************/

int graphType;
int fillPercentage;

CGFloat xMax;
CGFloat yMax;

NSString *graphTitle;
NSString *xAxisTitle;
NSString *yAxisTitle;

BOOL graphOnBottom;

@interface Graph : BaseViewController<CPTPlotDataSource, UIActionSheetDelegate, CPTBarPlotDataSource, CPTBarPlotDelegate>

/*************** Methods *****************/


// graphing methods
-(void)initPlot;
-(void)configureHost;
-(void)configureGraph;
-(void)configureChart;
-(void)configureLegend;
-(void)configurePlots;
-(void)configureAxes;

@end

Graph.m:

#import "Graph.h"

@implementation Graph

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self initPlot];
}

/************************ Methods *************************/

// initialize the entire graph plot
-(void)initPlot
{
    [self configureHost];
    [self configureGraph];
    if (graphType == PieGraph)
    {
        [self configureChart];
        [self configureLegend];
    }
    else if (graphType == BarGraph)
    {
        [self configurePlots];
        [self configureAxes];
    }
}

// configure the host
-(void)configureHost
{
    CGRect parentRect = self.view.bounds;

    int maxHeight = (parentRect.size.height - 55);
    int height = (maxHeight - ((100 - fillPercentage) * maxHeight / 100));

    int yPosition;
    if (graphOnBottom) yPosition = (maxHeight - height + 55);
    else yPosition = 55;

    parentRect = CGRectMake(parentRect.origin.x, yPosition, parentRect.size.width, height);

    hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:parentRect];
    hostView.allowPinchScaling = NO;

    [self.view addSubview:hostView];
}

// configure the graph
-(void)configureGraph
{
    CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:hostView.bounds];
    hostView.hostedGraph = graph;

    if (graphType == PieGraph)
    {
        graph.paddingLeft = 0.0f;
        graph.paddingTop = 0.0f;
        graph.paddingRight = 0.0f;
        graph.paddingBottom = 0.0f;
        graph.axisSet = nil;
    }
    else if (graphType == BarGraph)
    {
        graph.plotAreaFrame.masksToBorder = NO;

        if ([xAxisTitle isEqualToString:@""]) graph.paddingBottom = 0.0f;
        else graph.paddingBottom = 30.0f;
        if ([yAxisTitle isEqualToString:@""]) graph.paddingLeft = 0.0f;
        else graph.paddingLeft = 30.0f;
        graph.paddingTop = 0.0f;
        graph.paddingRight = 0.0f;

        CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
        plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromCGFloat(0.0f) length:CPTDecimalFromCGFloat(xMax)];
        plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromCGFloat(0.0f) length:CPTDecimalFromCGFloat(yMax)];
    }
    else if (graphType == LineGraph)
    {

    }

    CPTMutableTextStyle *textStyle = [CPTMutableTextStyle textStyle];
    textStyle.color = [CPTColor blackColor];
    textStyle.fontName = @"Helvetica-Bold";
    textStyle.fontSize = 12.0f;

    graph.title = graphTitle;
    graph.titleTextStyle = textStyle;
    graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;

    selectedTheme = [CPTTheme themeNamed:kCPTPlainWhiteTheme];
    [graph applyTheme:selectedTheme];
}

// configure the chart
-(void)configureChart
{
    CPTGraph *graph = hostView.hostedGraph;

    CPTGradient *overlayGradient = [[CPTGradient alloc] init];
    overlayGradient.gradientType = CPTGradientTypeRadial;
    overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.0] atPosition:0.9];
    overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.4] atPosition:1.0];

    CPTPieChart *pieChart = [[CPTPieChart alloc] init];

    pieChart.dataSource = self;
    pieChart.delegate = self;
    pieChart.pieRadius = (hostView.bounds.size.height * 0.7) / 2.5;
    pieChart.identifier = graph.title;
    pieChart.startAngle = M_PI_4;
    pieChart.sliceDirection = CPTPieDirectionClockwise;

    pieChart.overlayFill = [CPTFill fillWithGradient:overlayGradient];

    [graph addPlot:pieChart];
}

// configure plots
-(void)configurePlots
{
    CPTGraph *graph = hostView.hostedGraph;

    if (graphType == BarGraph)
    {
        CPTMutableLineStyle *barLineStyle = [[CPTMutableLineStyle alloc] init];
        barLineStyle.lineColor = [CPTColor lightGrayColor];
        barLineStyle.lineWidth = 0.5;

        CPTBarPlot *bar = [CPTBarPlot tubularBarPlotWithColor:[CPTColor redColor] horizontalBars:YES];

        bar.dataSource = self;
        bar.delegate = self;
        bar.barWidth = CPTDecimalFromFloat(2.5f);
        bar.barOffset = CPTDecimalFromFloat(2.5f);
        bar.identifier = @"redBar";

        bar.lineStyle = barLineStyle;

        CPTBarPlot *bar2 = [CPTBarPlot tubularBarPlotWithColor:[CPTColor greenColor] horizontalBars:YES];

        bar2.dataSource = self;
        bar2.delegate = self;
        bar2.barWidth = CPTDecimalFromFloat(2.5f);
        bar2.barOffset = CPTDecimalFromFloat(2.5f);
        bar2.identifier = @"greenBar";

        bar2.lineStyle = barLineStyle;

        [graph addPlot:bar toPlotSpace:graph.defaultPlotSpace];
        [graph addPlot:bar2 toPlotSpace:graph.defaultPlotSpace];
    }
    else if (graphType == LineGraph)
    {

    }
}

// configure axes
-(void)configureAxes
{
    if (graphType == BarGraph)
    {
        CPTMutableTextStyle *axisTitleStyle = [CPTMutableTextStyle textStyle];
        axisTitleStyle.color = [CPTColor blackColor];
        axisTitleStyle.fontName = @"Helvetica-Bold";
        axisTitleStyle.fontSize = 12.0f;
        CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
        axisLineStyle.lineWidth = 2.0f;
        axisLineStyle.lineColor = [[CPTColor blackColor] colorWithAlphaComponent:1];

        CPTXYAxisSet *axisSet = (CPTXYAxisSet *) hostView.hostedGraph.axisSet;

        axisSet.xAxis.labelingPolicy = CPTAxisLabelingPolicyNone;
        axisSet.xAxis.title = xAxisTitle;
        axisSet.xAxis.titleTextStyle = axisTitleStyle;
        axisSet.xAxis.titleOffset = 5.0f;
        axisSet.xAxis.axisLineStyle = axisLineStyle;

        axisSet.yAxis.labelingPolicy = CPTAxisLabelingPolicyNone;
        axisSet.yAxis.title = yAxisTitle;
        axisSet.yAxis.titleTextStyle = axisTitleStyle;
        axisSet.yAxis.titleOffset = 5.0f;
        axisSet.yAxis.axisLineStyle = axisLineStyle;
    }
    else if (graphType == LineGraph)
    {

    }
}

// configure the legend
-(void)configureLegend
{
    CPTGraph *graph = hostView.hostedGraph;

    CPTLegend *legend = [CPTLegend legendWithGraph:graph];

    legend.numberOfColumns = 1;
    legend.fill = [CPTFill fillWithColor:[CPTColor whiteColor]];
    legend.borderLineStyle = [CPTLineStyle lineStyle];
    legend.cornerRadius = 5.0;

    graph.legend = legend;
    graph.legendAnchor = CPTRectAnchorBottomLeft;
    //CGFloat legendPadding = -(self.view.bounds.size.width / 8);
    graph.legendDisplacement = CGPointMake(3.0, 3.0);
}

@end

最后我正在测试所有这些视图控制器类:

TestView.h:

#import "Graph.h"

NSArray *channel;

int offline;
int online;

@interface TestView : Graph

/*************** Methods *****************/

// back button
- (IBAction)backButtonClicked:(id)sender;

// handle view load
-(void) handleViewLoad;

// set arrays
-(void)setArrays;

@end

TestView.m:

#import "TestView.h"

@interface TestView ()

@end

@implementation TestView

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self handleViewLoad];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)backButtonClicked:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

/*************** graph things ****************/

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    return 1;
}

-(NSNumber*)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)idx
{
    int returnVal = 0;
    NSLog([NSString stringWithFormat:@"idx: %d", idx]);
    /*switch (idx)
    {
        case 0:
            for (int x = 0; x < [channel count]; x++)
            {
                if ([channel[x] integerValue] == 20) returnVal ++;
            }
            offline = returnVal;
            return [NSNumber numberWithInt:returnVal];
            break;

        case 1:
            for (int x = 0; x < [channel count]; x++)
            {
                if ([channel[x] integerValue] != 20) returnVal ++;
            }
            online = returnVal;
            return [NSNumber numberWithInt:returnVal];
            break;
    }*/
    if ([plot.identifier isEqual:@"greenBar"])
    {
        for (int x = 0; x < [channel count]; x++)
        {
            if ([channel[x] integerValue] != 20) returnVal ++;
        }
        online = returnVal;
        return [NSNumber numberWithInt:returnVal];
    }
    else if ([plot.identifier isEqual:@"redBar"])
    {
        for (int x = 0; x < [channel count]; x++)
        {
            if ([channel[x] integerValue] == 20) returnVal ++;
        }
        offline = returnVal;
        return [NSNumber numberWithInt:returnVal];
    }
    return 0;
}

-(CPTLayer*)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)idx
{
    /*switch (idx)
    {
        case 0:
            return [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:@"Offline: %d", offline]];
            break;

        default:
            return [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:@"Online: %d", online]];
            break;
    }*/

    if ([plot.identifier isEqual:@"greenBar"])
    {
        return [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:@"Online: %d", online]];
    }
    else if ([plot.identifier isEqual:@"redBar"])
    {
        return [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:@"Offline: %d", offline]];
    }
    return nil;
}

-(NSString*)legendTitleForPieChart:(CPTPieChart*)pieChart recordIndex:(NSUInteger)idx
{
    switch (idx)
    {
        case 0:
            return @"Offline";
            break;

        default:
            return @"Online";
            break;
    }

    return @"";
}

// handle view load
-(void)handleViewLoad
{
    session = [BaseViewController getSession];
    [self setArrays];

    graphType = BarGraph;
    fillPercentage = 50;
    graphOnBottom = NO;
    graphTitle = @"Coordinators Online/Offline";
    xAxisTitle = @"Number of Devices";
    yAxisTitle = @"";
    xMax = (CGFloat)([channel count] + ([channel count] * 0.30f));
    yMax = (CGFloat)([channel count] + ([channel count] * 0.30f));

    [self initPlot];
}

// set arrays
-(void)setArrays
{
    channel = [Json extractCoordinatorChannel:session];
}

@end

以下是我的图表的一些示例:

enter image description here

enter image description here

如您所见,问题是x轴和y轴都根据值而变化。我只需要改变x轴,并且每个绘图都需要固定y轴。

1 个答案:

答案 0 :(得分:0)

数据源应检查fieldEnum参数,以查看请求的数据字段(条形位置或条形尖端)。

switch ( fieldEnum ) {
    case CPTBarPlotFieldBarLocation:
        returnVal = /* y value */;
        break;

    case CPTBarPlotFieldBarTip:
        returnVal = /* x value */;
        break;

    default:
        break;
}