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];
我正在使用 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];