【问题标题】:CorePlot ScatterPlot labelingPolicyCorePlot ScatterPlot labelingPolicy
【发布时间】:2015-04-10 20:15:04
【问题描述】:

我正在使用 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。您可以将locationmax - min 的最小值用于length
  • 问题不清楚。 “所需的集合”是什么意思?
  • 感谢 Eric 的反馈。我的意思是我如何推断 Y 轴的最小值、最大值我需要标签从 1500 开始到 4000 结束(所有值都在 3000 和 4000 之间)。我知道您在上面的评论中提到使用最小值作为位置,使用最大最小值作为长度。

标签: ios core-plot scatter-plot


【解决方案1】:

正如我在上面的评论中所指出的,绘图范围采用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) 作为长度。

【讨论】:

  • 好的……这有帮助……但是我根本看不到 x 轴……我唯一改变的是 CPTPlotRange plotRangeWithLocation: 到建议值。在此处查看屏幕截图 - drive.google.com/file/d/0BzNycg3hp-CmRl9OQ3ZLa21pTTg/… ...我正在使用 y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;我知道在幕后有一点魔力,它决定了它做得很好的 y 标签。然而,这对 x 轴标签有何影响?
  • 轴的交叉点由orthogonalCoordinateDecimal 确定。您已将 x 轴设置为在 y = 0 处穿过 y 轴。将其更改为 yMin 或使用 axisConstraints 来定位轴。
  • 1.约束偏移量是从绘图区域的边缘开始测量的,这也决定了网格线的范围。我无法想象你想要什么,但你需要调整约束偏移和填充。 2. 使用labelFormatter。使用所需的前缀字符串设置 NSNumberFormatter 并使用它来格式化标签。
  • 2.您想使用positivePrefix 和/或negativePrefix,而不是填充。
  • 1.你关心情节是否可以滚动标签吗?如果是这样,您需要调整左侧填充。否则,您可以使用gridLinesRange 来缩短网格线。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多