Issue with drawing with Quartz 2d / CGContext and zooming
Right now we have a UIScrollView that has one subview, a UIView. This UIView holds two UIImageView subviews, one is a static background image. The second UIImageView is a view for users to draw on, which we handle using CGContext.
We are using a scrollview because the background image and drawing area are large. When the user selects a button that enters drawing mode, they can swipe with two fingers to scroll and use one finger to draw. This all works fine.
The problem is when we leave drawing mode and try zooming in. The background image zooms perfectly, but the drawing UIImageView on top of it does something strange. It will stay the normal size for a couple seconds, disappear, and then suddenly appear at the zoomed in size. So it is zooming in, but there's some very strange behavior and a delay before it does.
For reference, here is how we handle the drawing.
/**
When the user first starts moving the pen
*/
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
isMouseMoved = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touc开发者_C百科h locationInView:imageView];
// Setting up the context
UIGraphicsBeginImageContext(imageView.frame.size);
[imageView.image drawInRect:CGRectMake(0, 0, imageView.frame.size.width, imageView.frame.size.height)];
if(isEraserOn){
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), eraserRadius);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
CGRect eraserFrame = eraser.frame;
eraserFrame.origin.x = currentPoint.x - (eraserRadius/2);
eraserFrame.origin.y = currentPoint.y - (eraserRadius/2);
eraser.frame = eraserFrame;
}else{
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), penRadius);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), r, g, b, 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeNormal);
}
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
mouseMoved++;
if (mouseMoved == 1) {
mouseMoved = 0;
}
}
Does anyone have any idea what's going on with our drawing UIImageView? We thought the delay might be due to antialiasing when it zooms in, but we tried disabling that and we still encounter the same problem.
The Problem, probably is that, you are doing all of your drawing inside the touchesMoved method rather than doing it in DrawRect and calling the setNeedsDisplay method to invoke drawing when you want. In an excellent video from wwdc 2011 it has been clearly explained that grabbing CGContext in methods such as touchesMoved or tochesBegan is one of the most common causes of problems associated with drawing. So I would suggest you : 1) Do not invoke UIGraphicsGetCurrentContext() in tochesMoved, rather do it in DrawRect method of the UIView on which the user draws. In touchesMoved, you can simply save the points that were touched and you can the same to draw lines in DrawRect 2) Send setNeedsDisplay message to the UIView at the end of touchesMoved. This will ensure that UIView refreshes every time touchesMoved is called and may improve the response time. You can give this a try without even trying (1)
Hope this helps!
精彩评论