【问题标题】:How to animate gradient moving up on iOS如何在 iOS 上设置渐变动画
【发布时间】:2013-06-27 12:12:45
【问题描述】:

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

我希望有一个从红色到蓝色到绿色的渐变,每个屏幕的 1/3,相互淡入(渐变),然后,我希望红色从屏幕顶部消失并重新出现底端。 (见下图……)

动画应该向上移动,我希望渐变在屏幕底部向上并重新向上。

我尝试使用 CAGradientLayer 并为“colors”属性设置动画,但这看起来就像一切都相互淡入,不一定会移出屏幕。

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

提前致谢!

【问题讨论】:

    标签: iphone ios core-animation core-graphics


    【解决方案1】:

    如您所见,为 CAGradientLayer 的 colors 属性设置动画只会导致淡入淡出。但是我认为渐变层是要走的路。您应该查看以下选项:

    • 动画positions属性以及/而不是colors。
    • 创建一个更大的渐变层,其中包含您的完整动画循环并为其位置设置动画

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

    【讨论】:

    • 好的,所以我尝试创建一个比屏幕大的渐变层(屏幕高度的 3 倍),并为它的 position.y 设置动画,它可以工作,直到 position.y > screen origin.y。我是否要创建另一个渐变并将其放在第一个渐变之下以便它继续,在较大的渐变层离开屏幕后如何保持动画继续?我认为仅仅创建一个具有超长高度的 CAGradientLayer 并为其 position.y 设置动画并不一定是答案,因为它最终仍然可以结束。我希望它永远动画。
    • 好吧,当它到达一个循环点时,你会将位置重置到顶部(没有动画)然后再次循环。
    • 工作就像一个魅力。一条评论 - 我需要创建 2 个 CAGradientLayers,一个是红蓝红,另一个也是红蓝红。我将一个放在另一个之上(一个在顶部,一个从第一个的末尾开始),我为两者的 position.y 设置动画,直到第一个离开屏幕,第二个现在位于第一个的原点。然后我在没有动画的情况下将第一个移到第二个下面,然后再次为 position.y 设置动画。谢谢@jrtuton!
    【解决方案2】:

    你应该继承 UIView 来创建一个 GradientView 类。添加一个数组来保存您正在移动的颜色。选择很重要,我wrote an article 解释了原因。覆盖 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()
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2019-07-23
    • 1970-01-01
    • 2017-07-25
    相关资源
    最近更新 更多