2011-02-08 70 views
3

我想在iphone上使用coreplot繪製一個XY圖,其中x軸上的日期和y軸上的一些值。參考使用coreplot SDK發佈的DatePlot示例,我能夠以月爲單位在x軸上繪製日期圖形(即x從月份的1日期到最後日期)。現在我想要一個年度量表,即我想在x軸上顯示所有月份名稱(1月,2月,3月等),並將我的剔號間隔顯示爲一個月的時間。在x軸上的月份的核心圖(iphone)

我用下面的代碼顯示值月度規模現在

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剔inteval需要爲一個月。我試了下面的代碼,但沒有工作

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軸上顯示,但它顯示爲

一月,三月,四月,五月,五月,六月,七月,八月,九月,十月,十一月,十二月。

您可以看到沒有Feb,並且有5個條目。我的滴答時間間隔如何與每個月的天數相關聯。任何解決方案 感謝和問候,

回答

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]; 
+0

我有一個問題,因爲我用CPTAxisLabelingPolicyAutomatic,當我放大縮小,x軸已被重新繪製成1到10。 – nullmicgo 2012-02-13 03:39:33

1

剛剛在相關問題中回答。使用CPTCalendarFormatter而不是CPTTimeFormatter,當您必須設置以秒爲單位的時間間隔偏移(例如小時= 60 * 60,日= 24 * 60 * 60)時很好,但幾個月的可變天數/秒(30 * 24 * 60 * 60或31 * 24 * 60 * 60,28,閏年等)。 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; 
}