Track touch points in Multitouch

2019-01-20 09:59发布

问题:

I am working on a drawing project, I want to support multitouch, I have gone through documentation online, which suggest to track the touch points, I did it , But I am not getting the desired behaviour. I am not getting straight lines.

Below is my code

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    red = 0.0/255.0;
    green = 0.0/255.0;
    blue = 0.0/255.0;
    brush = 10.0;
    opacity = 1.0;

     self.view.multipleTouchEnabled = YES;

     touchPaths = [NSMutableDictionary dictionary];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {


    for (UITouch *touch in touches)
    {
        NSString *key = [NSString stringWithFormat:@"%d", (int) touch];
        lastPoint = [touch locationInView:self.view];

        [touchPaths setObject:[NSValue valueWithCGPoint:lastPoint] forKey:key];
    }

}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    for (UITouch *touch in touches)
    {
        NSString *key = [NSString stringWithFormat:@"%d", (int) touch];

        lastPoint = [[touchPaths objectForKey:key] CGPointValue];


        CGPoint currentPoint1 = [touch locationInView:self.view];

        UIGraphicsBeginImageContext(self.view.frame.size);
        [self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint1.x, currentPoint1.y);
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);

        CGContextStrokePath(UIGraphicsGetCurrentContext());
        self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
        [self.tempDrawImage setAlpha:opacity];
        UIGraphicsEndImageContext();

        lastPoint = currentPoint1;

    }
}

But when I draw using this code, I get this.

So friends, please help me out, what I am doing wrong.

Regards Ranjit

回答1:

You are not populating the touchPaths properly. Try setting it after each drawing instead, something like this:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    for (UITouch *touch in touches)
    {
        NSString *key = [NSString stringWithFormat:@"%d", (int) touch];

        CGPoint lastPoint = [[touchPaths objectForKey:key] CGPointValue];


        CGPoint currentPoint1 = [touch locationInView:self.view];

        UIGraphicsBeginImageContext(self.view.frame.size);
        [self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint1.x, currentPoint1.y);
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);

        CGContextStrokePath(UIGraphicsGetCurrentContext());
        self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
        [self.tempDrawImage setAlpha:opacity];
        UIGraphicsEndImageContext();
        // I changed your code here
        [touchPaths setObject:[NSValue valueWithCGPoint:currentPoint1] forKey:key];

    }
}

You are currently setting lastPoint here but you do not seem to use it (and it would only work with one touch). There is no need to have lastPoint as a field either.



回答2:

I always try to use gesture-recognizers when possible. Here I use the UIPanGestureRecognizer:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPan:)]];
}

- (void)didPan:(UIPanGestureRecognizer*)panGesture {
    for (NSUInteger touchIndex = 0; touchIndex < panGesture.numberOfTouches; touchIndex++) {
        // touchIndex is basically the "source" (the finger) from which the point comes from
        CGPoint p = [panGesture locationOfTouch:touchIndex inView:self.view];
        [self drawAtPoint:p withIndex:touchIndex];
    }
}


- (void)drawAtPoint:(CGPoint)point withIndex:(NSUInteger)index{
    UIView *smallPoint = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, 3, 3)];
    [smallPoint setBackgroundColor:[self colorForIndex:index]];
    [self.view addSubview:smallPoint];
}

- (UIColor*)colorForIndex:(NSUInteger)index {
    switch (index) {
        case 0: return [UIColor redColor];
        case 1: return [UIColor orangeColor];
        case 2: return [UIColor yellowColor];
        case 3: return [UIColor blueColor];
        case 4: return [UIColor greenColor];
    }
    return [UIColor clearColor];
}

I don't draw a bezier path, but if you drop it in an empty ViewController and run it, you will see that when multi-touching the screen, each finger draws a different colour.

So if you take into consideration the touchIndex, basically you can keep track of different paths for different fingers.

Let's say you use two fingers to draw: you will have panGesture.numberOfTouches == 2, and touchIndex 0 will represent the first finger, and touchIndex 1 will represent the second finger. You can accumulate the points in different arrays and add the points to their corresponding path.