Question

I am doing a calligraphy application and would like to modify my code below so when a user ends a brush stroke, the line tapers and thins out like it would with a real calligraphy pen (a flick effect). I understand that touchesEnded may be a better way to do this, however I was just wondering what would be the best way to programmatically make this flick at the end of a stroke using CGRect or GraphicsContext in UIKit in Xcode for Objective C.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;

UITouch *touch = [touches anyObject];
currentPoint = [touch locationInView:self.view];



UIGraphicsBeginImageContext(CGSizeMake(320, 568));
[drawImage.image drawInRect:CGRectMake(0, 0, 320, 568)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0, 0, 0, 1);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());


[drawImage setFrame:CGRectMake(0, 0, 320, 568)];
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
//what code do I put here to get the flick effect - what CGGetContext Parameter
//may be applicable or what programming technique may help with this.     

}
Was it helpful?

Solution

This may be over simplifying, but it should lead you in something of the right direction. I'm going to just make a triangle, but you could eventually add bezier curves to make the effect more realistic.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
//what code do I put here to get the flick effect - what CGGetContext Parameter
//may be applicable or what programming technique may help with this. 

    UIGraphicsBeginImageContext(CGSizeMake(320, 568));
    [drawImage.image drawInRect:CGRectMake(0, 0, 320, 568)];
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 5.0);
    CGContextSetRGBFillColor(context, 0, 0, 0, 1);
    CGContextBeginPath(context);
    CGContextBeginPath(context);
    CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
    CGContextClosePath(context);
    CGContextStrokePath(context);

    //Normalized directionality
    float lineLength = sqrt((currentPoint.x - lastPoint.x)*(currentPoint.x - lastPoint.x) + (currentPoint.y - lastPoint.y)*(currentPoint.y - lastPoint.y));
    float dx = (currentPoint.x - lastPoint.x)/lineLength;
    float dy = (currentPoint.y - lastPoint.y)/lineLength;

    //Now make a triangle
    CGContextBeginPath(context);

    //2.5 is from 1/2 of your line width (5)
    CGContextMoveToPoint(context, currentPoint.x + 2.5*dy, currentPoint.y - 2.5*dx);

    //This 10 is completely arbitrary, the length your taper is going to be.
    //Ideally this will be proportional to your last line segment length, longer if their finger is moving faster...
    CGContextAddLineToPoint(context, currentPoint.x + 10*dx, currentPoint.y + 10*dy);

    //Now the last tip of the triangle
    CGContextMoveToPoint(context, currentPoint.x - 2.5*dy, currentPoint.y + 2.5*dx);
    CGContextClosePath(context);
    CGContextFillPath(context);

    [drawImage setFrame:CGRectMake(0, 0, 320, 568)];
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

Now to make this cooler you could add in calculation of the curve the person was drawing and create your "triangle" taper with bezier curves in the direction that they were curving. That could actually be really fun to calculate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top