2013-03-10 19 views
5

Mam UIImageView, który pokazuje obraz, który użytkownik właśnie zrobił z aparatem. Na tym obrazie muszę narysować przezroczyste ruchome koło, które ma ustawiony rozmiar. Tak więc, gdy użytkownik przeciąga palcem po obrazie, kółko porusza się wraz z nim. Następnie, jeśli użytkownik przestaje przesuwać palec, okrąg pozostaje w tym samym miejscu.Najlepszy sposób narysowania okręgu na UIImageView IOS

Byłem czytanie dokumentacji Apple na CAShapeLayer ale ja wciąż nie jestem pewien najlepszy sposób, byłbym rysowania UIView?

Wszelkie przykłady byłyby genialne. Dzięki.

Odpowiedz

19

Poniższy kod tworzy trzy gesty:

  • Gest kranu krople kółko na widoku (tak więc można zobaczyć, jak CAShapeLayer jest tworzony);

  • Gest przesunięcia przesuwa okrąg (zakładając, że zacząłeś poruszać się od wewnątrz koła); i

  • Gest szczypania zmienia rozmiar koła.

ten sposób, że może wyglądać tak:

#import <QuartzCore/QuartzCore.h> 
#import <UIKit/UIGestureRecognizerSubclass.h> 

@interface ViewController() 

@property (nonatomic, weak) CAShapeLayer *circleLayer; 
@property (nonatomic) CGPoint circleCenter; 
@property (nonatomic) CGFloat circleRadius; 

@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // create tap gesture 

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self 
                      action:@selector(handleTap:)]; 
    [self.view addGestureRecognizer:tap]; 

    // create pan gesture 

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self 
                      action:@selector(handlePan:)]; 
    [self.view addGestureRecognizer:pan]; 

    // create pinch gesture 

    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self 
                       action:@selector(handlePinch:)]; 
    [self.view addGestureRecognizer:pinch]; 
} 

// Create a UIBezierPath which is a circle at a certain location of a certain radius. 
// This also saves the circle's center and radius to class properties for future reference. 

- (UIBezierPath *)makeCircleAtLocation:(CGPoint)location radius:(CGFloat)radius 
{ 
    self.circleCenter = location; 
    self.circleRadius = radius; 

    UIBezierPath *path = [UIBezierPath bezierPath]; 
    [path addArcWithCenter:self.circleCenter 
        radius:self.circleRadius 
       startAngle:0.0 
        endAngle:M_PI * 2.0 
       clockwise:YES]; 

    return path; 
} 

// Create a CAShapeLayer for our circle on tap on the screen 

- (void)handleTap:(UITapGestureRecognizer *)gesture 
{ 
    CGPoint location = [gesture locationInView:gesture.view]; 

    // if there was a previous circle, get rid of it 

    [self.circleLayer removeFromSuperlayer]; 

    // create new CAShapeLayer 

    CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 
    shapeLayer.path = [[self makeCircleAtLocation:location radius:50.0] CGPath]; 
    shapeLayer.strokeColor = [[UIColor redColor] CGColor]; 
    shapeLayer.fillColor = nil; 
    shapeLayer.lineWidth = 3.0; 

    // Add CAShapeLayer to our view 

    [gesture.view.layer addSublayer:shapeLayer]; 

    // Save this shape layer in a class property for future reference, 
    // namely so we can remove it later if we tap elsewhere on the screen. 

    self.circleLayer = shapeLayer; 
} 

// Let's move the CAShapeLayer on a pan gesture (assuming we started 
// pan inside the circle). 

- (void)handlePan:(UIPanGestureRecognizer *)gesture 
{ 
    static CGPoint oldCenter; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     // If we're starting a pan, make sure we're inside the circle. 
     // So, calculate the distance between the circle's center and 
     // the gesture start location and we'll compare that to the 
     // radius of the circle. 

     CGPoint location = [gesture locationInView:gesture.view]; 
     CGPoint translation = [gesture translationInView:gesture.view]; 
     location.x -= translation.x; 
     location.y -= translation.y; 

     CGFloat x = location.x - self.circleCenter.x; 
     CGFloat y = location.y - self.circleCenter.y; 
     CGFloat distance = sqrtf(x*x + y*y); 

     // If we're outside the circle, cancel the gesture. 
     // If we're inside it, keep track of where the circle was. 

     if (distance > self.circleRadius) 
      gesture.state = UIGestureRecognizerStateCancelled; 
     else 
      oldCenter = self.circleCenter; 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     // Let's calculate the new center of the circle by adding the 
     // the translationInView to the old circle center. 

     CGPoint translation = [gesture translationInView:gesture.view]; 
     CGPoint newCenter = CGPointMake(oldCenter.x + translation.x, oldCenter.y + translation.y); 

     // Update the path for our CAShapeLayer 

     self.circleLayer.path = [[self makeCircleAtLocation:newCenter radius:self.circleRadius] CGPath]; 
    } 
} 

// Let's resize circle in the CAShapeLayer on a pinch gesture (assuming we have 
// a circle layer). 

- (void)handlePinch:(UIPinchGestureRecognizer *)gesture 
{ 
    static CGFloat oldCircleRadius; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     if (self.circleLayer) 
      oldCircleRadius = self.circleRadius; 
     else 
      gesture.state = UIGestureRecognizerStateCancelled; 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     CGFloat newCircleRadius = oldCircleRadius * gesture.scale; 
     self.circleLayer.path = [[self makeCircleAtLocation:self.circleCenter radius:newCircleRadius] CGPath]; 
    } 
} 

@end 
+2

Thanks Rob bardzo jasnych i po prostu to, co było potem, dałbym dwa kleszcze gdybym mógł :-) – MrBeanzy

+0

@Rob powyższy kod jest wielki czy możesz mi również pomóc, wiedząc, jak przyciąć część obrazu pod kółkiem do osobnego obrazu? Dzięki –

+0

@Rob również gesture.state = UIGestureRecognizerStateCancelled; daje błąd na ios7 –

Powiązane problemy