2013-08-12 15 views
5

Sto lavorando a un'applicazione di disegno di piccole dimensioni, che ha un requisito di base per supportare lo zoom in/out. Ho due questioni principali:Disegno su una vista zoomabile

  1. disegno non appare nitida e chiara, quando la vista viene ingrandita/trasforma. C'è un approccio migliore, o c'è un modo per migliorare il disegno quando la vista è ingrandita?

  2. Le prestazioni del disegno sono lente, quando si esegue il disegno su una tela di 1200 x 1200 punti (su iPhone). Qualche possibilità di migliorarlo per tele di grandi dimensioni?

Codice Zoom:

- (void)scale:(UIPinchGestureRecognizer *)gestureRecognizer { 
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer]; 

    UIView *canvas = [gestureRecognizer view]; 

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || 
     [gestureRecognizer state] == UIGestureRecognizerStateChanged) { 

     // Calculate the drawing view's size 
     CGSize drawingViewSize = ...; 

     // Calculate the minimum allowed tranform size 
     // Developer's Note: I actually wanted to use the size 1/4th of the view 
     // but self.view.frame.size doesn't return the correct (actual) width and height 
     // It returns these values inverted i.e. width as height, and vice verse. 
     // The reason is that the view appears to be transformed (90 degrees). 
     // Since there's no work-around this, so for now, I'm just using fixed values. 
     CGSize minTranformSize = CGSizeMake(100.0f, 100.0f); 

     if ((minTranformSize.width > drawingViewSize.width) && (minTranformSize.height > drawingViewSize.height)) { 
      minTranformSize = drawingViewSize; 
     } 

     // Transform the view, provided 
     // 1. It won't scale more than the original size of the background image 
     // 2. It won't scale less than the minimum possible transform 
     CGSize transformedSize = CGSizeMake(canvas.frame.size.width * [gestureRecognizer scale], 
              canvas.frame.size.height * [gestureRecognizer scale]); 

     if ((transformedSize.width <= drawingViewSize.width) && (transformedSize.height <= drawingViewSize.height) && 
      (transformedSize.width >= minTranformSize.width) && (transformedSize.height >= minTranformSize.height)) { 

      canvas.transform = CGAffineTransformScale([canvas transform], 
                 [gestureRecognizer scale], 
                 [gestureRecognizer scale]); 
     } 

     [gestureRecognizer setScale:1.0]; 

    } else if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) { 

     // Recenter the container view, if required (piece is smaller than the view and it's not aligned) 
     CGSize viewSize = self.view.bounds.size; 

     if ((canvas.frame.size.width < viewSize.width) || 
      (canvas.frame.size.height < viewSize.height)) { 

      canvas.center = CGPointMake(viewSize.width/2, viewSize.height/2); 
     } 

     // Adjust the x/y coordinates, if required (piece is larger than the view and it's moving outwards from the view) 
     if (((canvas.frame.origin.x > 0) || (canvas.frame.origin.y > 0)) && 
      ((canvas.frame.size.width >= viewSize.width) && (canvas.frame.size.height >= viewSize.height))) { 

      canvas.frame = CGRectMake(0.0, 
             0.0, 
             canvas.frame.size.width, 
             canvas.frame.size.height); 
     } 

     canvas.frame = CGRectIntegral(canvas.frame); 
    } 
} 

Codice Disegno

- (void)draw { 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSaveGState(context); 

    if (self.fillColor) { 
     [self.fillColor setFill]; 
     [self.path fill]; 
    } 

    if ([self.strokeColor isEqual:[UIColor clearColor]]) { 
     [self.path strokeWithBlendMode:kCGBlendModeClear alpha:1.0]; 

    } else if (self.strokeColor) { 
     [self.strokeColor setStroke]; 
     [self.path stroke]; 
    } 

    CGContextRestoreGState(context); 
} 

risposta

4

Questo è un problema piuttosto complicato, che ho lottato molto con.

Ho finito per convertire i disegni in vettoriale.

  1. disegnare tutte le linee in un livello, disegnare tutti i riempimenti in un altro.
  2. convertire i disegni di Vector, utilizzando Potrace (http://potrace.sourceforge.net/)
  3. disegnare il vettore utilizzando SVGKit (https://github.com/SVGKit/SVGKit) e nascondere il livello disegnato in 1)

Si sta lavorando abbastanza bene e abbastanza veloce, ma richiede molto lavoro. Abbiamo un'applicazione nella nostra azienda che applica questa tecnica:

https://itunes.apple.com/us/app/ideal-paint-hd-mormor/id569450492?mt=8.

Se il tuo unico problema è la prestazione, prova a dare un'occhiata a CATiledLayer. (utilizzato anche nell'app menzionata sopra). Aumenterà enormemente le prestazioni (puoi trovare un buon tutorial qui: http://www.cimgf.com/2011/03/01/subduing-catiledlayer/).

Buona fortuna! :)

+0

In effetti, sembra un sacco di lavoro, e mi chiedo che tipo di prestazioni (in termini di tempo e fps) stai ricevendo nella tua applicazione di disegno? – Mustafa

+0

La traccia richiede molto tempo (alcuni secondi), il disegno è invece molto veloce. La nostra strategia è quella di consentire all'utente di disegnare senza tracciare, finché l'utente non sceglie un altro strumento per avviare lo zoom. Quindi mostriamo uno spinner mentre eseguiamo il tracciamento. – EsbenB

0

Prima di tutto si sta trasformando Visualizza questo non è il modo migliore per lo zoom. Il trasferimento può essere utilizzato solo per aumentare o diminuire le dimensioni di UIVew Per lo zoom si può d questo.

1) ottenere ottenere pic dello schermo utilizzando questo codice

UIGraphicsBeginImageContext(self.drawingView.bounds.size); 
CGContextRef context = UIGraphicsGetCurrentContext(); 
//[self.view.layer renderInContext:context]; 
[self.layerContainerView.layer renderInContext:context]; 
UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext(); 
[scaleLabel setHidden:FALSE]; 
return screenShot; 

2) poi metterlo su qualche UIImageView e quindi eseguire zomming su questa immagine

scrollView.userInteractionEnabled=TRUE; 
self.scrollView.minimumZoomScale = 1.000; 
self.scrollView.maximumZoomScale = 30.0f; 
[self centerScrollViewContents]; 
CGFloat newZoomScale = self.scrollView.zoomScale/1.5f; 
newZoomScale = MAX(newZoomScale, self.scrollView.minimumZoomScale); 
[self.scrollView setZoomScale:newZoomScale animated:YES]; 

3) poi di nuovo Imposta ingrandita immagine di sfondo del UIView

questo funziona perfetto per me spero che questo sarà anche funziona per voi

+0

Questo approccio ingrandirà l'immagine usando una tecnica simile a quella che l'OP sta già utilizzando. NON otterrai immagini nitide e chiare semplicemente ingrandendo/ridimensionando le immagini. – EsbenB