Draw area formatting in column chart


#1

Hi, I’m just getting started and have a basic question.  I’m following the Column Chart sample.  However when I create my chart, the first and last column appear at the edge of the draw area on the Y axis , resulting in a clipped appearance.

Example image

I’m sure there is a setting to adjust this, but I didn’t see an obvious match.  Here’s the code I’m using to instantiate the chart object.

BOOL iPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
    
    if (chart == nil){
        CGRect frame = self.view.bounds;
        
        if (iPad) {
            frame.origin.x += 10;
            frame.origin.y += 50;
            frame.size.width -= 50;
            frame.size.height -= 100;
        } else {
            frame.size.width -= 10;
        }
        
        chart = [[ShinobiChart alloc] initWithFrame:frame];

        chart.clipsToBounds = NO;
        chart.autoresizingMask = ~UIViewAutoresizingNone;
    }
    chart.title = viewItem.report.displayName;
    
// // Use a number axis for the x axis.
// SChartNumberAxis *xAxis = [[SChartNumberAxis alloc] init];
// xAxis.title = viewItem.report.xAxisLabel;
// chart.xAxis = xAxis;
        
    CTMetricsCapacityItem *first = [results objectAtIndex:0];
    CTMetricsCapacityItem *last = [results lastObject];
    SChartDateRange *range = [[SChartDateRange alloc] initWithDateMinimum:first.date andDateMaximum:last.date];
    
    SChartDateTimeAxis *dateAxis = [[SChartDateTimeAxis alloc] initWithRange:range];
        
    chart.xAxis = dateAxis;
               
    // Use a number axis for the y axis.
    SChartNumberAxis *yAxis = [[SChartNumberAxis alloc] init];
    yAxis.title = viewItem.report.yAxisLabel;
    chart.yAxis = yAxis;
    
    if (iPad) {
        chart.legend.hidden = NO;
        chart.legend.position = SChartLegendPositionBottomMiddle;
        chart.legend.placement = SChartLegendPlacementOutsidePlotArea;
    }
    
    chart.datasource = self;
    
    [self.view addSubview:chart];
    self.view.backgroundColor = chart.theme.chartStyle.backgroundColor;

#2

Hi Chris,

Try having a play with the  rangePaddingLow and rangePaddingHigh properties on your X-axis. These can be used to add padding to either the low end or the high end of your axis. The documentation for the SChartAxis (the parent class of all axis types) can be found here:

http://www.shinobicontrols.com/docs/ShinobiControls/ShinobiCharts/2.2.0/Standard/Normal/Classes/SChartAxis.html

Jan


#3

I just wanted to add, since you are using a date/time axis, you will want to be setting your padding high/low properties to a SChartDateFrequency object. The documentation for this object can be found here:

http://www.shinobicontrols.com/docs/ShinobiControls/ShinobiCharts/2.2.0/Premium/Normal/Classes/SChartDateFrequency.html

Essentially, it is a way of expressing a date duration, rather than using a NSDate which represents a fixed moment in time. If you wanted to set a single days padding you would do the following:

// Set the lower padding on the date/time axis 'myAxis' to a day.
myAxis.ragePaddingLow = [SChartDateFrequency dateFrequencyWithDay:1];

Hope the above helped!


#4

Thanks Jan, but I don’t see that the rangePaddingLow or rangePaddingHigh properties have any effect on a SChartDateTimeAxis.  I tried applying these props on a Y axis that was of type SChartNumberAxis and it worked as expected.

I’ve created a very simple demonstration project so you can see the issue as well.  In addition, I’ve tried creating an NSTimeInterval of 1 day and setting the rangePadding properties to that, but it didn’t work either.

Here’s the chart that you’ll see from the code below.  As before, I’m trying to move the initial column off of the Y axis, and move the last column in so that it will display it’s label.

Column Chart

@implementation CTViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    chart = [[ShinobiChart alloc] initWithFrame:self.view.bounds];
    chart.title = @"Column Date Chart";
    chart.autoresizingMask = ~UIViewAutoresizingNone;
    
    NSDate *now = [NSDate date];
    
    SChartDateRange *range = [[SChartDateRange alloc] initWithDateMinimum:[now dateByAddingTimeInterval:60*60*24*-9] andDateMaximum:now];
    
    SChartDateTimeAxis *xAxis = [[SChartDateTimeAxis alloc] initWithRange:range];
    NSDateFormatter *dayFormatter = [[NSDateFormatter alloc] init];
    [dayFormatter setDateFormat:@"MMMM d"];
    SChartTickLabelFormatter *formatter = [SChartTickLabelFormatter dateFormatter];
    [formatter setFormatter:dayFormatter];
    xAxis.labelFormatter = formatter;
    
    xAxis.rangePaddingLow = [SChartDateFrequency dateFrequencyWithDay:1];
    xAxis.rangePaddingHigh = [SChartDateFrequency dateFrequencyWithDay:1];
    
    chart.xAxis = xAxis;
    
    SChartNumberAxis *yAxis = [[SChartNumberAxis alloc] init];
    yAxis.majorTickFrequency = [NSNumber numberWithInt:1];
    SChartRange *yRange = [[SChartRange alloc] initWithMinimum:[NSNumber numberWithInt:0] andMaximum:[NSNumber numberWithInt:11]];
    yAxis.defaultRange = yRange;
    
    chart.yAxis = yAxis;
    
    chart.datasource = self;
    
    [self.view addSubview:chart];
}

- (int)numberOfSeriesInSChart:(ShinobiChart *)chart {
    return 1;
}

-(SChartSeries *)sChart:(ShinobiChart *)chart seriesAtIndex:(int)index {
    
    SChartColumnSeries *columnSeries = [[SChartColumnSeries alloc] init];
    columnSeries.title = @"Values";
    return columnSeries;
}

- (int)sChart:(ShinobiChart *)chart numberOfDataPointsForSeriesAtIndex:(int)seriesIndex {
    return 10;
}

- (id<SChartData>)sChart:(ShinobiChart *)chart dataPointAtIndex:(int)dataIndex forSeriesAtIndex:(int)seriesIndex
{
    SChartDataPoint *datapoint = [SChartDataPoint new];
    
    NSDate *now = [NSDate date];

    datapoint.xValue = [now dateByAddingTimeInterval:60*60*24*-1*dataIndex];
    datapoint.yValue = [NSNumber numberWithInt:dataIndex + 1];
    
    return datapoint;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

@end

#5

Hi Chris,

The reason the padding properties aren’t having any effect is because you are explicitly setting the range of your axis. The padding properties are only taken into account when the axis is being auto-calculated. Try initialising your X-axis without specifying a range, like so:

SChartDateTimeAxis *xAxis = [[SChartDateTimeAxis alloc] init];

Also, thanks for attaching something that demonstrates the problem you are having - I can’t explain how much easier this makes investigating the problem!  :laughing:


#6

Thanks Jan, appreciate your response.  This solved the problem, and as a happy by-product, I don’t even need to use the rangePaddingLow and rangePaddingHigh properties to make a decent looking chart.

I guess I was confused because whenever I find that an object has a custom initializer (in this case initWithRange) I typically assume that this is the preferred initializer that the API designer expected us to use.  Thanks for clearing up my misconception.


#7

No worries Chris. I am glad you managed to get everything working!