CorePlot 中的多个(分组)条

Multiple (grouped) bars in CorePlot

我需要创建一个图表,每个 x 轴将 3 个柱分组,类似于此图像:

我正在创建的图表如下图所示:

我的代码:

构建EVDChart

- (void)constructEVDChart
{
    CPTXYGraph *newGraph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];

    CPTTheme *theme = [CPTTheme themeNamed:@"Sales Farma"];
    [newGraph applyTheme:theme];

    self.hostingView.hostedGraph = newGraph;
    self.barChart = newGraph;

    newGraph.plotAreaFrame.masksToBorder = NO;
    newGraph.paddingLeft   = 60.0;
    newGraph.paddingTop    = 40.0;
    newGraph.paddingRight  = 20.0;
    newGraph.paddingBottom = 50.0;

    // Create grid line styles
    CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
    majorGridLineStyle.lineWidth = 1.0;
    majorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.15];

    // Add plot space for horizontal bar charts
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)newGraph.defaultPlotSpace;
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:@0.0 length:@30.0];
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:@0.0 length:@15.0];

    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)newGraph.axisSet;
    CPTXYAxis *x          = axisSet.xAxis;
    {
        x.axisLineStyle       = nil;
        x.majorTickLineStyle  = nil;
        x.minorTickLineStyle  = nil;
        x.majorIntervalLength = @2.5;
        x.orthogonalPosition  = @0.0;
        x.majorGridLineStyle = majorGridLineStyle;

        // Define some custom labels for the data elements
        //x.labelRotation  = CPTFloat(M_PI_4);
        x.labelingPolicy = CPTAxisLabelingPolicyNone;
    }

    CPTNumberArray customTickLocations  = @[@1, @5, @10, @15];
    CPTStringArray xAxisLabels          = @[@"Label A", @"Label B", @"Label C", @"Label D"];
    NSUInteger labelLocation            = 0;

    NSNumber * vTickLocation = @1.5;

    CPTMutableAxisLabelSet customLabels = [NSMutableSet setWithCapacity:xAxisLabels.count];
    for ( NSNumber *tickLocation in customTickLocations ) {
        CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] initWithText:xAxisLabels[labelLocation++] textStyle:x.labelTextStyle];
        newLabel.tickLocation = vTickLocation;
        newLabel.offset       = x.labelOffset + x.majorTickLength;
        [customLabels addObject:newLabel];

        vTickLocation = [NSNumber numberWithFloat:([vTickLocation floatValue] + 2.5)];
    }

    x.axisLabels = customLabels;

    CPTXYAxis *y = axisSet.yAxis;
    {
        y.axisLineStyle       = nil;
        y.majorTickLineStyle  = nil;
        y.minorTickLineStyle  = nil;
        y.majorIntervalLength = @5.0;
        y.orthogonalPosition  = @0.0;
        y.majorGridLineStyle = majorGridLineStyle;
    }

    // Profissional
    CPTBarPlot *profBar = [[CPTBarPlot alloc] init];
    profBar.dataSource = self;
    profBar.barOffset  = @0.50;
    profBar.barWidth   = @0.50;
    profBar.identifier = @"Bar Plot 1";
    profBar.delegate        = self;
    profBar.fill = [CPTFill fillWithColor:[CPTColor getCustomSFAColor:[UIColor sfaGraphOrangeColor]]];
    profBar.lineStyle = nil;
    [newGraph addPlot:profBar toPlotSpace:plotSpace];
    [profBar release];

    // PDV
    CPTBarPlot *pdvBar = [[CPTBarPlot alloc] init];
    pdvBar.dataSource      = self;
    pdvBar.barOffset       = @1.25;
    pdvBar.barWidth        = @0.50;
    pdvBar.identifier      = @"Bar Plot 2";
    pdvBar.delegate        = self;
    pdvBar.fill = [CPTFill fillWithColor:[CPTColor getCustomSFAColor:[UIColor sfaGraphBlueColor]]];
    pdvBar.lineStyle = nil;
    [newGraph addPlot:pdvBar toPlotSpace:plotSpace];
    [pdvBar release];

    // Estab
    CPTBarPlot *estabBar = [[CPTBarPlot alloc] init];
    estabBar.dataSource      = self;
    estabBar.barOffset       = @2.00;
    estabBar.barWidth        = @0.50;
    estabBar.identifier      = @"Bar Plot 3";
    estabBar.delegate        = self;
    estabBar.fill = [CPTFill fillWithColor:[CPTColor getCustomSFAColor:[UIColor sfaGraphGreenColor]]];
    estabBar.lineStyle = nil;
    [newGraph addPlot:estabBar toPlotSpace:plotSpace];
    [estabBar release];
}

情节记录数

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

绘图数量

- (nullable id)numberForPlot:(nonnull CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    NSNumber *num = nil;

    switch ( fieldEnum ) {
        case CPTBarPlotFieldBarLocation:
        {
            num = @(index);
            break;
        }
        case CPTBarPlotFieldBarTip:
            num = @( (index + 1) * 2 );
            break;
    }

    return num;
}

dataLabelForPlot

- (nullable CPTLayer *)dataLabelForPlot:(nonnull CPTPlot *)plot recordIndex:(NSUInteger)index
{
    static CPTMutableTextStyle *whiteText = nil;
    static dispatch_once_t onceToken      = 0;

    dispatch_once(&onceToken, ^{
        whiteText = [[CPTMutableTextStyle alloc] init];
        whiteText.color = [CPTColor whiteColor];
    });

    CPTTextLayer *newLayer = nil;

    if ( [plot isKindOfClass:[CPTPieChart class]] ) {
        switch ( index ) {
            case 0:
                newLayer = (id)[NSNull null];
                break;

            default:
                newLayer = [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:@"%lu", (unsigned long)index] style:whiteText];
                break;
        }
    }
    else if ( [plot isKindOfClass:[CPTScatterPlot class]] ) {
        newLayer = [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:@"%lu", (unsigned long)index] style:whiteText];
    }

    return newLayer;
}

条形间隔一个单位,但由于它们的宽度均为 0.5,因此无论您做什么,它们都会重叠。为了匹配示例图,将每个条形的宽度设置为 0.25。这让所有三个地块在一起,每组之间的差距为 0.25。使条形宽度略小(例如 0.2),以便在相邻条形之间也留出一个小间隙。我会使用 -0.25、0.0 和 0.25 的条形偏移。这将使分组集中在条形位置上,并在组之间留下一些 space。

数据标签没有显示,因为 -dataLabelForPlot:recordIndex: 总是 returns nil。该图是 CPTBarPlot,而数据标签方法仅为饼图和散点图创建标签。