核心图:在x轴上显示每日标签的每日标签

时间:2013-02-09 20:40:07

标签: ios objective-c cocoa-touch charts core-plot

对于我的Core Plot图表中的绘图值,我在NSDate - 轴上显示基于x的值。 这些值包含许多年,并且每天都会绘制。

我想在x - 轴上显示每年或每月的标签,但不是每天都显示。这就是为什么我不能使用Core Plot示例应用程序DatePlot中显示的标记方法。

目前我手动创建标签(如下面的代码段所示)。不幸的是,这个解决方案导致了下面屏幕截图中显示的问题(2001年的标签太接近2002年)。

[sortedArray enumerateObjectsUsingBlock:  
   ^(Price *priceItem, NSUInteger idx, BOOL *stop) {

NSDateComponents *yearComponents = 
   [gregorian components:NSYearCalendarUnit 
   fromDate:price.dateTime];
NSDateComponents *monthComponents =
   [gregorian components:NSMonthCalendarUnit 
   fromDate:price.dateTime];       
NSInteger year = [yearComponents year];
NSInteger month = [monthComponents month];
if (month != previousMonth) {
   [minorTickLocations addObject:
   [NSDecimalNumber numberWithUnsignedInteger:idx]];
   previousMonth = month;
}
if (year != previousYear) {
   CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] 
   initWithText: [NSString stringWithFormat:@"%u", year]
   textStyle: axisTitleTextStyle];
   newLabel.tickLocation = CPTDecimalFromUnsignedInteger(idx);
   newLabel.offset = x.labelOffset + x.majorTickLength / 2.0;
   [xAxisLabels addObject:newLabel];
   [majorTickLocations addObject:
       [NSDecimalNumber numberWithUnsignedInteger:idx]];
   previousYear = year;
   }
}];

enter image description here

我想知道是否有更好的方法使用标准Core Plot方法对此进行编码。

如果日期格式化程序行为可用于仅显示年份(YYYY),月份和年份(MMM-YYYY)或仅显示月份(MMM),那就太棒了。

修改

正如Eric在他的帖子中所建议的那样,为了能够使用CPTDateFormatter,我将我的日期转换为年份。这就是我设置图表的方式(最初,我只想在每个日历年绘制一个刻度线):

x.labelingPolicy = CPTAxisLabelingPolicyFixedInterval;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy"];
CPTCalendarFormatter *calendarFormatter = [[CPTCalendarFormatter alloc]
   initWithDateFormatter:dateFormatter];
calendarFormatter.referenceDate = [sortedPrices[0] 
   valueForKey:@"dateTime"];
calendarFormatter.referenceCalendarUnit = NSYearCalendarUnit;
x.labelFormatter = calendarFormatter;

这就是我将基于整数的初始索引转换为基于“年度分数”的索引的方法:

- (NSArray*)indexArrayOfDatesArray:(NSArray*)dates
{
NSCalendar *gregorian = [[NSCalendar alloc] 
   initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *startDate = [sortedCommonSharePrices[0] valueForKey:@"dateTime"];
NSDateComponents *yearComponents = [gregorian components: NSYearCalendarUnit
   fromDate:startDate];
NSUInteger startYear = yearComponents.year;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:dates.count];
[dates enumerateObjectsUsingBlock:^(NSDate *date, NSUInteger idx, BOOL *stop) {
   NSDateComponents *yearComponents = [gregorian 
        components:NSYearCalendarUnit fromDate:date];
   NSInteger years = [yearComponents year];
   NSUInteger numberOfDaysSinceStartOfYear =
        [gregorian ordinalityOfUnit:NSDayCalendarUnit
         inUnit:NSYearCalendarUnit forDate:date];

   NSUInteger totalNumberOfDaysInYear = 365;

   double fractionOfYear = (double)numberOfDaysSinceStartOfYear /
      (double)totalNumberOfDaysInYear + (double)years - (double)startYear;

   [array addObject:[NSNumber numberWithDouble:fractionOfYear]];
}];    
return array;
}

这似乎工作正常,但似乎是很多代码(关于改进代码的任何想法?)。

问题

缩放和平移时(使用plotSpace:willChangePlotRangeTo)我想将x轴标签设置为新的日期范围(基于新绘图范围中的天数。但是,我得到的数字不正确刻度和错误标签(请参阅下面的屏幕截图)。

我如何设置标签参数以使标签正确?

谢谢你的帮助!

plotSpace:willChangePlotRangeTo的代码段:

NSDateComponents *components = [gregorian components:NSDayCalendarUnit 
   fromDate:newStartDate toDate:newEndDate options:0];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
CPTCalendarFormatter *calendarFormatter = 
   [[CPTCalendarFormatter alloc] initWithDateFormatter:dateFormatter];
calendarFormatter.referenceDate = [sortedPrices[0] valueForKey:@"dateTime"];

if (components.day < 365) {
   dateFormatter.dateFormat = @"ddd-MMM-yyyy";
   calendarFormatter.referenceCalendarUnit = NSDayCalendarUnit;
} else if (components.day < 365 * 2) {
   dateFormatter.dateFormat = @"MMM yyyy";
   calendarFormatter.referenceCalendarUnit = NSYearCalendarUnit;
} else if (components.day < 365 * 4) {
   dateFormatter.dateFormat = @"qqq yyyy";
   calendarFormatter.referenceCalendarUnit = NSYearCalendarUnit;
} else {
   dateFormatter.dateFormat = @"yyyy";
   calendarFormatter.referenceCalendarUnit = NSYearCalendarUnit;
}
CPTXYAxis *x = axisSet.xAxis;
x.preferredNumberOfMajorTicks = 10;
x.majorIntervalLength = CPTDecimalFromDouble(0.1);
x.minorTicksPerInterval = 1;
x.labelFormatter = calendarFormatter;

Wrong ticks and labels

2 个答案:

答案 0 :(得分:4)

提供您自己的标签政策,如下所示:

...
CPTXYAxis *x = axisSet.xAxis;
int totalNumberOfYearsToShow = 3;
int startYear = 2010;
int i = 0;
NSMutableSet *xLabels = [NSMutableSet setWithCapacity:totalRecords];
NSMutableSet *xLocations = [NSMutableSet setWithCapacity:totalRecords];

while (i < totalNumberOfYearsToShow)
{
    NSNumber *xData = [NSNumber numberWithInt:(i + startYear)];
    CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[xData stringValue] textStyle:x.labelTextStyle];
    label.tickLocation = CPTDecimalFromInt([xData intValue]);
    label.offset = x.majorTickLength;

    if (label)
    {
        [xLabels addObject:label];
        [xLocations addObject:xData];
    }

    i ++;
}


x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.axisLabels = xLabels;
x.majorTickLocations = xLocations;
...

希望有所帮助。

答案 1 :(得分:1)

  

我无法使用Core Plot示例应用程序DatePlot中显示的标记方法。

为什么不呢?使用固定区间标签政策,只需将majorIntervalLength设置为相当于一年,然后使用CPTCalendarFormatterCPTTimeFormatter格式化标签。