2012-06-24 13 views
21

Ecco un semplice disegnoUIBezierPath traccia 1px linea e riempie rettangolo larghezza 1px - risultati diversi.

 

- (void)drawRect:(CGRect)rect 
{ 
    //vertical line with 1 px stroking 
    UIBezierPath *vertLine = [[UIBezierPath alloc] init]; 
    [vertLine moveToPoint:CGPointMake(20.0, 10.0)]; 
    [vertLine addLineToPoint:CGPointMake(20.0, 400.0)]; 
    vertLine.lineWidth = 1.0; 
    [[UIColor blackColor] setStroke]; 
    [vertLine stroke]; 

    //vertical rectangle 1px width 
    UIBezierPath *vertRect= [UIBezierPath bezierPathWithRect:CGRectMake(40.0, 10.0, 1.0, 390.0)]; 
    [[UIColor blackColor] setFill]; 
    [vertRect fill]; 

} 

On non retina 3GS e simulatore la prima linea è sfocata e sembra più ampio di 1 px, ma la seconda linea è croccante.

Purtroppo non ho né l'iPhone 4 né il nuovo iPad da testare, ma sul simulatore di retina entrambe le linee sembrano uguali.

Domanda: il rettangolo anziché il tratto è l'unico modo per ottenere lo stesso risultato per i dispositivi non retina e retina?

risposta

51

Si sta riempiendo l'interno del rettangolo ma si sta accarezzando la linea dal centro. Poiché le coordinate in entrambi i casi (gli angoli del rettangolo e le coordinate di inizio e fine nella linea) sono definite come valori di numeri interi (senza frazioni), le coordinate si trovano sui confini dei punti esatti.

Ho detto "coordinate" sopra quando si parla dei punti della linea, per non confonderli con i punti sullo schermo. Ho anche detto "limiti di punti" invece di "limiti di pixel" per lo stesso motivo. iOS definisce le sue coordinate e tutti i punti in quelli che vengono chiamati "punti" anziché in pixel. Un punto è una misura indipendente dalla risoluzione. Entrambi i dispositivi retina e non retina hanno lo stesso numero di punti sullo schermo, è solo che corrispondono a un diverso numero di pixel effettivi. sguardo

Let ad accarezzare una linea che si trovano sui confini del punto (come nella vostra domanda) rispetto al riempimento di un rettangolo in cui gli angoli si trovano sui confini punto:

Nelle illustrazioni che seguono sto accarezzando una linea con il nero e riempiendo un rettangolo con l'arancione su uno schermo non retina e uno schermo retina. Ho anche delineato la linea e il rettangolo con il blu. In entrambi i casi è possibile visualizzare la dimensione di un punto per tale risoluzione e confrontarlo con la griglia di pixel effettiva.

Nel caso di non retina, è possibile notare che tentare di accarezzare la linea dal centro con una linea di 1 punto con (in questo caso corrispondente a una larghezza di linea di 1 pixel) riempirebbe metà dei pixel in alto e metà sui pixel sottostanti. Poiché i pixel sono riempiti solo a metà, l'opacità di tali pixel è del 50%. Ciò si traduce in un colore più chiaro (su uno sfondo bianco). Poiché entrambi i pixel in alto e in basso sono riempiti di partito, accarezzano i pixel sia sopra che sotto. Questo fa apparire la linea come se fosse larga 2 pixel invece di una.

È possibile confrontarlo rapidamente con il rettangolo che viene riempito all'interno.

non retina

Lo stesso caso su uno schermo retina, un aspetto diverso. In questo caso, la dimensione di un punto è la stessa ma consiste di 4 pixel anziché 1. Questa volta, quando si accarezza la linea, mezzo punto sopra la linea e mezzo punto sotto la linea riempirà completamente la riga di pixel sopra e sotto a causa dello schermo ad alta risoluzione. Ciò significa che la linea appare come se fosse larga 1 punto e che il colore appaia completamente opaco.

Possiamo anche vedere che il rettangolo riempito ha lo stesso aspetto.

retina


Per risolvere questo problema, si dovrebbe mettere i punti per la vostra linea in pixel e mezzo.Tracciando la linea dal centro su un dispositivo a bassa risoluzione significa che la linea si estende di mezzo punto verso l'alto e mezzo punto verso il basso. Poiché il centro della linea si trova ora al centro del punto, significa che la linea tratteggiata si trova completamente all'interno dei pixel e la linea appare nitida. Fare ciò non avrà alcun effetto sulla linea della retina poiché spostando in basso (o su) mezzo punto, significa comunque che riempirai completamente i pixel sopra e sotto.

Nell'illustrazione seguente (per retina) ho mostrato sia la griglia di punti che la griglia di pixel.

half pixel non-retina half pixel retina

2

La ragione si ottengono risultati diversi con ictus e riempire è che le loro interpretazioni di argomenti è diverso.

Il tratto aggiunge metà della larghezza della linea su ciascun lato della coordinata. Quindi il tuo punto è 20.0 e la larghezza della linea è 1px. Il risultato sarà una linea nera da 1 pixel tra (19.5-20.5), teoricamente. Poiché non c'è alcun pixel non integrato sullo schermo del dispositivo, verrà convertita una linea grigia/sfocata di 2 pixel tra (19-21). per aggirare questo problema, devi sommare ciascuna delle tue coordinate con 0.5 (come in CGPointMake (20.5, 10.5)) in modo che la larghezza non venga più divisa tra pixel.

Tuttavia, gli argomenti nel riempimento vengono utilizzati per impostare i bordi dell'area da riempire, CGRectMake (40.0, 10.0, 1.0, 390.0) implica una regione compresa tra (40 - 41). Di conseguenza non vi è alcuna parte frazionaria che cade sui pixel per apparire sfocata.

Problemi correlati