核心图:如何在平均值上绘制 Y 轴图?
Core-plot: How to plot a graph with Y Axis on mean value?
我已经设置了一个带有核心图的图表,当存在要显示的新数据时会显示动画。我按照 CorePlot 的示例代码在图表中显示动画的新数据。
情况是这样的:
- 我要显示一个值的趋势(比如速度)
- X轴:我要绘制的速度值
- Y 轴:时间值,我希望该轴始终以图表中当前可用的平均值为中心
- 图表中的每个值都必须可见,所以我必须扩大 x 轴的范围以容纳所有数据。
现在 Y 轴在每个新值处移动。中间没有"anchored"。
这是我对图表的初始设置:
- (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];
...
}
}
在此先感谢您的帮助。
新xRange
的length
应该是delta * 2
把平均值放在中间。
CPTPlotRange *newXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(avgValue-delta)
length:CPTDecimalFromDouble(delta * 2.0)];
我已经设置了一个带有核心图的图表,当存在要显示的新数据时会显示动画。我按照 CorePlot 的示例代码在图表中显示动画的新数据。
情况是这样的:
- 我要显示一个值的趋势(比如速度)
- X轴:我要绘制的速度值
- Y 轴:时间值,我希望该轴始终以图表中当前可用的平均值为中心
- 图表中的每个值都必须可见,所以我必须扩大 x 轴的范围以容纳所有数据。
现在 Y 轴在每个新值处移动。中间没有"anchored"。
这是我对图表的初始设置:
- (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];
...
}
}
在此先感谢您的帮助。
新xRange
的length
应该是delta * 2
把平均值放在中间。
CPTPlotRange *newXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(avgValue-delta)
length:CPTDecimalFromDouble(delta * 2.0)];