2012-06-25 13 views
10
self.myPath=[UIBezierPath bezierPathWithArcCenter:center 
              radius:200 
             startAngle:0 
             endAngle:180 
             clockwise:YES]; 

(questo molto sono stato in grado di alzarsi in esecuzione con l'aiuto di un po 'googling ..)Come ottenere il percorso inverso di un UIBezierPath

ho questo percorso. Ora voglio riempire il contrario di questo percorso, quindi lasciare questa parte e riempire tutto il resto. Qualcuno può aiutarmi con la codifica. Non ho molte informazioni su questo.

> IL PROBLEMA

enter image description here

L'area sta mostrando dopo aver usato Cemal Risposta in precedenza mostrava solo un cerchio con corsa rosso.

> NEW EDIT

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     self.backgroundColor = [UIColor whiteColor]; 
     self.punchedOutPath = 
     [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 400, 400)]; 
     self.fillColor = [UIColor redColor]; 
     self.alpha = 0.8; 
    } 
    return self; 
} 

- (void)drawRect:(CGRect)rect 
{ 
    [[self fillColor] set]; 
    UIRectFill(rect); 

    CGContextRef ctx = UIGraphicsGetCurrentContext(); 
    CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut); 

    [[self punchedOutPath] fill]; 

    CGContextSetBlendMode(ctx, kCGBlendModeNormal); 
} 

enter image description here

+0

Sarà un cerchio completo o una forma circolare aperta? Inoltre, puoi fornire un'immagine di ciò che ti aspetti? Non deve essere bello, ma aiuterà molto le persone a capire cosa stai cercando di fare in modo che possano aiutarti. –

+0

done..stato lavorando per fornirlo solo da quando ho creato la taglia – Shubhank

risposta

2

ho due soluzione per voi.

  1. Disegnare questo percorso su un CALayer. E usa quello CALayer come livello maschera per te attuale CALayer.

  2. Disegna un rettangolo con le dimensioni del tuo fotogramma prima di aggiungere un arco.

    UIBezierPath *path = [UIBezierPath bezierPathWithRect:view.frame]; 
    [path addArcWithCenter:center 
           radius:200 
          startAngle:0 
           endAngle:2*M_PI 
          clockwise:YES]; 
    

userei seconda soluzione. :)

+2

La seconda soluzione è la migliore, tranne che l'arco deve essere aggiunto in senso antiorario, quindi l'area che delimita è esclusa da [la regola del numero di avvolgimento diverso da zero] (https: //developer.apple.com/library/ios/documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_paths/dq_paths.html#//apple_ref/doc/uid/TP30001066-CH211-TPXREF106) (il rettangolo viene aggiunto in senso orario) . –

+0

questo non sta funzionando per me sto ottenendo un risultato piuttosto strano..io l'ho aggiunto nella domanda..ricilmente vedere..grazie – Shubhank

+1

endAngle deve essere radianti (non gradi). Vuoi un cerchio a 360 °, quindi è 2 o 6.283. Puoi scrivere questo come '2 * M_PI'. –

12

Ecco un'alternativa che non richiede invertire il percorso del tutto.

Si hanno una porzione di una vista che si vuole in sostanza "ritagliare":

clipped out

Diciamo che si desidera che l'area bianca per essere [UIColor whiteColor] con il 75% alfa. Ecco come procedere rapidamente:

  • Si crea una nuova sottoclasse UIView.
  • Questo punto di vista ha due proprietà:

    @property (retain) UIColor *fillColor; 
    @property (retain) UIBezierPath *punchedOutPath; 
    
  • di ignorare il suo metodo -drawRect: per fare questo:

    - (void)drawRect:(CGRect)rect { 
        [[self fillColor] set]; 
        UIRectFill(rect); 
    
        CGContextRef ctx = UIGraphicsGetCurrentContext(); 
        CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut); 
    
        [[self punchedOutPath] fill]; 
    
        CGContextSetBlendMode(ctx, kCGBlendModeNormal); 
    } 
    

C'è un avvertimento qui: Il fillColor della vista deve non include il componente alfa. Quindi nel tuo caso vorrai che sia solo [UIColor whiteColor]. Quindi applica tu stesso il bit alpha chiamando [myView setAlpha:0.75].

Cosa sta succedendo qui: si sta utilizzando una modalità di fusione chiamata "Destinazione esterna". Matematicamente è definito come R = D*(1 - Sa), ma in parole povere significa "Immagine di destinazione ovunque l'immagine di destinazione è opaca ma l'immagine di origine è trasparente e trasparente altrove".

