简体   繁体   中英

iOS: How do I draw a line (UIBezierpath or otherwise) that fades over time, and interacts with views as it touches them?

For example:

I draw the orange line below with my finger, as it touches the blue squares, they light up.

I can draw a line using UIBezierPath from StackOverflow questions / tutorials I found, but I have no idea how to make it fade away or interact with other views.

This is not a for a game, just a regular iOS app. I'm not sure if that changes things.

Any ideas?

范例图片

I've achieved a rubbish version that isn't smooth, but has the feel i'm going for in terms of line drawing

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [[[event allTouches] allObjects] firstObject];
    CGPoint point = [touch locationInView:self.view];
    UIView *dot = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, 6, 6)];
    dot.backgroundColor = UIColorFromRGB(0xeb3b6e);
    dot.layer.cornerRadius = 3;

    for(UILabel *el in self.testLabels){
        CGPoint pointInSuperView = [self.view convertPoint:point toView:el.superview];
        if(CGRectContainsPoint(el.frame, pointInSuperView))
            el.textColor = UIColorFromRGB(0xeb3b6e);
    }
    [self.view addSubview:dot];
    [UIView animateWithDuration:1.0 animations:^{
        dot.alpha = 0;
    } completion:^(BOOL finished) {
        [dot removeFromSuperview];
    }];
}

If by "it" in "it touches the blue squares", you mean the line, that will be difficult to do. A line has no rect, so you can't use methods like CGRectIntersectsRect to see if the line and square intersect. It would be much easier to use the touch point of your finger (which should be where the line is anyway). You probably want to have the blue squares in an array, and inside touchesMoved, loop through the array to see if any of the squares contains the touch point (using CGRectContainsPoint).

You probably have already a UIPanGesture set-up or a touchesBegan: / touchesMoved: implementation that enables you to make your drawing. Since you are always drawing up to your current finger's position, you could use the pan gesture's or touche's locationInView: CGPoint (that you should already be using to update your UIBezierPath) to check if it intersects one of your squares with CGRectContainsPoint .

To make your line fade away, the simple way would be to start a timer when you stop drawing, and make the layer containing that drawing fade away:

CABasicAnimation *fadeAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeAnim.fromValue = @(1);
fadeAnim.toValue = @(0);
fadeAnim.duration = 1;
[myLayer addAnimation:fadeAnim forKey:nil];
myLayer.opacity = 0;

Or you could animate the line to make it "shorten" (like the snake game), if you use a CAShapeLayer:

CABasicAnimation *strokeAnim = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
strokeAnim.fromValue = @(0);
strokeAnim.toValue = @(1);
strokeAnim.duration = 3;
[shapeLayer addAnimation:strokeAnim forKey:nil];

To make it fade away from the beginning of the line to the most recent part, it is another story, because it requires you to "paint" your line with a gradient color.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM