Coreplot 注释位置不正确 - plotAreaFrame.plotArea.touchedPoint 显示 NAN

Coreplot annotations not in proper location - plotAreaFrame.plotArea.touchedPoint is showing NAN

我正在使用 coreplot 来显示图表。注释未显示在位置点上方。 当我调试 graph.plotAreaFrame.plotArea touchedPoints 时显示 NAN 而不是正确的点。

-(void)configureGraph {
// 1 - Create the graph
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:CGRectMake(0.0, 0.0, 320, 260)];
[graph applyTheme:[CPTTheme themeNamed:kCPTStocksTheme]];

graph.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
graph.plotAreaFrame.fill = [CPTFill fillWithColor:[CPTColor clearColor]];


// 2 - Set graph title
NSString *title = @"Speed";
//graph.title = title;
// 3 - Create and set text style
CPTMutableTextStyle *titleStyle = [CPTMutableTextStyle textStyle];
titleStyle.color = [CPTColor whiteColor];
titleStyle.fontName = @"Helvetica-Bold";
titleStyle.fontSize = 16.0f;
graph.titleTextStyle = titleStyle;
graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
graph.titleDisplacement = CGPointMake(0.0f, 10.0f);
// 4 - Set padding for plot area
[graph.plotAreaFrame setPaddingLeft:35.0f];
[graph.plotAreaFrame setPaddingBottom:25.0f];
[graph.plotAreaFrame setPaddingTop:5.0f];
[graph.plotAreaFrame setPaddingRight:0.0f];

graph.plotAreaFrame.masksToBorder = YES;
//graph.plotAreaFrame.plotArea.delegate = self;


// 5 - Enable user interactions for plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
plotSpace.delegate = self;



// 2 - Create the three plots
CPTScatterPlot *aaplPlot = [[CPTScatterPlot alloc] init];
aaplPlot.dataSource = self;
aaplPlot.delegate = self;
aaplPlot.plotSymbolMarginForHitDetection = 5.0;

aaplPlot.interpolation = CPTScatterPlotInterpolationCurved;
aaplPlot.identifier = @"A";
CPTColor *aaplColor = [CPTColor colorWithComponentRed:127.0f/255.0f green:255.0f/255.0f blue:255.0f/255.0f alpha:1.0f];
[graph addPlot:aaplPlot toPlotSpace:plotSpace];

// 3 - Set up plot space
[plotSpace scaleToFitPlots:[NSArray arrayWithObjects:aaplPlot, nil]];
[plotSpace setYRange: [CPTPlotRange plotRangeWithLocation:[NSNumber numberWithInt:0] length:[NSNumber numberWithInt:maxY+10]]];
[plotSpace setXRange: [CPTPlotRange plotRangeWithLocation:[NSNumber numberWithInt:0] length:[NSNumber numberWithInt:maxX]]];

  // 4 - Create styles and symbols
CPTMutableLineStyle *aaplLineStyle = [aaplPlot.dataLineStyle mutableCopy];
aaplLineStyle.lineWidth = 2.5;
aaplLineStyle.lineColor = aaplColor;
aaplPlot.dataLineStyle = aaplLineStyle;
CPTMutableLineStyle *aaplSymbolLineStyle = [CPTMutableLineStyle lineStyle];
aaplSymbolLineStyle.lineColor = aaplColor;
CPTPlotSymbol *aaplSymbol = [CPTPlotSymbol ellipsePlotSymbol];
aaplSymbol.fill = [CPTFill fillWithColor:aaplColor];
aaplSymbol.lineStyle = aaplSymbolLineStyle;
aaplSymbol.size = CGSizeMake(6.0f, 6.0f);
aaplPlot.plotSymbol = aaplSymbol;


CPTMutableTextStyle *axisTitleStyle = [CPTMutableTextStyle textStyle];
axisTitleStyle.color = [CPTColor whiteColor];
axisTitleStyle.fontName = @"Helvetica-Bold";
axisTitleStyle.fontSize = 12.0f;
CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
axisLineStyle.lineWidth = 2.0f;
axisLineStyle.lineColor = [CPTColor whiteColor];
CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init];
axisTextStyle.color = [CPTColor whiteColor];
axisTextStyle.fontName = @"Helvetica-Bold";
axisTextStyle.fontSize = 11.0f;
CPTMutableLineStyle *tickLineStyle = [CPTMutableLineStyle lineStyle];
tickLineStyle.lineColor = [CPTColor whiteColor];
tickLineStyle.lineWidth = 2.0f;
CPTMutableLineStyle *gridLineStyle = [CPTMutableLineStyle lineStyle];
tickLineStyle.lineColor = [CPTColor blackColor];
tickLineStyle.lineWidth = 1.0f;
// 2 - Get axis set
CPTXYAxisSet *axisSet = (CPTXYAxisSet *) graph.axisSet;
// 3 - Configure x-axis
CPTAxis *x = axisSet.xAxis;
x.title = @"Distance --> (Points are 200 meter apart)";
x.titleTextStyle = axisTitleStyle;
x.titleOffset = 8.0f;
x.labelOffset = 0.0f;


x.axisLineStyle = axisLineStyle;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.preferredNumberOfMajorTicks = 4;
x.labelTextStyle = axisTextStyle;
x.majorTickLineStyle = axisLineStyle;
x.majorTickLength = 0.0f;
x.minorTickLength = 0.0f;

