【问题标题】:Core plot with month on x Axis (iphone)x轴上带有月份的核心图(iphone)
【发布时间】:2011-02-08 10:18:41
【问题描述】:

我想在 iphone 上使用 coreplot 绘制一个 XY 图,x 轴为日期,y 轴为一些值。参考与 coreplot SDK 一起提供的 DatePlot 示例,我能够在 x 轴上按月绘制带有日期的图表(即 x 范围从一个月的 1 个日期到最后一个日期)。现在我想要一个年度规模,即我想在 x 轴上显示所有月份名称(Jan、Feb、Mar 等),并将我的刻度间隔显示为一个月时间。

我使用以下代码来显示每月的值

oneXUnit        =   60 * 60 * 24;
x.majorIntervalLength    =  CPDecimalFromFloat((float) oneXUnit);
NSDateFormatter *dateFormatter   =   [[[NSDateFormatter alloc] init]autorelease];
NSString *dateString        =   @"0";
[dateFormatter setDateFormat:@"MM"];
CPTimeFormatter *timeFormatter  =   [[CPTimeFormatter alloc]initWithDateFormatter:dateFormatter];
timeFormatter.referenceDate =   [dateFormatter dateFromString:dateString];
x.labelFormatter    =   timeFormatter;

现在对于年度模式,x 刻度间隔需要为一个月。我尝试了下面的代码,但没有工作

oneXUnit        =   60 * 60 * 24 * 30;
x.majorIntervalLength    =  CPDecimalFromFloat((float) oneXUnit);
NSDateFormatter *dateFormatter   =   [[[NSDateFormatter alloc] init]autorelease];
NSString *dateString        =   @"Jan";
[dateFormatter setDateFormat:@"MMM"];
CPTimeFormatter *timeFormatter  =   [[CPTimeFormatter alloc]initWithDateFormatter:dateFormatter];
timeFormatter.referenceDate =   [dateFormatter dateFromString:dateString];
x.labelFormatter    =   timeFormatter;   

我认为这个逻辑失败了,因为每个月的天数不同。现在月份在 x 轴上显示,但它显示为

1 月、3 月、4 月、5 月、5 月、6 月、7 月、8 月、9 月、10 月、11 月、12 月。

您可以看到没有 2 月,而 5 月有 2 个条目。我的刻度间隔如何与每个月的天数相关。有什么解决办法吗? 感谢和问候,

