核心绘图:如何从用户选择的柱形图中呈现弹出窗口

3

我想要实现的目标

我正在使用Core Plot (1.1)来绘制柱状图,我希望在用户选择(点击)的柱子下方显示一个弹出窗口,其中包含更多详细信息。

代码

我的代码如下:

- (void)barPlot:(CPTBarPlot *)plot barWasSelectedAtRecordIndex:(NSUInteger)idx {

    NSNumber *yValue = self.values[idx];
    NSLog(@"barWasSelectedAtRecordIndex x: %i, y: %@",idx,yValue);

    NSDecimal plotPoint[2];
    NSNumber *plotXvalue = [self numberForPlot:plot
                                         field:CPTScatterPlotFieldX
                                   recordIndex:idx];
    plotPoint[CPTCoordinateX] =
        CPTDecimalFromFloat(plotXvalue.floatValue);

    NSNumber *plotYvalue = [self numberForPlot:plot
                                         field:CPTScatterPlotFieldY
                                   recordIndex:idx];

    plotPoint[CPTCoordinateY] =
        CPTDecimalFromFloat(plotYvalue.floatValue); 

    CPTXYPlotSpace *plotSpace =
        (CPTXYPlotSpace *)graph.defaultPlotSpace;
    CGPoint dataPoint =
        [plotSpace plotAreaViewPointForPlotPoint:plotPoint];
    NSLog(@"datapoint (CGPoint) coordinates tapped: %@",
          NSStringFromCGPoint(dataPoint));

    GrowthChartInfoTableViewController *infoViewController =
        [self.storyboard instantiateViewControllerWithIdentifier:
         @"GrowthChartInfo"];

    self.popover = [[UIPopoverController alloc]
                    initWithContentViewController:infoViewController];
    self.popover.popoverContentSize = CGSizeMake(320, 300);
    self.popover.delegate = self;
    CGRect popoverAnchor =
            CGRectMake(dataPoint.x + graph.paddingLeft,
                       dataPoint.y - graph.paddingTop + graph.paddingBottom,
                       (CGFloat)1.0f, (CGFloat)1.0f);

    [self.popover presentPopoverFromRect:popoverAnchor
                                  inView:self.view
                permittedArrowDirections:UIPopoverArrowDirectionAny
                                animated:YES];
}

我的问题

弹出视图控制器的纵向位置不正确,每个工具栏都不同,对于第一个工具栏,其y值为负数,它被放置在工具栏的上限而非下限,并且遮盖了工具栏。横向位置似乎是正确的。

enter image description here

请帮忙解决

是否有任何想法可以解决我的代码无法按预期工作的问题?

谢谢!

编辑

根据Eric的答案,我已经更新了我的代码:

- (void)barPlot:(CPTBarPlot *)plot barWasSelectedAtRecordIndex:(NSUInteger)idx {

    NSNumber *plotXvalue = [self numberForPlot:plot
                                         field:CPTScatterPlotFieldX
                                   recordIndex:idx];
    NSNumber *plotYvalue = [self numberForPlot:plot
                                         field:CPTScatterPlotFieldY
                                   recordIndex:idx];

    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;

    CGPoint cgPlotPoint =
        CGPointMake(plotXvalue.floatValue,
                    plotYvalue.floatValue);
    CGPoint cgPlotAreaPoint =
        [graph convertPoint:cgPlotPoint toLayer:graph.plotAreaFrame.plotArea];

    NSDecimal plotAreaPoint[2];
    plotAreaPoint[CPTCoordinateX] =
        CPTDecimalFromFloat(cgPlotAreaPoint.x);
    plotAreaPoint[CPTCoordinateY] =
        CPTDecimalFromFloat(cgPlotAreaPoint.y);

    CGPoint dataPoint = [plotSpace


           plotAreaViewPointForPlotPoint:plotAreaPoint];
        NSLog(@"datapoint (CGPoint) coordinates tapped: %@",NSStringFromCGPoint(dataPoint));

GrowthChartInfoTableViewController *infoViewController = [self.storyboard 
   instantiateViewControllerWithIdentifier:@"GrowthChartInfo"];



    self.popover = nil;
        self.popover = [[UIPopoverController alloc]


      initWithContentViewController:infoViewController];
    self.popover.popoverContentSize = CGSizeMake(250, 200);
    self.popover.delegate = self;
    CGRect popoverAnchor =
        CGRectMake(dataPoint.x + graph.paddingLeft,
                   dataPoint.y - graph.paddingTop + graph.paddingBottom,
                   (CGFloat)1.0f, (CGFloat)1.0f);

    [self.popover presentPopoverFromRect:popoverAnchor
        inView:self.view
        permittedArrowDirections:UIPopoverArrowDirectionUp
        animated:YES];
}

然而,我得到的结果比以前更加错误。我相信我一定理解错了什么。以下是NSLog命令的一些结果:

barWasSelectedAtRecordIndex x: 0, y: -0.03920931548773198848
datapoint (CGPoint) coordinates tapped: {-6388.88, -67024.8}

barWasSelectedAtRecordIndex x: 2, y: 0.174494288286651392
datapoint (CGPoint) coordinates tapped: {-6073.38, -66790}

