objective-ciosuikitquartz-core

Smooth line after zooming


I am trying to implement a drawing feature. Currently I am using UIBezierPath:

@interface DrawView : UIView {
    UIBezierPath *myPath;
}
@end

@implemenation DrawView

-(id)initWithFrame:(CGRect)frame {
    //...normal init code
    myPath = [[UIBezierPath alloc]init];
    myPath.lineCapStyle = kCGLineCapRound;
    myPath.lineJoinStyle = kCGLineJoinRound;
    myPath.miterLimit = 0;
    myPath.lineWidth = 10;
}

In touchesBegan: I track the startPoint and call [myPath moveToPoint:myTouch locationInView:self]; In touchesMoved: I call [myPath addLineToPoint...]; [self setNeedsDisplay].

My DrawView is a subview of a UIScrollView.

My problem: When I zoom in the drawing is very cornered or pixelated.

I want to redraw the drawing in a way so it looks nice and smooth, but I can't figure out how or where to start.

I've found this simple "solution":

-(void)scrollViewDidEndZooming:(UIScrollView*)scrollView withView:(UIView*)view atScale:(float)scale {
    view.layer.contentsScale = scale;
    [view setNeedsDisplay];
}

When I implement the method in this way the drawing will be smoother after zomming, but the App becomes really laggy and slow. At a high maximumZoomScale of the scrollView the App crahes completely. When I understand the docu correctly setting contentsScale higher than 2 isn't a good idea or changing contensScale in any way isn't so good.


Solution

  • I found a solution for my problem (I'm still facing other problems with drawing...): When zooming is finished I call a method that looks like this:

        -(void)redrawWithScale:(float)scale {
            _myPath.lineWidth = _myPath.lineWidth * scale //currently _myPath is a UIBezierPath, with CGPath it should be equal
            [_myPath applyTransform:CGAffineTransformMakeScale(scale, scale)];
    
            [self setNeedsDisplay];
    
            //or with a CAShapeLayer:
            _shapeLayer.path = _myPath.CGPath;
       }
    

    Edit:

    In my current implementation I'm using a CAShapeLayer (as a sublayer of my UIView). The UIBezierPath is set to the path attribute of the shapeLayer. Calling setNeedsDisplay isn't neccessary with this solution.