Iphone 如何在iOS上设置渐变向上移动的动画

Iphone 如何在iOS上设置渐变向上移动的动画,iphone,ios,core-animation,core-graphics,Iphone,Ios,Core Animation,Core Graphics,我想模仿“想要”的iPhone应用程序背景,有3种颜色我想让视图循环,比如红色、蓝色和绿色 我希望有一个渐变,从红色到蓝色再到绿色,每1/3的屏幕,相互淡入(渐变),然后,我希望红色在顶部离开屏幕,在底部返回。(见下图……) 动画应该向上移动,我希望渐变向上,并在屏幕底部进行改造,然后向上移动 我试着使用CAGradientLayer并设置“colors”属性的动画,但看起来一切都会相互淡入,不一定会离开屏幕 考虑使用OpenGL,但不想为了一些看起来很简单的东西而降低成本。如有任何帮助/代码示

我想模仿“想要”的iPhone应用程序背景,有3种颜色我想让视图循环,比如红色、蓝色和绿色

我希望有一个渐变,从红色到蓝色再到绿色,每1/3的屏幕,相互淡入(渐变),然后,我希望红色在顶部离开屏幕,在底部返回。(见下图……)

动画应该向上移动,我希望渐变向上,并在屏幕底部进行改造,然后向上移动

我试着使用CAGradientLayer并设置“colors”属性的动画,但看起来一切都会相互淡入,不一定会离开屏幕

考虑使用OpenGL,但不想为了一些看起来很简单的东西而降低成本。如有任何帮助/代码示例,将不胜感激。我基本上需要帮助使用CoreAnimation/CoreGraphics设置渐变动画

提前谢谢


如您所发现的,为CAGradientLayer的
颜色设置动画只会导致褪色。然而,我认为梯度层是最好的选择。您应该查看以下选项:

  • 设置
    位置
    属性以及/而不是
    颜色
    的动画
  • 创建包含完整动画循环的较大渐变层并设置其位置动画

第二个选项可能会提供最佳性能,因为梯度不需要重新计算

您应该将UIView子类化以创建GradientView类。添加一个数组以保存正在移动的颜色。选择很重要,我会解释原因。替代drawRect(rect:CGRect)方法并在颜色的组件之间插值:

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);
}
索引变量从0开始,在因子介于0.0和1.0之间时环绕颜色数组,并通过计时器设置动画:

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()
}

好的,所以我试着创建一个比屏幕大的渐变层(屏幕高度的3倍),并为它的位置.y设置动画,直到位置.y>屏幕原点.y。我是否要创建另一个渐变并将其放置在第一个渐变下,以便继续,在较大的渐变层离开屏幕后,如何保持动画继续?我认为仅仅创建一个具有超长高度的CAGradientLayer并设置其位置的动画。y不一定是答案,因为它最终还是可以结束的。我希望它永远有动画效果。好吧,当它到达一个循环点时,你可以将位置重置到顶部(没有动画),然后再次循环。效果很好。一条评论——我需要创建两个CAGradientLayers,一个红-蓝-红,另一个红-蓝-红。我把一个放在另一个的上面(一个在上面,一个从第一个结尾开始),我设置了两个的位置.y的动画,直到第一个离开屏幕,第二个现在在第一个的原点。然后,我在没有动画的情况下将第一个移动到第二个下,并再次设置位置.y的动画。谢谢@jrtuton!这似乎没有按照要求设置渐变动画,我查看了你的speedo应用程序,动画非常出色,如果可以的话,你是如何做到的?我在我的博客上添加了一篇帖子,其中包含一些配套代码。请看一看,如果是你想要的@MikeM链接不再工作,你有其他链接吗?这里是更新的链接