【问题标题】:Core-plot: How to plot a graph with Y Axis on mean value?核心图:如何在平均值上绘制带有 Y 轴的图?
【发布时间】:2015-10-24 13:37:11
【问题描述】:

我已经设置了一个带有核心图的图表,当存在要显示的新数据时会显示动画。我按照 CorePlot 的示例代码在图表中显示新数据的动画。

情况是这样的:

  • 我必须显示一个值的趋势(例如速度)
  • X轴:我要绘制的速度值
  • Y 轴:时间值,我希望轴始终以图表中当前可用的平均值为中心
  • 图表中的每个值都必须可见,因此我必须扩大 x 轴的范围以容纳所有数据。

现在 Y 轴在每个新值处移动。没有被“锚定”在中间。

这是我对图表的初始设置:

- (void)configureHost {

    self.hostViewTop = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height/3, 2*self.view.frame.size.width/5, self.view.frame.size.height/1.5)];
    self.hostViewTop.collapsesLayers = NO;
    [self.hostViewTop setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
    [self.hostViewTop setAutoresizesSubviews:YES];
    self.hostViewTop.allowPinchScaling = NO;
    [self.view addSubview:self.hostViewTop];
}

- (void) configurePlots{

    CPTGraph *graph = self.hostViewTop.hostedGraph;
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;

//    1 - Create the three plots

    ...  

//    2 - Set up plot space

    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(MAX_DATA_ON_CHART)];
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(MAX_VALUE)];

//    4 - Create styles and symbols

    ...
}

- (void)configureAxes {

    // 1 - Create styles

    ...

    // 2 - Get axis set

    CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.hostViewTop.hostedGraph.axisSet;

    // X axis

    CPTXYAxis *x = axisSet.xAxis;
    x.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
    x.orthogonalCoordinateDecimal = CPTDecimalFromUnsignedInteger(0);
    x.minorGridLineStyle = minorGridLineStyle;
    x.majorGridLineStyle = majorGridLineStyle;
    x.minorTickLineStyle = minorTickLineStyle;
    x.majorTickLineStyle = majorTickLineStyle;
    x.minorTicksPerInterval = 9;
    x.axisLineStyle = axisLineStyle;
    x.labelTextStyle = clearTextStyle;
    x.axisConstraints = [CPTConstraints constraintWithUpperOffset:0.0];
    x.coordinate = CPTCoordinateX;
    x.tickDirection = CPTSignNegative;

    NSNumberFormatter *labelFormatter = [[NSNumberFormatter alloc] init];
    labelFormatter.numberStyle = NSNumberFormatterNoStyle;
    x.labelFormatter = labelFormatter;

    // Y axis

    CPTXYAxis *y = axisSet.yAxis;

    y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;

    // Y Axis at the beginning is at MAX_VALUE/2

    y.orthogonalCoordinateDecimal = CPTDecimalFromUnsignedInteger(MAX_VALUE/2);

    y.minorGridLineStyle = minorGridLineStyle;
    y.majorGridLineStyle = majorGridLineStyle;
    y.minorTickLineStyle = minorTickLineStyle;
    y.majorTickLineStyle = majorTickLineStyle;

    y.majorIntervalLength = CPTDecimalFromInt(10);
    y.minorTicksPerInterval = 3;

    y.labelAlignment = CPTAlignmentRight;

    y.axisLineStyle = axisLineStyle;
    y.labelTextStyle = clearTextStyle;
    y.labelFormatter = labelFormatter;
    y.coordinate = CPTCoordinateY;
}

当有新数据可用时:

- (void)newData:(int)data {

    CPTGraph *graphTop = self.hostViewTop.hostedGraph;
    CPTPlot *plotTop = [graphTop plotWithIdentifier:@"ID"];

    if (plotTop) {

        if (dataArray.count > MAX_DATA) {
            NSRange range;
            range.location = 0;
            range.length = dataArray.count-MAX_DATA;
            [dataArray removeObjectsInRange:range];
            [plotTop deleteDataInIndexRange:range];
        }

        CPTXYPlotSpace *plotSpaceTop = (CPTXYPlotSpace *)graphTop.defaultPlotSpace;
        NSUInteger location = (currentIndex > MAX_DATA ? currentIndex - MAX_DATA + 1 : 0);

        CPTPlotRange *newYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(location)
                                                               length:CPTDecimalFromUnsignedInteger(MAX_DATA+MAX_DATA/4)];

        [plotSpaceTop setYRange:newYRange];

        currentIndex++;

        // minValue, maxVlue, avgValue calculated from al data visible in chart

        minValue = ...
        maxValue = ...
        avgValue = ...

        ...

        double delta;

        if (fabs(avgValue-minValue) > fabs(maxValue-avgValue)) {
            delta = fabs(avgValue-minValue);
        } else if (fabs(maxValue-avgValue)) {
            delta = fabs(maxValue-avgValue);
        }

        CPTPlotRange *newXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(avgValue-delta) length:CPTDecimalFromDouble(avgValue+delta)];

        [plotSpaceTop setXRange:newXRange];

        [((CPTXYAxisSet *) graphTop.axisSet).yAxis setOrthogonalCoordinateDecimal:CPTDecimalFromDouble(avgValue)];

        ...

        [plotTop insertDataAtIndex:newData.count - 1 numberOfRecords:1];

        ...
    }
}

提前感谢您的帮助。

【问题讨论】:

  • 除了在平均 x 值处穿过 x 轴之外,您还希望 y 轴在绘图区域居中吗?
  • 正确,并且(为此)我需要扩展 x 轴的范围以按比例保存所有值,从而使 Y 轴位于中心

标签: ios plot core-plot


【解决方案1】:

新的xRangelength 应该是delta * 2 以将平均值放在中间。

CPTPlotRange *newXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(avgValue-delta)
                                                       length:CPTDecimalFromDouble(delta * 2.0)];

【讨论】:

  • 是的,没错,很多 CorePlot 代码,我还没有看到那个细节。现在是正确的。坦克很多;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-12
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
相关资源
最近更新 更多