Swift 在iOS应用程序中使用计时器和循环平滑动画

Swift 在iOS应用程序中使用计时器和循环平滑动画,swift,animation,timer,grand-central-dispatch,Swift,Animation,Timer,Grand Central Dispatch,我有一个具有星星评级的ViewController,看起来像这样(除了有10颗星星) 当用户为一些没有评级的对象打开ViewController时,我想用非常简单的方法将用户的注意力指向这些星星:设置星星高亮显示的动画(当每个字母一个接一个高亮显示时,在现实世界中的一些广告上可以看到这种行为) 一颗星突出显示 两颗星突出显示 三颗星突出显示 把它们都关掉 所以我就是这样做的 func delayWithSeconds(_ seconds: Double, completion: @escap

我有一个具有星星评级的ViewController,看起来像这样(除了有10颗星星)

当用户为一些没有评级的对象打开ViewController时,我想用非常简单的方法将用户的注意力指向这些星星:设置星星高亮显示的动画(当每个字母一个接一个高亮显示时,在现实世界中的一些广告上可以看到这种行为)

  • 一颗星突出显示
  • 两颗星突出显示
  • 三颗星突出显示
  • 把它们都关掉
  • 所以我就是这样做的

    func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
        DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
            completion()
        }
    } 
    
    func ratingStarsAnimation() {
        for i in 1...11 {
            var timer : Double = 0.6 + Double(i)*0.12
            delayWithSeconds(timer) {
                ratingStars.rating = (i < 10) ? Double(i) : 0
            }
        }
    }
    
    func delayWithSeconds(u0; seconds:Double,completion:@escaping()->()){
    DispatchQueue.main.asyncAfter(截止日期:.now()+秒){
    完成()
    }
    } 
    功能分级开始模拟(){
    因为我在1…11{
    无功定时器:双精度=0.6+双精度(i)*0.12
    延时秒(计时器){
    评级星级=(i<10)?双(i):0
    }
    }
    }
    
    这是怎么回事?我有一个名为delayWithSeconds的函数来延迟操作,我使用这个函数来延迟每个星号的高亮显示。0.6是动画开始前的初始延迟。高亮显示所有星星后-最后一步是关闭所有星星的高亮显示。 这个代码可以工作,但我不能说它是平滑的

    我的问题是:

  • 如何更改0.6+双精度(I)*0.12以获得平滑的动画效果
  • 我认为我的延迟解决方案不好——如何才能更好地解决任务

  • 看看CADisplaylink类。它是一个专门的计时器,与屏幕的刷新率相关联,在iOS上是60fps。 它是许多第三方动画库的主干

    用法示例:

    var displayLink: CADisplayLink?
    let start: Double = 0
    let end: Double = 10
    let duration: CFTimeInterval = 5 // seconds
    var startTime: CFTimeInterval = 0
    
    let ratingStars = RatingView()
    
    func create() {
        displayLink = CADisplayLink(target: self, selector: #selector(tick))
        displayLink?.add(to: .main, forMode: .defaultRunLoopMode)
    }
    
    func tick() {
        guard let link = displayLink else {
            cleanup()
            return
        }
    
        if startTime == 0 { // first tick
            startTime = link.timestamp
            return
        }
    
        let maxTime = startTime + duration
        let currentTime = link.timestamp
    
        guard currentTime < maxTime else {
            finish()
            return
        }
    
        // Add math here to ease the animation
    
        let progress = (currentTime - startTime) / duration
        let progressInterval = (end - start) * Double(progress)
    
        // get value =~ 0...10
        let normalizedProgress = start + progressInterval
    
    
        ratingStars.rating = normalizedProgress
    }
    
    func finish() {
        ratingStars.rating = 0
        cleanup()
    }
    
    func cleanup() {
        displayLink?.remove(from: .main, forMode: .defaultRunLoopMode)
        displayLink = nil
        startTime = 0
    }
    
    var displayLink:CADisplayLink?
    让我们开始:Double=0
    让结束:双=10
    let持续时间:CFTimeInterval=5//s
    var startTime:CFTimeInterval=0
    让ratingStars=RatingView()
    func create(){
    displayLink=CADisplayLink(目标:自身,选择器:#选择器(勾号))
    displayLink?.add(添加到:.main,forMode:.defaultRunLoopMode)
    }
    func tick(){
    guard let link=displayLink else{
    清理()
    返回
    }
    如果startTime==0{//第一个勾号
    startTime=link.timestamp
    返回
    }
    设maxTime=startTime+持续时间
    让currentTime=link.timestamp
    保护currentTime
    首先,这将使动画更加平滑。如果你想添加缓和,你仍然需要添加一些三角函数,但这应该不会太难

    • CADisplaylink:

    • 缓和曲线:


    看看CADisplaylink类。它是一个专门的计时器,与屏幕的刷新率相关联,在iOS上是60fps。 它是许多第三方动画库的主干

    用法示例:

    var displayLink: CADisplayLink?
    let start: Double = 0
    let end: Double = 10
    let duration: CFTimeInterval = 5 // seconds
    var startTime: CFTimeInterval = 0
    
    let ratingStars = RatingView()
    
    func create() {
        displayLink = CADisplayLink(target: self, selector: #selector(tick))
        displayLink?.add(to: .main, forMode: .defaultRunLoopMode)
    }
    
    func tick() {
        guard let link = displayLink else {
            cleanup()
            return
        }
    
        if startTime == 0 { // first tick
            startTime = link.timestamp
            return
        }
    
        let maxTime = startTime + duration
        let currentTime = link.timestamp
    
        guard currentTime < maxTime else {
            finish()
            return
        }
    
        // Add math here to ease the animation
    
        let progress = (currentTime - startTime) / duration
        let progressInterval = (end - start) * Double(progress)
    
        // get value =~ 0...10
        let normalizedProgress = start + progressInterval
    
    
        ratingStars.rating = normalizedProgress
    }
    
    func finish() {
        ratingStars.rating = 0
        cleanup()
    }
    
    func cleanup() {
        displayLink?.remove(from: .main, forMode: .defaultRunLoopMode)
        displayLink = nil
        startTime = 0
    }
    
    var displayLink:CADisplayLink?
    让我们开始:Double=0
    让结束:双=10
    let持续时间:CFTimeInterval=5//s
    var startTime:CFTimeInterval=0
    让ratingStars=RatingView()
    func create(){
    displayLink=CADisplayLink(目标:自身,选择器:#选择器(勾号))
    displayLink?.add(添加到:.main,forMode:.defaultRunLoopMode)
    }
    func tick(){
    guard let link=displayLink else{
    清理()
    返回
    }
    如果startTime==0{//第一个勾号
    startTime=link.timestamp
    返回
    }
    设maxTime=startTime+持续时间
    让currentTime=link.timestamp
    保护currentTime
    首先,这将使动画更加平滑。如果你想添加缓和,你仍然需要添加一些三角函数,但这应该不会太难

    • CADisplaylink:

    • 缓和曲线:


    你能展示你迄今为止已经完成的动画和你想要的动画吗?我如何展示?通过dropBox分享视频。我将制作你想要的任何类型的动画。现在,如果你看大字(L&R),我只能向你展示接近所需动画的节奏示例-你可以看到它们以非线性方式突出显示,从慢到快,你可以显示你迄今为止所取得的动画和你想要的动画。我如何显示它?通过dropBox共享视频。我将制作你想要的任何类型的动画。现在,我只能向你展示接近所需动画的节奏示例-如果你看的话在大号字母(L&R)上,您可以看到它们以非线性方式从慢到快高亮显示