CorePlot ScatterPlot labelingPolicy

CorePlot ScatterPlot labelingPolicy

我正在使用 CorePlot 绘制几个月内的平均价格。 这就是我想要实现的目标

我已经能够制作这个

很明显图表绘制不正确。

这是我在 viewController 中用来设置图形并绘制它的代码。

- (void)viewDidLoad {
[super viewDidLoad];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
NSDictionary *jsonDataDictionary;
// Can be done async with loading timers
NSURL *url = [NSURL URLWithString:
                @"http://greyloft.com/analytics/query.php?project=PARC%20VISTA&area=1200&months=5"];
NSData *urlData = [NSData dataWithContentsOfURL:url];

if (urlData) {
    NSError *error=nil;
    jsonDataDictionary = [NSJSONSerialization JSONObjectWithData:urlData
                                                          options:kNilOptions
                                                            error:&error];
    // We receive the order of the months in reverse order in the json i.e. most recent first.
    // e.g. Feb-15, Jan-15, Dec-14 and so on
    // We need to show plotting in reverse order on x axis effectively needing to reverse the array.
    NSArray *reverseAvgRentals = [[jsonDataDictionary objectForKey:@"results"] objectForKey:@"average"];
    _averageRentals = [[reverseAvgRentals reverseObjectEnumerator] allObjects];
    _transactions = [[jsonDataDictionary objectForKey:@"results"] objectForKey:@"transactions"];

    _months = [[NSMutableArray alloc] init];
    _rentals = [[NSMutableArray alloc] init];
    for (NSDictionary *rental in _averageRentals) {
        [_months addObject:[rental objectForKey:@"month"]];
        [_rentals addObject:[rental objectForKey:@"average"]];
    }
    // KVC to find min/max in an array
    _minRental = _maxRental = 0;
    _minRental = [[_rentals valueForKeyPath:@"@min.intValue"] intValue];
    _maxRental = [[_rentals valueForKeyPath:@"@max.intValue"] intValue];
}}

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
    return [_months count];
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
    NSNumber *num = [[NSNumber alloc] init];
    if (fieldEnum == CPTScatterPlotFieldX) {
        // Simply return index as we want to return number for each month
        num = [NSNumber numberWithInt:index+1];
    } else {
        num = [[_averageRentals objectAtIndex:index] valueForKey:@"average"];
    }
    return num;
}

    -(void)initPlot {
    [self configureHost];
    [self configureGraph];
    [self configurePlots];
    [self configureAxes];
}

-(void)configureHost {
    self.graphHostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.graphContainerView.bounds];
    self.graphHostView.allowPinchScaling = YES;
    [self.graphContainerView addSubview:self.graphHostView];
}

-(void)configureGraph {
    // Create the graph
    CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:self.graphHostView.bounds];
    [graph applyTheme:nil];
    self.graphHostView.hostedGraph = graph;
    [graph.plotAreaFrame setPaddingLeft:30.0f];
    [graph.plotAreaFrame setPaddingBottom:30.0f];
    [graph.plotAreaFrame setPaddingTop:10.0f];
}

