objective c - sistema - Core Plot: Cómo presentar popover desde una barra seleccionada por el usuario
sistema operativo ios pdf (1)
El método -plotAreaViewPointForPlotPoint:
devuelve un punto en el sistema de coordenadas del área de trazado. Necesita convertir eso al sistema de coordenadas del gráfico:
[graph convertPoint:dataPoint fromLayer:graph.plotAreaFrame.plotArea];
El gráfico y su vista de alojamiento comparten un sistema de coordenadas. Si self.view
no es la vista de alojamiento, deberá convertir las coordenadas a su sistema de coordenadas desde la vista de alojamiento.
Una muestra de código más completa:
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));
Lo que me gustaría lograr
Estoy usando Core Plot (1.1) para dibujar un gráfico de barras y me gustaría presentar un popover con más detalles debajo de la barra que el usuario ha seleccionado (tocado).
Código
Mi código se ve así:
- (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];
}
Mi problema
La posición y del controlador de vista popover es incorrecta, es diferente para cada barra y para la primera barra, que tiene un valor y negativo, se presenta en el límite superior de la barra en lugar del límite inferior y oculta la barra . La posición x parece ser correcta.
Por favor ayuda
¿Alguna idea sobre por qué mi código no funciona como se esperaba?
¡Gracias!
Editar
Basado en la respuesta de Eric, he actualizado mi código de la siguiente manera:
- (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];
}
Sin embargo, los resultados que recibo son más erróneos que antes. Creo que debo haber malinterpretado algo. Estos son algunos de los resultados de los comandos 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}
Parece que la conversión de las coordenadas de barras a las coordenadas de vista es completamente incorrecta en mi código.
Editar 2
¡Gracias de nuevo por su muestra de código, Eric!
He actualizado mi código y lo he probado con las siguientes opciones (y-value = 0: plotPoint[CPTCoordinateY] = CPTDecimalFromFloat(0.0f)
, que da como resultado un punto de anclaje para el popover cuyo valor de y parece ser incorrecto (consulte a la siguiente captura de pantalla). El valor y del punto de anclaje debe ser equivalente a la posición de 0
en el eje y.
Luego traté de establecer el valor y del punto de anclaje al valor y actual de los datos. ( plotPoint[CPTCoordinateY] = plotYvalue.decimalValue
). Esto da como resultado un punto de anclaje que está cerca del valor 0 del eje y en lugar de estar cerca de la parte superior de la barra. Sin embargo, el valor y cambia un poco para cada compañía (valor x) lo que indica que puede haber un problema con el cambio de los valores y:
También probé la conversión adicional que Eric sugirió dataPoint = [self.view convertPoint:dataPoint fromView:graph.hostingView]
, pero esto no modificó los resultados. Además, traté de agregar - graph.paddingTop + graph.paddingBottom
a los valores y finales, sin éxito.
Agradecería cualquier idea sobre cuál podría ser mi error.
¡Gracias!