2013-06-30 16 views
5

Voglio simulare lo sfondo dell'app "Want" per iPhone, ci sono 3 colori che voglio far scorrere in una vista, diciamo rosso, blu e verde.Come animare il gradiente che si sposta su iOS

Voglio che ci sia un gradiente dal rosso al blu al verde, ogni 1/3 dello schermo, sfumato l'uno nell'altro (gradiente), quindi, voglio che il rosso vada fuori dallo schermo in alto e torni indietro sul fondo. (Vedi foto sotto ...)

L'animazione dovrebbe spostarsi verso l'alto, voglio che il gradiente salga e si riformi nella parte inferiore dello schermo e salga.

Ho provato a utilizzare CAGradientLayer e ad animare la proprietà "colors", ma sembra proprio che tutto si dissolva l'un l'altro, non necessariamente fuori dallo schermo.

Contemplando usando OpenGL, ma non voglio andare così in basso per qualcosa che sembra piuttosto semplice. Qualsiasi esempio di aiuto/codice sarebbe molto apprezzato. Fondamentalmente ho bisogno di aiuto per animare un gradiente usando CoreAnimation/CoreGraphics.

Grazie in anticipo!

enter image description here

enter image description here

enter image description here

risposta

5

Animare la proprietà colors di un CAGradientLayer sarà solo causare una dissolvenza, come hai scoperto. Comunque penso che un gradiente sia la strada da percorrere. Si dovrebbe guardare le seguenti opzioni:

  • animare la proprietà positions così come/invece del colors.
  • la creazione di un livello di sfumatura più grande che contiene il ciclo di animazione completo e animare la sua posizione

La seconda opzione sarà probabilmente dare le migliori prestazioni, come il gradiente non avrà bisogno di essere ricalcolato.

+0

Ok, così ho provato a generare un livello di sfumatura più grande dello schermo (3x l'altezza dello schermo), ed animato sua position.y, e funziona, finché il position.y> schermo origin.y . Creo un altro gradiente e lo posiziono sotto il primo in modo che continui, come si fa a mantenere l'animazione in corso dopo che il livello Gradiente più grande si spegne? Penso solo a creare un CAGradientLayer con un'altezza molto lunga e ad animarne la posizione. Non è necessariamente la risposta, perché può ancora finire. Mi piacerebbe animare per sempre. – Supereid86

+0

Bene, quando arriva a un punto di loop, resetta la posizione verso l'alto (senza animazione) e poi loop di nuovo. – jrturton

+0

Ha funzionato come un fascino. Un commento: avevo bisogno di creare 2 CAGradientLayers, uno rosso-blu-rosso e l'altro rosso-blu-rosso.Ho messo uno sopra l'altro (uno in cima e uno in partenza alla fine del primo), ho animato la posizione di entrambi fino a quando il primo è andato fuori schermo e il secondo era ora all'origine del primo. Ho quindi spostato il primo sotto il secondo senza animazione, e animato di nuovo la posizione. Grazie @jrtuton! – Supereid86

0

Dovresti creare una classe GradientView con la sottoclasse di UIView. Aggiungi un array per contenere i colori che stai attraversando. La scelta è importante e io wrote an article spiegando il perché. Sovrascrivere il drawRect (rect: CGRect) metodo ed interpolare tra i componenti dei colori:

override func drawRect(rect: CGRect) { 

    let context = UIGraphicsGetCurrentContext(); 
    CGContextSaveGState(context); 

    let c1 = colors[index == 0 ? (colors.count - 1) : index - 1] // previous 
    let c2 = colors[index]          // current 
    let c3 = colors[index == (colors.count - 1) ? 0 : index + 1] // next 

    var c1Comp = CGColorGetComponents(c1.CGColor) 
    var c2Comp = CGColorGetComponents(c2.CGColor) 
    var c3Comp = CGColorGetComponents(c3.CGColor) 

    var colorComponents = [ 
     c1Comp[0] * (1 - factor) + c2Comp[0] * factor, // color 1 and 2 
     c1Comp[1] * (1 - factor) + c2Comp[1] * factor, 
     c1Comp[2] * (1 - factor) + c2Comp[2] * factor, 
     c1Comp[3] * (1 - factor) + c2Comp[3] * factor, 
     c2Comp[0] * (1 - factor) + c3Comp[0] * factor, // color 2 and 3 
     c2Comp[1] * (1 - factor) + c3Comp[1] * factor, 
     c2Comp[2] * (1 - factor) + c3Comp[2] * factor, 
     c2Comp[3] * (1 - factor) + c3Comp[3] * factor  
    ] 

    let gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), &colorComponents, [0.0, 1.0], 2) 

    let startPoint = CGPoint(x: 0.0, y: 0.0) 
    let endPoint = CGPoint(x: rect.size.width, y: rect.size.height) 
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, CGGradientDrawingOptions.DrawsAfterEndLocation) 

    CGContextRestoreGState(context); 
} 

La variabile indice inizia da 0 e avvolge la matrice colori, mentre il fattore è compreso tra 0,0 e 1,0 e anima attraverso un timer:

var index: Int = 0 
var factor: CGFloat = 1.0 
var timer: NSTimer? 

func animateToNextGradient() { 
    index = (index + 1) % colors.count 
    self.setNeedsDisplay() 
    self.factor = 0.0  
    self.timer = NSTimer.scheduledTimerWithTimeInterval(1.0/60.0, target: self, selector: "animate:", userInfo: nil, repeats: true) 

} 

func animate(timer: NSTimer) { 
    self.factor += 0.02 
    if(self.factor > 1.0) { 
     self.timer?.invalidate() 
    } 
    self.setNeedsDisplay() 
} 
+1

Questo non sembra animare il gradiente come richiesto, ho cercato la tua app speedo e l'animazione è geniale, come hai fatto a farlo se posso? – DrPatience

+1

Ho aggiunto un post dopo la tua domanda sul mio blog con qualche codice di accompagnamento. Per favore guarda se è quello che vuoi http://karmadust.com/animating-a-gradient-in-a-uiview/ –

+0

@MikeM Quel link non funziona più, ne hai un altro? –

Problemi correlati