1

I have two UIViews (BlueView and RedView) that draw a UIBeizerPath (It must be uibeizarpath).

My MainView initializes both views and controls the zoom feature.

I can get the views to zoom, however, when they zoom the UIBeizerPaths are pixelated. I have tried using [viewname].layer.contentsScale = [[UIScreen mainScreen] scale] * currentScale; but that does not work.

Any help wold be greatly appreciated!

Through the magic of Photoshop, here are some illustrations of what I am attempting to accomplish.

What the View looks like not zoomed:

Non Zoomed

My result of zooming in:

Bad Zoom

The desired result when zooming:

Desired Zoom

Any suggestions? Would be greatly appreciated. Here is my code:

MainView.h

#import <UIKit/UIKit.h>
#import “RedLine.h”
#import “BlueLine.h

@interface MainView : UIViewController {
    CGRect screenRect;

    //ZOOM
    CGFloat zoomScale;
    CGFloat _previousScale;
    CGPoint _originalCenter; 

RedLine * redLine;
BlueLine * blueLine;
}
@end

MainView.m

#import "MainView.h"
#import "BlueLine.h"
#import "RedLine.h"

// ZOOM SCALE
#define MAX_SCALE 4.0
#define MIN_SCALE 1.0


@interface MainView ()

@end

@implementation MainView

- (void)viewDidLoad
{
    [super viewDidLoad];
    screenRect = [[UIScreen mainScreen] bounds];

    zoomScale = 1.0;


    //Draw the lines
    blueLine = [[BlueLine alloc] initWithFrame:self.view.frame];
    [self.view addSubview:blueLine];

    redLine = [[RedLine alloc] initWithFrame:self.view.frame];
    [self.view addSubview:redLine];



    UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(zoomTool:)];
    [self.view addGestureRecognizer:pinchGesture];

}

#pragma mark - ZOOM 

//ZOOM VIEW
- (void) zoomTool:(UIPinchGestureRecognizer *)recognizer
{
    NSLog(@"Pinch scale: %f", recognizer.scale);
    if ([recognizer state] == UIGestureRecognizerStateBegan) {
        _previousScale = zoomScale;
    }

    CGFloat currentScale = MAX(MIN([recognizer scale] * zoomScale, MAX_SCALE), MIN_SCALE);
    CGFloat scaleStep = currentScale / _previousScale;
    [redLine setTransform: CGAffineTransformScale(redLine.transform, scaleStep, scaleStep)];
    redLine.layer.contentsScale = [[UIScreen mainScreen] scale] * currentScale;
    [blueLine setTransform: CGAffineTransformScale(blueLine.transform, scaleStep, scaleStep)];
    blueLine.layer.contentsScale = [[UIScreen mainScreen] scale] * currentScale;

    _previousScale = currentScale;

    if ([recognizer state] == UIGestureRecognizerStateEnded ||
        [recognizer state] == UIGestureRecognizerStateCancelled ||
        [recognizer state] == UIGestureRecognizerStateFailed) {
        // Gesture can fail (or cancelled?) when the notification and the object is dragged simultaneously
        zoomScale = currentScale;
    }


}
@end

BlueLine.m

#import "BlueLine.h"

@implementation BlueLine

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    UIBezierPath *thisLine = [UIBezierPath bezierPath];

    [thisLine moveToPoint:CGPointMake(100, 100)];
    [thisLine addLineToPoint:CGPointMake(250, 250)];
    thisLine.lineWidth = 10;
    [[UIColor blueColor] setStroke];
    [thisLine stroke];

}
@end

RedLine.m

#import "RedLine.h"

@implementation RedLine

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    UIBezierPath *thisLine = [UIBezierPath bezierPath];

    [thisLine moveToPoint:CGPointMake(300, 300)];
    [thisLine addLineToPoint:CGPointMake(100, 450)];
    thisLine.lineWidth = 10;
    [[UIColor redColor] setStroke];
    [thisLine stroke];

}
@end
JasonBourne
  • 338
  • 2
  • 13

1 Answers1

0

Transform will just stretch the view,so it gets pixelated instead follow below procedure.

when ever zoom happens call the setNeedsLayout method of your views.And increase the lineWidth by scale times original width.It will draw perfectly.

Add a new public property to your views.And below missing lines.

@property CGFloat zoomScale;

-(void)viewDidLoad{
 zoomScale=1.0;
}

-(void)drawRect{
    thisLine.lineWidth = 10*zoomScale;
}

so whenever zoom happens ,

blueView.zoomScale =zoomScale;
[blueView setNeedsDisplay];

FULL CODE (FOR RED LINE)

- (void) zoomTool:(UIPinchGestureRecognizer *)recognizer
{
    NSLog(@"Pinch scale: %f", recognizer.scale);
    if ([recognizer state] == UIGestureRecognizerStateBegan) {
        _previousScale = zoomScale;
    }

    CGFloat currentScale = MAX(MIN([recognizer scale] * zoomScale, MAX_SCALE), MIN_SCALE);
    redLine.scale=currentScale;
    [redLine setNeedsDisplay];
    _previousScale = currentScale;

    if ([recognizer state] == UIGestureRecognizerStateEnded ||
        [recognizer state] == UIGestureRecognizerStateCancelled ||
        [recognizer state] == UIGestureRecognizerStateFailed) {
        // Gesture can fail (or cancelled?) when the notification and the object is dragged simultaneously
        zoomScale = currentScale;
    }
}

RedLine.h

#import <UIKit/UIKit.h>

@interface RedLine : UIView
@property CGFloat scale;
@end

RedLine.m

#import "RedLine.h"

@implementation RedLine
@synthesize scale =scale;
- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        scale=1.0f;
    }
    return self;
}

- (void)drawRect:(CGRect)rect {


    [self setBackgroundColor:[UIColor clearColor]];

    CGPoint p1 =CGPointMake(50, 50);
    CGPoint p2 =CGPointMake(300, 300);

    CGFloat offsetX =self.center.x *(scale-1);
    CGFloat offsetY =self.center.y *(scale-1);

    p1.x =p1.x*scale -offsetX;
    p1.y =p1.y*scale -offsetY;

    p2.x =p2.x*scale -offsetX;
    p2.y =p2.y*scale -offsetY;


    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    CGContextSetLineWidth(context, 10*scale);

    CGContextMoveToPoint(context, p1.x, p1.y);
    CGContextAddLineToPoint(context, p2.x, p2.y);

    CGContextStrokePath(context);

}
@end
santhu
  • 4,796
  • 1
  • 21
  • 29