【问题讨论】:

    标签: iphone date graph axis


    【解决方案1】:

    我遇到了同样的问题。我的快速而肮脏的解决方案是进行自定义标签,循环整个月并将时间戳添加到数组中。

    x.labelingPolicy = CPAxisLabelingPolicyNone;
    
    NSMutableArray *customLabels = [NSMutableArray arrayWithCapacity:12];
    NSMutableArray *customMajorTickLocations = [NSMutableArray arrayWithCapacity:12];
    NSMutableArray *customMinorTickLocations = [NSMutableArray arrayWithCapacity:12];
    NSDate* dateCurrentMonth = [[NSDate date] dateAtStartOfYear];
    
    for (NSUInteger iMonth = 0; iMonth < 12; iMonth++)
    {
        NSNumber* numMajorTickLocation = [NSNumber numberWithDouble:[dateCurrentMonth timestampAtMidnight]];
        NSNumber* numMinorTickLocation = [NSNumber numberWithDouble:[dateCurrentMonth timestampAtMidnight]+14*oneDay];
    
    CPAxisLabel *newLabel = [[CPAxisLabel alloc] initWithText:[dateFormatter stringFromDate:dateCurrentMonth] textStyle:x.labelTextStyle];
    newLabel.tickLocation = [numMinorTickLocation decimalValue];
    newLabel.offset = x.labelOffset + x.majorTickLength;
    
    dateCurrentMonth = [[dateCurrentMonth dateByAddingDays:32] dateAtStartOfMonth];
    
    [customLabels addObject:newLabel];
    [customMajorTickLocations addObject:numMajorTickLocation];
    [customMinorTickLocations addObject:numMinorTickLocation];
    [newLabel release];
    
    }
    
    // add a last major tick to close the range
    [customMajorTickLocations addObject:[NSNumber numberWithDouble:[dateCurrentMonth timestampAtMidnight]]];
    
    x.axisLabels = [NSSet setWithArray:customLabels];
    x.majorTickLocations = [NSSet setWithArray:customMajorTickLocations];
    x.minorTickLocations = [NSSet setWithArray:customMinorTickLocations];
    

    【讨论】:

    • 我有一个问题,因为我使用的是 CPTAxisLabelingPolicyAutomatic,当我放大缩小时,x 轴已重新绘制为 1 到 10。
    【解决方案2】:

    刚刚回答了一个相关问题。使用 CPTCalendarFormatter 而不是 CPTTimeFormatter,这在您必须以秒为单位设置时间间隔偏移量(例如小时 = 60*60,日 = 24*60*60)时很好,但月份的天数/秒数(30* 24*60*60 或 31*24*60*60, 28, 闰年 ecc.)。 CPTCalendarFormatter 让您决定标签上日期计算的日历单位。这样,固定了参考日期和参考日历单位,在数据源方法中,您将必须返回从参考日期开始的这些单位的数量。

    这是完整的代码,享受吧。

    在您的 viewDidLoad 或其他地方初始化图表:

    [...]
    
    // Graph host view
    CPTGraphHostingView* hostView = [[CPTGraphHostingView alloc] initWithFrame:self.view.frame];
    [self.view addSubview: hostView];
    
    // Your graph
    CPTGraph* graph = [[CPTXYGraph alloc] initWithFrame:hostView.bounds];
    hostView.hostedGraph = graph;
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)[graph axisSet];    
    
    // xAxis configuration
    CPTXYAxis *xAxis = [axisSet xAxis];
    [xAxis setLabelingPolicy:CPTAxisLabelingPolicyFixedInterval];
    // Prepare dateFormat for current Locale, we want "JAN 2014" "FEB 2014" and so on
    NSString *dateComponents = @"MMMYY";
    NSString *localDateFormat = [NSDateFormatter dateFormatFromTemplate:dateComponents options:0 locale:[NSLocale currentLocale]];
    NSDateFormatter *labelDateFormatter=[[NSDateFormatter alloc] init];
    labelDateFormatter.dateFormat=localDateFormat;    
    // Set xAxis date Formatter
    CPTCalendarFormatter *xDateYearFormatter = [[CPTCalendarFormatter alloc] initWithDateFormatter:labelDateFormatter];
    //Keep in mind this reference date, it will be used to calculate NSNumber in dataSource method
    xDateYearFormatter.referenceDate = [NSDate dateWithTimeIntervalSince1970:0];
    xDateYearFormatter.referenceCalendarUnit=NSMonthCalendarUnit;    
    [xAxis setLabelFormatter:xDateYearFormatter];
    
    // yAxis configuration
    CPTXYAxis *yAxis = [axisSet yAxis];
    [yAxis setMajorIntervalLength:CPTDecimalFromFloat(_YOURYINTERVAL_)];
    [yAxis setLabelingPolicy:CPTAxisLabelingPolicyFixedInterval];
    [yAxis setLabelFormatter:_YOURYFORMATTER_];
    [yAxis setAxisConstraints:[CPTConstraints constraintWithLowerOffset:0.0]]
    
    // Get the (default) plotspace from the graph so we can set its x/y ranges
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
    NSDate *startDate=_YOURSTARTINGDATE_
    //Number of months since the reference date
    NSInteger xStart=[[[NSCalendar currentCalendar] components: NSCalendarUnitMonth
                                     fromDate: xDateYearFormatter.referenceDate
                                       toDate: _YOURSTARTINGDATE_
                                      options: 0] month];    
    [plotSpace setXRange: [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInteger(xStart)     length:CPTDecimalFromInteger(_YOURDATESARRAY_.count-1)]];
    [plotSpace setYRange: [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat(_YOURMAXYVALUE_)]];
    
    [...]
    

    在轴上返回值的数据源方法:

     -(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
    {
        switch (fieldEnum) {
    
            case CPTScatterPlotFieldX: {
    
                NSInteger monthsOffset=[[[NSCalendar currentCalendar] components: NSCalendarUnitMonth  fromDate: [NSDate dateWithTimeIntervalSince1970:0] toDate: [_YOURDATESARRAY_ objectAtIndex:index] options: 0] month];                
                NSNumber *val = [NSNumber numberWithInteger:monthsOffset];    
                return val;
                break;
            }
            case CPTScatterPlotFieldY: {
                NSNumber *val=_YOURVALUEFORYAXIS_;
                return val;
                break;
            }
            default:
                break;
        }
    
        return nil;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-24
      • 2020-11-17
      • 1970-01-01
      • 2020-05-12
      相关资源
      最近更新 更多