Così sta andando a utilizzare la destinazione (vale a dire, ciò che è già nel contesto) se la nuova roba è trasparente (cioè al di fuori del percorso di Bezier), e quindi dove il tracciato Bezier sarebbe opaca, che roba è diventerà trasparente. Tuttavia, il materiale di destinazione deve essere già opaco. Se non è opaco, la fusione non fa quello che vuoi. Questo è il motivo per cui devi fornire un opaco UIColor e quindi fare qualsiasi trasparenza tu voglia con la vista direttamente.


mi sono imbattuto questo me stesso, con queste circostanze:

  • la finestra ha uno sfondo [UIColor greenColor]
  • il fillColor è bianco
  • il punchedOutPath è un ovale che è inserto 10 punti dai bordi della vista.
  • la vista ha una alpha di 0.75

Con il codice precedente, ottengo questo:

enter image description here

L'interno è verde puro, e l'esterno ha la sovrapposizione semitrasparente.


Aggiornamento

Se il rivestimento è un'immagine, allora avrete bisogno di creare una nuova immagine. Ma il principio è lo stesso:

UIImage* ImageByPunchingPathOutOfImage(UIImage *image, UIBezierPath *path) { 
    UIGraphicsBeginImageContextWithOptions([image size], YES, [image scale]); 

    [image drawAtPoint:CGPointZero]; 

    CGContextRef ctx = UIGraphicsGetCurrentContext(); 
    CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut); 
    [path fill]; 


    UIImage *final = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return final; 
} 

Si potrebbe quindi prendere il risultato di questa funzione e metterlo in una UIImageView.

+0

sarai in grado di fornirmi il tuo progetto .. ?? Per favore..! sarebbe meglio dato che avrei un codice funzionante ... altrimenti dovrò chiarire le domande con te ... e questo potrebbe diventare noioso per te! – Shubhank

+0

@shubhank il codice nella risposta descrive tutto ciò di cui hai bisogno –

+0

ciao..puoi controllare la mia nuova modifica al ques..i ho provato il tuo metodo..setto lo sfondo della mia vista per essere di colore bianco ... ma l'ovale è è di colore nero .. puoi aiutarmi con esso.avrebbe dovuto essere bianco ... grazie – Shubhank

14

Utilizzare bezierPathByReversingPath. Da documenti (solo iOS 6.0+):

Crea e restituisce un nuovo oggetto percorso Bezier con i contenuti invertiti del percorso corrente.

modo per invertire il vostro percorso, devi solo:

UIBezierPath* aPath = [UIBezierPath bezierPathWithArcCenter:center 
                radius:200 
               startAngle:0 
                endAngle:180 
                clockwise:YES]; 
self.myPath = [aPath bezierPathByReversingPath]; 
2

Si può mettere questo in una singola applicazione schermo nel controller della vista: Si farà una vista sfondo giallo e uno strato blu sopra di esso che ha una regione ovale ritagliata da una maschera.

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    // create a yellow background 
    UIView *bg = [[UIView alloc] initWithFrame:self.view.bounds]; 
    bg.backgroundColor = [UIColor yellowColor]; 
    [self.view addSubview:bg];  

    // create the mask that will be applied to the layer on top of the 
    // yellow background 
    CAShapeLayer *maskLayer = [CAShapeLayer layer]; 
    maskLayer.fillRule = kCAFillRuleEvenOdd; 
    maskLayer.frame = self.view.frame; 

    // create the paths that define the mask 
    UIBezierPath *maskLayerPath = [UIBezierPath bezierPath]; 
    [maskLayerPath appendPath:[UIBezierPath bezierPathWithRect:CGRectInset(self.view.bounds, 20, 20)]]; 
    // here you can play around with paths :) 
// [maskLayerPath appendPath:[UIBezierPath bezierPathWithOvalInRect:(CGRect){{80, 80}, {140, 190}}]]; 
    [maskLayerPath appendPath:[UIBezierPath bezierPathWithOvalInRect:(CGRect){{100, 100}, {100, 150}}]]; 
    maskLayer.path = maskLayerPath.CGPath; 

    // create the layer on top of the yellow background 
    CALayer *imageLayer = [CALayer layer]; 
    imageLayer.frame = self.view.layer.bounds; 
    imageLayer.backgroundColor = [[UIColor blueColor] CGColor]; 

    // apply the mask to the layer 
    imageLayer.mask = maskLayer; 
    [self.view.layer addSublayer:imageLayer]; 

} 

questo potrebbe rispondere a questa domanda così: UIBezierPath Subtract Path

+0

Puoi spiegare cosa stai facendo e perché? Solo così la persona che ha chiesto e altre persone in cerca della risposta capiscono di cosa si tratta. – Manuel

+0

La "regione ovale" mostra per me il quadrato ... – zakdances

+0

Strano, perché non [UIBezierPath bezierPathWithOvalInRect:] disegna un ovale? Hai copiato e incollato esattamente quel codice in un progetto vuoto a schermo singolo? – user511

Problemi correlati