我正在开发一个带有核心图表的iPhone应用程序。在一些教程的帮助下,我设法通过单点触摸和拖动来完成。如何通过多次触摸和拖动来实现?有人请帮帮我吗?
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
EskPlotTheme *defaultTheme = [[EskPlotTheme alloc] init];
linePlot = [[EskLinePlot alloc] init];
linePlot.delegate = self;
[linePlot renderInLayer:lineHostingView withTheme:defaultTheme];
[defaultTheme release];
}
EskLinePlot.m
- (id)init
{
self = [super init];
if (self)
{
// setting up the sample data here.
sampleData = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:6000],
[NSNumber numberWithInt:3000],
[NSNumber numberWithInt:2000],
[NSNumber numberWithInt:5000],
[NSNumber numberWithInt:7000],
[NSNumber numberWithInt:8500],
[NSNumber numberWithInt:6500], nil];
}
return self;
}
- (void)renderInLayer:(CPTGraphHostingView *)layerHostingView withTheme:(CPTTheme *)theme
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CGRect bounds = layerHostingView.bounds;
// Create the graph and assign the hosting view.
graph = [[CPTXYGraph alloc] initWithFrame:bounds];
layerHostingView.hostedGraph = graph;
[graph applyTheme:theme];
graph.plotAreaFrame.masksToBorder = NO;
// chang the chart layer orders so the axis line is on top of the bar in the chart.
NSArray *chartLayers = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:CPTGraphLayerTypePlots],
[NSNumber numberWithInt:CPTGraphLayerTypeMajorGridLines],
[NSNumber numberWithInt:CPTGraphLayerTypeMinorGridLines],
[NSNumber numberWithInt:CPTGraphLayerTypeAxisLines],
[NSNumber numberWithInt:CPTGraphLayerTypeAxisLabels],
[NSNumber numberWithInt:CPTGraphLayerTypeAxisTitles],
nil];
graph.topDownLayerOrder = chartLayers;
[chartLayers release];
// Add plot space for horizontal charts
graph.paddingLeft = 60.0;
graph.paddingTop = 70.0;
graph.paddingRight = 20.0;
graph.paddingBottom = 20.0;
// Setup plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
plotSpace.delegate = self;
int sampleCount = [sampleData count]-1;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat(sampleCount)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat(10000)];
// Setup grid line style
CPTMutableLineStyle *majorXGridLineStyle = [CPTMutableLineStyle lineStyle];
majorXGridLineStyle.lineWidth = 1.0f;
majorXGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.25f];
CPTMutableTextStyle *whiteTextStyle = [[[CPTMutableTextStyle alloc] init] autorelease];
whiteTextStyle.color = [CPTColor whiteColor];
// Setup x-Axis.
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
x.majorGridLineStyle = majorXGridLineStyle;
x.labelTextStyle = whiteTextStyle;
x.majorIntervalLength = CPTDecimalFromString(@"1");
x.minorTicksPerInterval = 1;
NSArray *exclusionRanges = [NSArray arrayWithObjects:[CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(0) length:CPTDecimalFromInt(0)], nil];
x.labelExclusionRanges = exclusionRanges;
// Setup y-Axis.
CPTMutableLineStyle *majorYGridLineStyle = [CPTMutableLineStyle lineStyle];
majorYGridLineStyle.lineWidth = 1.0f;
majorYGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.25];
CPTMutableLineStyle *minorYGridLineStyle = [CPTMutableLineStyle lineStyle];
minorYGridLineStyle.lineWidth = 1.0f;
minorYGridLineStyle.lineColor = [[CPTColor blackColor] colorWithAlphaComponent:0.1];
CPTXYAxis *y = axisSet.yAxis;
y.majorGridLineStyle = majorYGridLineStyle;
y.minorGridLineStyle = minorYGridLineStyle;
y.labelTextStyle = whiteTextStyle;
y.majorIntervalLength = CPTDecimalFromString(@"1000");
y.minorTicksPerInterval = 1;
y.orthogonalCoordinateDecimal = CPTDecimalFromString(@"0");
NSArray *yExlusionRanges = [NSArray arrayWithObjects:
[CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat(0.0)],
nil];
y.labelExclusionRanges = yExlusionRanges;
// Create a high plot area
CPTScatterPlot *highPlot = [[[CPTScatterPlot alloc] init] autorelease];
highPlot.identifier = kHighPlot;
CPTMutableLineStyle *highLineStyle = [[highPlot.dataLineStyle mutableCopy] autorelease];
highLineStyle.lineWidth = 2.f;
highLineStyle.miterLimit = 1.0f;
highLineStyle.lineColor = [CPTColor whiteColor];
highPlot.dataLineStyle = highLineStyle;
highPlot.dataSource = self;
CPTColor *areaColor1 = [[CPTColor whiteColor] colorWithAlphaComponent:0.8f];
CPTGradient *areaGradient1 = [CPTGradient gradientWithBeginningColor:areaColor1 endingColor:[[CPTColor whiteColor] colorWithAlphaComponent:0.2f]];
areaGradient1.angle = -90.0f;
CPTFill *areaGradientFill = [CPTFill fillWithGradient:areaGradient1];
highPlot.areaFill = areaGradientFill;
highPlot.areaBaseValue = [[NSDecimalNumber zero] decimalValue];
[graph addPlot:highPlot];
// Create the Savings Marker Plot
selectedCoordination = 2;
touchPlot = [[[CPTScatterPlot alloc] initWithFrame:CGRectNull] autorelease];
touchPlot.identifier = kLinePlot;
touchPlot.dataSource = self;
touchPlot.delegate = self;
[self hideTouchPlotColor];
[graph addPlot:touchPlot];
[pool drain];
}
- (void)hideTouchPlotColor
{
CPTColor *touchPlotColor = [CPTColor clearColor];
CPTMutableLineStyle *savingsPlotLineStyle = [CPTMutableLineStyle lineStyle];
savingsPlotLineStyle.lineColor = touchPlotColor;
CPTPlotSymbol *touchPlotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
touchPlotSymbol.fill = [CPTFill fillWithColor:touchPlotColor];
touchPlotSymbol.lineStyle = savingsPlotLineStyle;
touchPlotSymbol.size = CGSizeMake(12.0f, 12.0f);
CPTMutableLineStyle *touchLineStyle = [CPTMutableLineStyle lineStyle];
touchLineStyle.lineColor = [CPTColor clearColor];
touchLineStyle.lineWidth = 1.0f;
CPTMutableLineStyle *symbolLineStyle = [CPTMutableLineStyle lineStyle];
symbolLineStyle.lineColor = [CPTColor clearColor];
CPTPlotSymbol *plotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
plotSymbol.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
plotSymbol.lineStyle = symbolLineStyle;
plotSymbol.size = CGSizeMake(10.0, 10.0);
touchPlot.plotSymbol = plotSymbol;
touchPlot.dataLineStyle = touchLineStyle;
}
// Assign different color to the touchable line symbol.
- (void)showTouchPlotColor
{
CPTColor *touchPlotColor = [CPTColor orangeColor];
CPTMutableLineStyle *savingsPlotLineStyle = [CPTMutableLineStyle lineStyle];
savingsPlotLineStyle.lineColor = touchPlotColor;
CPTPlotSymbol *touchPlotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
touchPlotSymbol.fill = [CPTFill fillWithColor:touchPlotColor];
touchPlotSymbol.lineStyle = savingsPlotLineStyle;
touchPlotSymbol.size = CGSizeMake(12.0f, 12.0f);
CPTMutableLineStyle *touchLineStyle = [CPTMutableLineStyle lineStyle];
touchLineStyle.lineColor = [CPTColor orangeColor];
touchLineStyle.lineWidth = 1.0f;
CPTMutableLineStyle *symbolLineStyle = [CPTMutableLineStyle lineStyle];
symbolLineStyle.lineColor = [CPTColor blackColor];
CPTPlotSymbol *plotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
plotSymbol.fill = [CPTFill fillWithColor:[CPTColor orangeColor]];
plotSymbol.lineStyle = symbolLineStyle;
plotSymbol.size = CGSizeMake(10.0, 10.0);
touchPlot.plotSymbol = plotSymbol;
touchPlot.dataLineStyle = touchLineStyle;
}
// This method is call when user touch & drag on the plot space.
- (BOOL)plotSpace:(CPTPlotSpace *)space shouldHandlePointingDeviceDraggedEvent:(id)event atPoint:(CGPoint)point
{
// Convert the touch point to plot area frame location
CGPoint pointInPlotArea = [graph convertPoint:point toLayer:graph.plotAreaFrame];
NSDecimal newPoint[2];
[graph.defaultPlotSpace plotPoint:newPoint forPlotAreaViewPoint:pointInPlotArea];
NSDecimalRound(&newPoint[0], &newPoint[0], 0, NSRoundPlain);
int x = [[NSDecimalNumber decimalNumberWithDecimal:newPoint[0]] intValue];
if (x < 0)
{
x = 0;
}
else if (x > [sampleData count])
{
x = [sampleData count];
}
selectedCoordination = x;
if ([delegate respondsToSelector:@selector(linePlot:indexLocation:)])
[delegate linePlot:self indexLocation:x];
[touchPlot reloadData];
return YES;
}
- (BOOL)plotSpace:(CPTPlotSpace *)space shouldHandlePointingDeviceDownEvent:(id)event
atPoint:(CGPoint)point
{
[self showTouchPlotColor];
return YES;
}
- (BOOL)plotSpace:(CPTPlotSpace *)space shouldHandlePointingDeviceUpEvent:(id)event atPoint:(CGPoint)point
{
[self hideTouchPlotColor];
touchPlotSelected = NO;
return YES;
}
#pragma mark -
#pragma mark Scatter plot delegate methods
- (void)scatterPlot:(CPTScatterPlot *)plot plotSymbolWasSelectedAtRecordIndex:(NSUInteger)index
{
if ([(NSString *)plot.identifier isEqualToString:kLinePlot])
{
touchPlotSelected = YES;
[self applyHighLightPlotColor:plot];
if ([delegate respondsToSelector:@selector(linePlot:indexLocation:)])
[delegate linePlot:self indexLocation:index];
}
}
#pragma mark -
#pragma mark Plot Data Source Methods
- (NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
if ([(NSString *)plot.identifier isEqualToString:kLinePlot])
{
return kNumberOfMarkerPlotSymbols;
}
else {
return [sampleData count];
}
}
- (NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSNumber *num = nil;
if ( [(NSString *)plot.identifier isEqualToString:kHighPlot] )
{
if ( fieldEnum == CPTScatterPlotFieldY )
{
num = [sampleData objectAtIndex:index];
}
else if (fieldEnum == CPTScatterPlotFieldX)
{
num = [NSNumber numberWithInt:index];
}
}
else if ([(NSString *)plot.identifier isEqualToString:kLinePlot])
{
if ( fieldEnum == CPTScatterPlotFieldY )
{
switch (index) {
case 0:
num = [NSNumber numberWithInt:-1000];
break;
case 2:
num = [NSNumber numberWithInt:12700];
break;
default:
num = [sampleData objectAtIndex:selectedCoordination];
break;
}
}
else if (fieldEnum == CPTScatterPlotFieldX)
{
num = [NSNumber numberWithInt:selectedCoordination];
}
}
return num;
}
答案 0 :(得分:3)
我最近遇到了同样的问题,找不到任何解决方案。经过一段时间的研究和编码后,我找到了一些解决方案并希望分享一个非常简单的解决方案,因此它可以帮助您了解如何处理这个问题。
我创建了透明的UIView,我把它放在了CPTGraphHostingView之上。 此视图正在处理所需的触摸事件。 我们将其命名为TestView
TestView.h文件看起来像
@protocol TestViewDelegate <NSObject>
- (void)myTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)myTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)myTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@interface TestView : UIView
@property (nonatomic, weak) id <TestViewDelegate>delegate;
@end
TestView.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.delegate myTouchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
[self.delegate myTouchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[self.delegate myTouchesEnded:touches withEvent:event];
}
TestView委托,在我的案例中,viewController,包括corePlot主机视图,将实现这些方法并查看下面代码的示例
- (void)myTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if (touches.count == 1) {
UITouch *touch = (UITouch *)[[touches allObjects] objectAtIndex:0];
CGPoint point = [touch locationInView:nil];
[self plotSpace:self.plotSpace shouldHandlePointingDeviceDraggedEvent:event atPoint:point];
}
if (touches.count == 2) {
UITouch *touch = (UITouch *)[[touches allObjects] objectAtIndex:1];
CGPoint point = [touch locationInView:nil];
[self plotSpace:self.plotSpace shouldHandlePointingDeviceDraggedEvent:event atPoint:point];
}
}
viewController中的CPTPlotSpace委托方法看起来像
- (BOOL)plotSpace:(CPTPlotSpace *)space shouldHandlePointingDeviceDraggedEvent:(id)event atPoint:(CGPoint)point{
NSSet *allTouches = [event allTouches];
if ([allTouches count] >0 ) {
UITouch *touch1 = [[allTouches allObjects] objectAtIndex:0];
if (touch1){
CGPoint pointInPlotArea = [self.graph convertPoint:[touch1 locationInView:self.view] toLayer:self.graph.plotAreaFrame];
// padding
pointInPlotArea.x -=10;
NSDecimal newPoint[2];
[self.graph.defaultPlotSpace plotPoint:newPoint forPlotAreaViewPoint:pointInPlotArea];
NSDecimalRound(&newPoint[0], &newPoint[0], 0, NSRoundPlain);
int x = [[NSDecimalNumber decimalNumberWithDecimal:newPoint[0]] intValue];
x--;
if (x <= 0)
x = 0;
else if (x >= [self.currentDatapoints count])
x = [self.currentDatapoints count] - 1;
selectedCoordination = x;
self.label.text = [NSString stringWithFormat:@"%@", [self.currentDatapoints objectAtIndex:x]];
self.differenceLabel.text = @"";
[touchPlot reloadData];
}
if ([allTouches count] > 1){
secondTouchPlot.hidden = NO;
UITouch *touch2 = [[allTouches allObjects] objectAtIndex:1];
if (touch2) {
CGPoint pointInPlotArea = [self.graph convertPoint:[touch2 locationInView:self.view] toLayer:self.graph.plotAreaFrame];
pointInPlotArea.x -= 10;
NSDecimal newPoint[2];
[self.graph.defaultPlotSpace plotPoint:newPoint forPlotAreaViewPoint:pointInPlotArea];
NSDecimalRound(&newPoint[0], &newPoint[0], 0, NSRoundPlain);
int x = [[NSDecimalNumber decimalNumberWithDecimal:newPoint[0]] intValue];
x--;
if (x <= 0)
x = 0;
else if (x >= [self.currentDatapoints count])
x = [self.currentDatapoints count] - 1;
selectedCoordination2 = x;
self.secondLabel.text = [NSString stringWithFormat:@"%@", [self.currentDatapoints objectAtIndex:x]];
[secondTouchPlot reloadData];
float first = [self.label.text floatValue];
float second = [[self.currentDatapoints objectAtIndex:x] floatValue];
self.differenceLabel.textColor = (first - second) > 0 ? [UIColor greenColor] : [UIColor redColor];
self.differenceLabel.text = [NSString stringWithFormat:@"%f", first - second];
}
}
}
return YES;
}
这就是结果......
这不是优化代码,正如我上面提到的,它只是如何解决这个问题。
希望它有所帮助...
答案 1 :(得分:2)
我很可能最终会在多个回复中回答这个问题,但我会在此时开始:
你会认为Apple会在他们的手势识别对象中提供API来辅助多种手指跟踪算法等,但它们到目前为止还没有。在我开发的游戏中,我还需要多个手指,最多4个及以上,全部在屏幕上并一次移动/跟踪。我发现我必须实现自己的手指跟踪/向下/向上算法来完成除简单单指滑动和捏合缩放操作之外的其他事情。让我们深入研究:
我相信你的EskLinePlot.m文件“应该处理事件”,你将需要实现“有多少手指关闭”的增量。这样一来,当另一个手指向下时,另一个手指已经宕机,你将有一个计数。同样,您将需要在“应该处理事件”例程中实现一个递减器。在所有这些中间,还需要一个(尽管)小型数据库(可能是NSMutableArray)的触摸。该数据库将用于将拖动事件与手指相关联。那么最终如何完成这项工作。在羽绒事件中,您将: 1)在触摸数据库中创建新记录(阵列号可以作为您的唯一标识符 2)将新触摸的当前位置记录到您在步骤1中创建的(新)触摸记录中作为最新(或阵列位置0)位置。触摸数据库中的每个触摸项目应该具有手指所处的最后位置的4到10之间的某个历史(我倾向于将位置记录为0 =最新到3或9作为最旧的位置)。 3)不是简单地打开您创建的SINGLE(图形)线,而是在发生向下事件时添加一条新的(图形)线(执行与当前屏幕手指位置相同的相关性以绘制数字位置)
对于“应该处理拖动事件”: 1)查看在拖动事件中被中继的手指的位置,并将其与内部保持的触摸数据库中的触摸相关联(触摸数据库中的触摸最接近此时呈现的触摸数据)。 2)将相关触摸的所有先前位置点向下移动1. 0到1,1到2等等...通过全部然后丢弃最后一个。 3)将新点添加到相关触摸的先前点列表中作为最新点。 4)适当地移动与该手指相关的(图形)线
对于一个up事件: 1)关联在触摸数据库中呈现给手指的位置。 2)从触摸数据库中删除相关的触摸。 3)从屏幕上删除您分配给该手指的(图形)线
我希望这有帮助,我应该可以在某处找到一些示例代码,但我目前不在我的开发机器前面。