Frage

I want to know if it is possible to have custom spacing between bars after some fixed interval using Coreplot iOS library.
Like in the image below, after each 7 bars an unusual barspace is shown.
And if it is possible can you please guide how can this be achieved ?

Problem Visual

War es hilfreich?

Lösung

CPTBarPlot has the code to manage this.

-(BOOL)barAtRecordIndex:(NSUInteger)idx basePoint:(CGPoint *)basePoint tipPoint:(CGPoint *)tipPoint

Basically gets the bar and sets its basePoint and tipPoint.

At the end, it is using barOffsetLength to offset each bar based on its index.

CGFloat barOffsetLength = [self lengthInView:self.barOffset] * self.barOffsetScale;

For vertical bars, in your case, its offsetting the x coord of base and tip point. These are usually the same. Here you have the choice of adding your own offset.

Simply, here's what you need to do there in the same function:

CGFloat barOffsetLength = [self lengthInView:self.barOffset] * self.barOffsetScale;
if ([self.dataSource hasGapBeforeIndex:idx]) {
    offsetGap += [self.dataSource gapValue];
}

// Offset
if ( horizontalBars ) {
    basePoint->y += barOffsetLength;
    tipPoint->y  += barOffsetLength;
}
else {
    //HERO

    basePoint->x += barOffsetLength + offsetGap;
    tipPoint->x += barOffsetLength + offsetGap;
}

Here, you introduce a new variable in CPTBarPlot called offsetGap which gets increments everytime you introduce a gap. (be careful, this needs to be reset to zero when you change the dataset).

Also, in CPTPlotDataSource introduce

- (BOOL) hasGapBeforeIndex:(NSUInteger)index;
- (CGFloat) gapValue;

and implement it in your View Controller. Now you can introduce the gap anywhere.

PS: This obviously is a hack and upsets the axis labels and other things that might also need adjustment, but gives an overview anyway.

I played around with the sample app to achieve this.

Andere Tipps

You need to modify the positioning in your Core Plot data source method for the x axis

- (NSNumber *) numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)idx

and take into account where you want the spacing to occur. If you still don't get it, please post some code and I'll show you on that.

Logic example :

I want to represent the data for a month, lets say one that has 30 days, but at each 5 days, I want a pause at each 5 days. So instead of returning 30 in

- (NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot

, you return 34, and at indexes 6, 11, 16, 21 and 26 you return 0 for the method above.

You can extend this if you want not that much space for the 'pauses' and return double the amount of days (60), minus 4 (because for the pauses you return only for one record the value 0) and return for each 2 records the corresponding value in your data source. This can be again extended to your needed multiplier. I hope you got what I mean.

Thanks to @zakishaheen answer I managed to achieve this, but I broke label position and scroll content size 😄. This implementation is hacky thats why I decided not to continue with fixing it, its more just an example.

I created custom CustomOffsetBarPlot class and apply some Objective-C runtime magic.

- (BOOL)superImplementation:(SEL)selector idx:(NSUInteger)idx basePoint:(nonnull CGPoint *)basePoint tipPoint:(nonnull CGPoint *)tipPoint {
    Class granny = [self superclass];
    BOOL(* grannyImp)(id,SEL,NSUInteger,CGPoint*, CGPoint*) = (BOOL (*)(id,SEL,NSUInteger,CGPoint*, CGPoint*))class_getMethodImplementation(granny, selector);
    return grannyImp(self, selector, idx, basePoint, tipPoint);
}

-(BOOL)barAtRecordIndex:(NSUInteger)idx basePoint:(nonnull CGPoint *)basePoint tipPoint:(nonnull CGPoint *)tipPoint {
    SEL selector = _cmd;

    CGPoint originBasePointStart = *basePoint;
    CGPoint originTipPointStart = *tipPoint;
    [self superImplementation:selector idx:0 basePoint:&originBasePointStart tipPoint:&originTipPointStart];

    BOOL result = [self superImplementation:selector idx:idx basePoint:basePoint tipPoint:tipPoint];

    Class granny = [self class];
    SEL lengthView = NSSelectorFromString(@"lengthInView:");
    CGFloat(* grannyImp)(id,SEL,NSDecimal) = (CGFloat (*)(id,SEL,NSDecimal))class_getMethodImplementation(granny, lengthView);

    CGFloat barOffsetLengthOrigin = grannyImp(self, selector, self.barOffset.decimalValue);

    NSInteger barOffsetLength = originBasePointStart.x + idx * 18 + idx * 5; // idx * 5 - your offset
    basePoint->x = barOffsetLength;
    tipPoint->x = barOffsetLength;

    return result;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top