Scale using a drawing view

I am looking for a solution to have beautiful scaling in the form of a drawing. In my application, I have a view with another UIView (which is used as a drawing view), and when I draw a stroke on it, the stroke is perfect. But when I zoom in, I have this ugly effect (pixelated stroke): screenshot http://data.imagup.com/10/1160827911.5509png

Url

Is there a solution to have the right move?

My UIViewController has a hierarchy like this:

  • UIViewController
    • Scrollview
      • Scalable view (determined using the viewForZoomingInScrollView method)
        • Picture
        • Drawing view

Thanks a lot!

Regards, Sebastian;)

+4
source share
3 answers

I am creating a vector drawing application, and let me tell you that this is NOT an easy task to work properly and requires quite a bit of work.

Some points to keep in mind:

  • If you do not use vector graphics (for example, CGPaths vectors), you cannot delete pixels. UIImage, for example, only has this permission.
  • So that your drawing does not look uneven, you are going to need to redraw everything. If you have a lot of drawing, this can be an expensive task.
  • A good WHILE resolution scaling is almost impossible, because it will require too much context, and your drawing is likely to exceed the capabilities of the device.

I use the main graphics for drawing, so I solved this problem by selecting and managing several CGContexts and using them as buffers. I have one context that is ALWAYS stored at my minimum increased level (scale factor 1). This context is involved at all times and makes it such that when the time is completely turned off, the time taken to re-draw is not executed, since it has already been done. Another context is used for drawing when scaling. If not scaled, this context is ignored (since in any case it will have to be redrawn based on the new zoom level). The high-level algorithm for how I perform scaling is as follows:

- (IBAction)handlePinchGesture:(UIGestureRecognizer *)sender { if(sender.state == UIGestureRecognizerStateBegan) { //draw an image from the unzoomedContext into my current view //set the scale transformation of my current view to be equal to "currentZoom", a property of the view that keeps track of the actual zoom level } else if(sender.state == UIGestureRecognizerStateChanged) { //determine the new zoom level and transform the current view, keeping track in the currentZoom property //zooming will be pixelated. } else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled) { if(currentZoom == 1.0) { //you are done because the unzoomedContext image is already drawn into the view! } else { //you are zoomed in and will have to do special drawing //perform drawing into your zoomedContext //scale the zoomedContext //set the scale of your current view to be equal to 1.0 //draw the zoomedContext into the current view. It will not be pixelated! //any drawing done while zoomed needs to be "scaled" based on your current zoom and translation amounts and drawn into both contexts } } } 

This becomes even more complicated for me because I have extra buffers for buffers, because drawing images of my paths is much faster than drawing paths when there are a lot of drawings.

Between managing multiple contexts, setting up your code for efficient use in multiple contexts, after proper OOD, scaling a new drawing based on your current scaling and translation, etc., this is a mountain of work. I hope this either motivates you and puts you on the right path, or you decide that getting rid of this pixelation is not worth the effort :)

+4
source

I had the same problem and found a solution: tell the view to use CATiledLayer as the base layer, and then tell me how many zoom levels it supports. This worked for me, my drawing methods are automatically called when the view (parent) is enlarged.

A brief explanation of levelsOfDetail and levelsOfDetailBias :

  • levelsOfDetail determine how many zoom levels exist in total
  • levelsOfDetailBias determine how many of them are scaled.

So, in my example, I have 4 zoom levels, 3 are increased, and 1 is not an increased level, which means that my view only redraws when scaling.

 @imprementation MyZoomableView + (Class)layerClass { return [CATiledLayer class]; } - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { ((CATiledLayer *)self.layer).levelsOfDetail = 4; ((CATiledLayer *)self.layer).levelsOfDetailBias = 3; } return self; } @end 
+1
source

Use [self setContentScaleFactor:scale]; in your delegate method scrollViewDidEndZooming:

0
source

All Articles