barWasSelectedAtRecordIndex x: 2, y: 0.174494288286651392
datapoint (CGPoint) coordinates tapped: {-6073.38, -66790}

barWasSelectedAtRecordIndex x: 0, y: -0.03920931548773198848
datapoint (CGPoint) coordinates tapped: {-6388.88, -67024.8}

我的代码中从bar坐标转换为视图坐标的转换似乎完全错误。

编辑2

再次感谢您提供的代码示例,Eric!

我已经更新了代码,并尝试了以下选项(y值= 0:plotPoint [CPTCoordinateY] = CPTDecimalFromFloat(0.0f)),这会导致popover的锚点的y值似乎不正确(请参见以下屏幕截图)。 锚点的y值应该等于y轴上0的位置。

enter image description here

然后,我尝试将锚点的y值设置为数据的当前y值。 (plotPoint [CPTCoordinateY] = plotYvalue.decimalValue)。这会导致一个接近y轴0值而不是接近柱形顶部的锚点。但是,每个公司(x值)的y值都会略微变化,表明可能存在y值偏移问题:

enter image description here

我还尝试了Eric建议的附加转换 dataPoint = [self.view convertPoint:dataPoint fromView:graph.hostingView],但这并没有改变结果。此外,我尝试将- graph.paddingTop + graph.paddingBottom添加到最终y值中,但没有成功。

如果您有任何关于错误可能在哪里的想法,我将不胜感激。

谢谢!


Bar不是UIComponent。它只是一种绘图。因此,您需要为每个bar创建一个CGRect点,并将其存储在数组中,并且您需要在touchesBegan:方法中检查用户是否触摸了数组中的任何矩形。我也可能错了。但这只是一个想法。 - Dinesh Raja
我正在使用 - barPlot:barWasSelectedAtRecordIndex: 来获取所选柱形图的索引和其 y 值。 - AlexR
1个回答

8
< p > -plotAreaViewPointForPlotPoint: 方法返回图表区域坐标系中的一个点。您需要将其转换为图形的坐标系:

-plotAreaViewPointForPlotPoint:方法返回的是在绘图区域的坐标系中的一个点,需要将其转换为图形的坐标系。
[graph convertPoint:dataPoint fromLayer:graph.plotAreaFrame.plotArea];

图形及其托管视图共享一个坐标系。如果self.view不是托管视图,则需要将坐标从托管视图的坐标系转换为其坐标系。
下面是一个更完整的代码示例:
NSDecimal plotPoint[2];
NSNumber *plotXvalue = [self numberForPlot:plot
                                     field:CPTScatterPlotFieldX
                               recordIndex:idx];
plotPoint[CPTCoordinateX] = plotXvalue.decimalValue;

NSNumber *plotYvalue = [self numberForPlot:plot
                                     field:CPTScatterPlotFieldY
                               recordIndex:idx];
plotPoint[CPTCoordinateY] = plotYvalue.decimalValue; 

CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;

// convert from data coordinates to plot area coordinates
CGPoint dataPoint = [plotSpace plotAreaViewPointForPlotPoint:plotPoint];

// convert from plot area coordinates to graph (and hosting view) coordinates
dataPoint = [graph convertPoint:dataPoint fromLayer:graph.plotAreaFrame.plotArea];

// convert from hosting view coordinates to self.view coordinates (if needed)
dataPoint = [self.view convertPoint:dataPoint fromView:hostingView];

NSLog(@"barWasSelectedAtRecordIndex x: %@, y: %@", plotXvalue, plotYvalue);
NSLog(@"datapoint coordinates tapped: %@", NSStringFromCGPoint(dataPoint));

我是否需要先使用-plotAreaViewPointForPlotPoint:将点转换,然后再使用[graph convertPoint:dataPoint fromLayer:graph.plotAreaFrame.plotArea]进行第二次转换?当我链接这两种方法时,x值的结果是错误的。但是,当我不使用[graph convertPoint:dataPoint fromLayer:graph.plotAreaFrame.plotArea]时,我得到了正确的x值。这是为什么呢? - AlexR
需要进行-plotAreaViewPointForPlotPoint:转换。它接受数据坐标(柱形位置和顶部)的值,并将它们转换为绘图区域中的视图坐标。 - Eric Skroch
Eric,感谢您的代码示例,我已经进行了大量测试。然而,我仍然遇到了y坐标的问题:似乎存在y值偏移的问题。当我将y值设置为0时,锚点会固定在条形图的顶部。对于更改的y值(例如0.15和0.17),锚点也会发生变化,但仍保持接近y轴的0值。您对我的代码有何想法?谢谢! - AlexR
Core Plot在iOS上对托管视图应用了翻转变换。您的弹出窗口锚点的y坐标位于翻转坐标系统中。您还缺少另一个坐标空间转换。 - Eric Skroch
是的,看起来翻转坐标系统导致了这个问题。然而,我完全不知道我应该在哪里需要额外的空间转换(以及如何添加它)。不幸的是,这个坐标空间转换话题对我来说完全是新的。您能否给我一些提示,告诉我如何解决这个问题或者我应该在哪里寻找错误?非常感谢! - AlexR
不知道所有视图都是什么以及视图层次结构如何排列,很难提出更多建议。 - Eric Skroch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接