You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS能否实现连续逐帧视图动画?有无web requestAnimationFrame同类接口?

iOS 屏幕刷新率同步逐帧动画实现方案

你需要的对标Web端Window.requestAnimationFrame()的原生逐帧回调能力,是Core Animation框架提供的CADisplayLink,它会在屏幕每一次硬件刷新前触发回调,和系统渲染管线完全同步,比Timer方案的稳定性、流畅度高很多,非常适合实现幸运大转盘这类需要精细控制的惯性动画。

基础使用方式

CADisplayLink需要注册到RunLoop中才能生效,使用时需要注意持有引用、计算真实帧间隔,示例代码如下:

import QuartzCore

// 持有DisplayLink实例,避免被提前释放
private var displayLink: CADisplayLink?
// 记录上一帧时间戳,用于计算真实帧间隔
private var lastFrameTimestamp: CFTimeInterval = 0

func startInertiaAnimation() {
    // 初始化DisplayLink,绑定帧回调
    let link = CADisplayLink(target: self, selector: #selector(handleFrameTick(link:)))
    // 注册到主RunLoop的通用模式,避免滚动其他UI时动画被暂停
    link.add(to: .main, forMode: .common)
    displayLink = link
    lastFrameTimestamp = CACurrentMediaTime()
}

@objc private func handleFrameTick(link: CADisplayLink) {
    // 计算当前帧与上一帧的真实时间差,不要硬编码1/60
    let deltaTime = link.timestamp - lastFrameTimestamp
    lastFrameTimestamp = link.timestamp
    
    // 执行你的逐帧旋转更新逻辑
    tickAnimation(deltaTime: deltaTime)
    
    // 动画结束(转盘停靠到目标位置)后必须手动终止回调
    if isAnimationFinished {
        link.invalidate()
        displayLink = nil
    }
}

对比Timer方案的核心优势

  • 自动适配屏幕刷新率:在支持ProMotion的120Hz高刷屏设备上会自动匹配120fps的回调频率,动画流畅度远高于固定60fps的Timer方案
  • 回调时机精准:回调触发时机和屏幕刷新完全对齐,不会出现Timer受主线程调度影响导致的掉帧、回调堆积问题
  • 时间精度更高:通过内置的时间戳计算得到的帧间隔是真实值,做惯性减速计算时不会因为掉帧出现动画跳变、速度不均的问题,手感更自然

大转盘场景实现注意事项

  • 不要手动修改preferredFramesPerSecond属性,保持默认值0即可自动适配当前设备的最佳刷新率
  • 绝对不要硬编码deltaTime为1/60,否则出现掉帧时转盘旋转速度会突然跳变,惯性效果会非常生硬
  • 动画结束后必须调用invalidate()终止回调,否则DisplayLink会持续持有绑定的target,造成内存泄漏,也会空耗CPU资源
  • 如果需要更真实的物理减速效果,可以配合UIDynamicAnimator自定义物理行为,不过如果要完全自主控制旋转停靠逻辑,CADisplayLink是灵活度最高的选择

内容的提问来源于stack exchange,提问作者sak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:15:41