x.tickDirection = CPTSignNegative;
CGFloat dateCount = [self.arrayOfDates count];
NSMutableSet *xLabels = [NSMutableSet setWithCapacity:dateCount];
NSMutableSet *xLocations = [NSMutableSet setWithCapacity:dateCount];
float i = 0.0;
for (int index = 0 ; index < [self.arrayOfDates count]; index++) {

    float distanceX = (float)([[[self.arrayOfDates objectAtIndex:index] objectForKey:@"Distance"] floatValue]);
    NSString *labelDist = [NSString stringWithFormat:@"%.2f", distanceX];
    CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:labelDist  textStyle:x.labelTextStyle];
    CGFloat location = i++;
    label.tickLocation = [NSNumber numberWithFloat:i];
    label.offset = x.majorTickLength;
    if (label) {
        [xLabels addObject:label];
        [xLocations addObject:[NSNumber numberWithFloat:location]];
    }

}
//x.axisLabels = xLabels;
//x.majorTickLocations = xLocations;
// 4 - Configure y-axis
CPTAxis *y = axisSet.yAxis;
y.title = @"Traffic Density";
y.titleTextStyle = axisTitleStyle;
y.titleOffset = 18.0f;
y.axisLineStyle = axisLineStyle;
//y.majorGridLineStyle = gridLineStyle;
y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.preferredNumberOfMajorTicks = 4;

y.labelTextStyle = axisTextStyle;
y.labelOffset = 0.0f;
y.majorTickLineStyle = axisLineStyle;
y.majorTickLength = 0.0f;
y.minorTickLength = 0.0f;
y.tickDirection = CPTSignNegative;
int majorIncrement = ceil(maxY/4);
NSInteger minorIncrement = maxY/8;
CGFloat yMax = maxY;  // should determine dynamically based on max price
NSMutableSet *yLabels = [NSMutableSet set];
NSMutableSet *yMajorLocations = [NSMutableSet set];
NSMutableSet *yMinorLocations = [NSMutableSet set];


for (NSInteger j = 0; j <= yMax + majorIncrement; j++) {
    NSUInteger mod = j % majorIncrement;
    if (mod == 0) {
        CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:@"%i", j] textStyle:y.labelTextStyle];
        NSDecimal location = CPTDecimalFromInteger(j);
        label.tickLocation = [NSNumber numberWithInt:j];
        label.offset = -y.majorTickLength - y.labelOffset;
        if (label) {
            [yLabels addObject:label];
        }
        [yMajorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:location]];
    }
}


    y.axisLabels = yLabels;
y.majorTickLocations = yMajorLocations;

// Create a plot that uses the data source method

axisSet.xAxis.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
axisSet.xAxis.orthogonalPosition = [NSNumber numberWithInt:0];

axisSet.yAxis.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];

self.hostView.collapsesLayers = NO;
self.hostView.hostedGraph = graph;}

这是coreplot标注的显示方式

-(void)scatterPlot:(nonnull CPTScatterPlot *)plot     plotSymbolWasSelectedAtRecordIndex:(NSUInteger)index
{
CPTGraph *graph = self.hostView.hostedGraph;

CPTPlotSpaceAnnotation *annotation = self.symbolTextAnnotation;

if ( annotation ) {
    [graph.plotAreaFrame.plotArea removeAnnotation:annotation];
    self.symbolTextAnnotation = nil;
}

// Setup a style for the annotation
CPTMutableTextStyle *hitAnnotationTextStyle = [CPTMutableTextStyle textStyle];
hitAnnotationTextStyle.color    = [CPTColor whiteColor];
hitAnnotationTextStyle.fontName = @"Helvetica-Bold";
hitAnnotationTextStyle.fontSize = 16.0;

// Determine point of symbol in plot coordinates

NSNumber *x =  [NSNumber numberWithFloat:[[[self.arrayOfDates objectAtIndex:index] objectForKey:@"Distance"] floatValue]] ;
NSNumber *y = [NSNumber numberWithFloat:[[[self.arrayOfValues objectAtIndex:index] objectForKey:@"Speed"] floatValue]];
CPTNumberArray *anchorPoint = @[x, y];

// Add annotation
// First make a string for the y value
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.maximumFractionDigits = 2;
NSString *yString = [formatter stringFromNumber:y];



CPTPlotSpace *defaultSpace = graph.defaultPlotSpace;
if ( defaultSpace ) {
    CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:yString style:hitAnnotationTextStyle];
    annotation                    = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:defaultSpace anchorPlotPoint:anchorPoint];
    annotation.contentLayer       = textLayer;
    annotation.displacement       = CGPointMake(0.0, 10.0);

    [graph.plotAreaFrame.plotArea addAnnotation:annotation];
}
}

请检查屏幕截图,这些点与图表中的点不对齐。

数据源方法

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSInteger valueCount = [self.arrayOfDates count];
switch (fieldEnum) {
    case CPTScatterPlotFieldX:
        if (index < valueCount) {
            distanceX += [[[self.arrayOfDates objectAtIndex:index] objectForKey:@"Distance"] floatValue];
            NSLog(@"Distance = %f",distanceX);
            return [NSNumber numberWithFloat:distanceX];
        }
        break;

    case CPTScatterPlotFieldY:{
        float distance = [[[self.arrayOfValues objectAtIndex:index] objectForKey:@"Speed"] floatValue];
        return [NSNumber numberWithFloat:distance];

        break;
    }
}
return [NSDecimalNumber zero];}

当我点到点的时候,plotAreaFrame.plotArea.touchedPoint是NAN。请参考这个截图

问题没有显示数据源方法,但根据 x 轴标签的设置方式,看起来 x 值被绘制为数据索引。定位注释时尝试使用以下锚点计算:

NSNumber *y = [[self.arrayOfValues objectAtIndex:index] objectForKey:@"Speed"];
CPTNumberArray *anchorPoint = @[@(index), y];