-(void)configurePlots {
    // Get graph and plot space
    CPTGraph *graph = self.graphHostView.hostedGraph;
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;

    // 2 - Create the plot
    CPTScatterPlot *rentPlot = [[CPTScatterPlot alloc] init];
    rentPlot.dataSource = self;
    rentPlot.identifier = @"Rent";
    [graph addPlot:rentPlot toPlotSpace:plotSpace];

    // 3 - Set up plot space
    CGFloat xMin = 0.0f;
    CGFloat xMax = [_months count];
    CGFloat yMin = _minRental;
    CGFloat yMax = _maxRental;
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(xMin)
                                                    length:CPTDecimalFromFloat(xMax)];
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(yMin)
                                                    length:CPTDecimalFromFloat(yMax)];

    [plotSpace scaleToFitPlots:[graph allPlotSpaces]];
    CPTMutablePlotRange *xRange = [plotSpace.xRange mutableCopy];
    CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
    [xRange expandRangeByFactor:CPTDecimalFromDouble(1.4)];
    [yRange expandRangeByFactor:CPTDecimalFromDouble(3.0)];
    plotSpace.xRange = xRange;
    plotSpace.yRange = yRange;

    // 4 - Create styles and symbols
    //CPTColor *orangeColor = [CPTColor colorWithComponentRed:239.0f green:92.0f blue:94.0f alpha:1.0f];
    CPTColor *orangeColor = [CPTColor orangeColor];
    CPTMutableLineStyle *lineStyle = [rentPlot.dataLineStyle mutableCopy];
    lineStyle.lineWidth = 2.5f;
    lineStyle.lineColor = orangeColor;
    rentPlot.dataLineStyle = lineStyle;
    CPTMutableLineStyle *symbolLineStyle = [CPTMutableLineStyle lineStyle];
    symbolLineStyle.lineWidth = 2.5f;
    symbolLineStyle.lineColor = orangeColor;
    CPTPlotSymbol *symbol = [CPTPlotSymbol ellipsePlotSymbol];
    symbol.fill = [CPTFill fillWithColor:[CPTColor colorWithComponentRed:248.0f
                                                                   green:244.0f
                                                                    blue:251.0f
                                                                   alpha:1.0f]];
    symbol.lineStyle = symbolLineStyle;
    symbol.size = CGSizeMake(11.0f, 11.0f);
    rentPlot.plotSymbol = symbol;
}

-(void)configureAxes {
    // 1 - Create styles
    CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
    axisLineStyle.lineWidth = 0.0f;

    CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init];
    axisTextStyle.color = [CPTColor grayColor];
    axisTextStyle.fontName = @"Ubuntu-Bold";
    axisTextStyle.fontSize = 14.0f;

    CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
    majorGridLineStyle.lineWidth = 0.75;
    majorGridLineStyle.lineColor = [CPTColor lightGrayColor];

    // 2 - Get axis set
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.graphHostView.hostedGraph.axisSet;

    // 3 - Configure x-axis
    CPTXYAxis *x = axisSet.xAxis;
    x.axisLineStyle = axisLineStyle;
    x.labelingPolicy = CPTAxisLabelingPolicyNone;
    x.majorIntervalLength         = CPTDecimalFromDouble(1.0);
    x.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
    x.preferredNumberOfMajorTicks = 6;
    x.labelOffset = 50.0f;
    x.labelTextStyle = axisTextStyle;
    x.majorTickLineStyle = nil;
    x.minorTickLineStyle = nil;
    NSMutableSet *xLabelSet = [NSMutableSet setWithCapacity:[_months count]];
    NSMutableSet *xLocationSet = [NSMutableSet setWithCapacity:[_months count]];

    int location = 0;
    for (NSString *month in _months) {
        CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:month textStyle:x.labelTextStyle];
        label.tickLocation = CPTDecimalFromInt(location++);
        [xLabelSet addObject:label];
        [xLocationSet addObject:[NSNumber numberWithInteger:location]];
    }
    x.axisLabels = xLabelSet;
    x.majorTickLocations = xLocationSet;

    // 4 - Configure y-axis
    CPTXYAxis *y = axisSet.yAxis;
    y.axisLineStyle = axisLineStyle;
    y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
    y.orthogonalCoordinateDecimal = CPTDecimalFromDouble(-0.1);
    y.preferredNumberOfMajorTicks = 6;
    y.majorGridLineStyle = majorGridLineStyle;
    y.labelTextStyle = axisTextStyle;
    y.majorTickLineStyle = nil;
    y.minorTickLineStyle = nil;
}

我不明白 CorePlot 如何获取提供的数据并将其转换为所需的数据集。

有什么建议吗?

如我在上面的评论中所述,绘图范围采用 locationlength,如 NSRange。您可以使用位置的最小值和长度的 max - min

plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromCGFloat(yMin)
                                                length:CPTDecimalFromCGFloat(yMax - yMin)];

对于涵盖 1,500 到 4,000 的范围示例,请使用 1,500 作为位置,使用 2,500(4,000 - 1,500)作为长度。