Search code examples
iphoneiosuiscrollviewquartz-graphicsquartz-2d

UIScrollView pinch zoom into CGContextStrokePath without changing line width


I have a UIScrollView that contains a custom UIView. In my UIView I am overriding drawRect to draw a path using CGContextStrokePath. I would like to slightly alter the way the zoom works. Pinch zooming out will show more of the paths on the screen. This is what I want but i want the line width to stay the same not shrink as you zoom out so that they are still clear to the user.

I thought I would just do this (myUIView zoom target is called _lineView)

-(void)scrollViewDidZoom:(UIScrollView *)pScrollView
    {
      _lineView.zoomScale = _scrollView.zoomScale;
      [_lineView setNeedsDisplay];
    }

and then just calculate an appropriate line stroke size in my _lineView drawRect method to give the effect of constant line width as you zoom out.

This is really slow and I have read that this is expected as drawrect is not optimised to be called many times a second.

I then started looking at using a GLKView instead and just rendering the whole thing in opengl directly. The problem with this is I will have to implement all of the zooming and panning myself (with all the lovely zoom and pan bounce effects you get for free in UiScrollView). I will also have to implement all the controls I want to use in opengl, buttons etc.

Is there a way to do this whilst still using Quartz2d? I feel like opengl will give me lots of power but it will take me much longer to get the rest of my app done if I go down that route.


Solution

  • I figured this out. I found a simple way to do this that does not slow down the zoom / bouncing animations at all and is very fast and fluid.

    Quartz has a class called CAShapeLayer that lets you do some pretty cool stuff. Among these is being able to set a CGPath property and specify a linewidth. Changes are reflected in the view.

    So i basically call shapeLayer.lineWidth from my scrollViewDidZoom method and it does exactly what i need.