# requestAnimationFrame(callback)

在下一次重绘之前,调用用户提供的回调函数

参数

名称 类型 必填
callback (timestamp: number) => void

返回值

类型
number

兼容性 ?

uni-app x 兼容性

Web Android iOS HarmonyOS Android(VDOM) UTS 插件 iOS(VDOM) UTS 插件
4.0 4.25 4.25 4.61 4.25 x

uni-app 兼容性

Android(VDOM) UTS 插件 iOS UTS 插件
x x

参见

相关 Bug

# cancelAnimationFrame(taskId)

取消一个先前通过调用 requestAnimationFrame() 方法添加到计划中的动画帧请求

参数

名称 类型 必填
taskId number

返回值

类型
void

兼容性 ?

uni-app x 兼容性

Web Android iOS HarmonyOS Android(VDOM) UTS 插件 iOS(VDOM) UTS 插件
4.0 4.25 4.25 4.61 4.25 x

uni-app 兼容性

Android(VDOM) UTS 插件 iOS UTS 插件
x x

参见

相关 Bug

# 示例

示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见

扫码体验(手机浏览器跳转到App直达页)

示例

<template>
  <view class="page">
    <page-head :title="data.title"></page-head>
    <button @click="startRequestAnimationFrame">requestAnimationFrame</button>
    <button @click="stopRequestAnimationFrame">cancelAnimationFrame</button>
    <text class="frame-count">FPS: {{data.FPSString}}</text>
    <text class="frame-count">FrameCount: {{data.testFrameCount}}</text>
    <text class="tips">提示: 重复点击会忽略重复启动,避免创建多个并行的 requestAnimationFrame 循环</text>
  </view>
</template>

<script setup lang="uts">
  type DataType = {
    title: string;
    taskId: number;
    isRunning: boolean;
    FPSString: string;
    lastTime: number;
    frameCount: number;
    testFrameCount: number;
  }

  const initialData: DataType = {
    title: 'AnimationFrame',
    taskId: 0,
    isRunning: false,
    FPSString: '- / -ms',
    lastTime: 0,
    frameCount: 0,
    testFrameCount: 0
  }

  const data = reactive<DataType>(initialData)

  const updateFPS = (timestamp : number) => {
    data.frameCount++
    if (timestamp - data.lastTime >= 1000) {
      const timeOfFrame = (1000 / data.frameCount)
      data.FPSString = `${data.frameCount} / ${timeOfFrame.toFixed(3)}ms`
      data.frameCount = 0
      data.lastTime = timestamp
    }
  }

  type RunAnimationFrameType = (timestamp : number) => void
  let runAnimationFrame: RunAnimationFrameType = (timestamp : number) => {}
  runAnimationFrame = (timestamp : number) => {
    if (!data.isRunning) {
      return
    }
    updateFPS(timestamp)
    data.testFrameCount++
    data.taskId = requestAnimationFrame(runAnimationFrame)
  }

  type StartRequestAnimationFrameType = () => void
  let startRequestAnimationFrame: StartRequestAnimationFrameType = () => {}
  startRequestAnimationFrame = () => {
    if (data.isRunning) {
      return
    }
    data.isRunning = true
    data.taskId = requestAnimationFrame(runAnimationFrame)
  }

  const stopRequestAnimationFrame = () => {
    if (data.taskId > 0) {
      cancelAnimationFrame(data.taskId)
    }
    data.taskId = 0
    data.isRunning = false
    data.lastTime = 0
    data.frameCount = 0
    data.testFrameCount = 0
    data.FPSString = '- / -ms'
  }

  onUnload(() => {
    if (data.taskId > 0) {
      stopRequestAnimationFrame()
    }
  })

  defineExpose({
    data,
    startRequestAnimationFrame,
    stopRequestAnimationFrame
  })
</script>

<style>
  .page {
    padding: 15px;
  }

  .frame-count {
    margin-top: 15px;
  }

  .tips {
    font-size: 12px;
    margin-top: 30px;
    opacity: 0.7;
  }
</style>

提示

  • requestAnimationFrame/cancelAnimationFrame 为全局 API,如果需要跨平台处理 canvas 动画应使用 uni.createCanvasContextAsync
  • Android uni-app x requestAnimationframe 目前仅支持有参数callback,示例:requestAnimationFrame((timestamp : number) => {})