如何计算Web动画帧率FPS

目录
  • 流畅动画的标准
  • 法一:借助 Chrome 开发者工具
  • 法二:借助 Frame Timing API
    • Blink 内核早期架构
    • JS 动画与 CSS 动画的细微区别
    • 什么是 Frame Timing API ?
    • Frame Timing API 示意
  • 法三:借助 requestAnimationFrame API
    • 使用 requestAnimationFrame 计算 FPS 原理

流畅动画的标准

首先,理清一些概念。FPS 表示的是每秒钟画面更新次数。我们平时所看到的连续画面都是由一幅幅静止画面组成的,每幅画面称为一帧,FPS 是描述“帧”变化速度的物理量。

理论上说,FPS 越高,动画会越流畅,目前大多数设备的屏幕刷新率为 60 次/秒,所以通常来讲 FPS 为 60 frame/s 时动画效果最好,也就是每帧的消耗时间为 16.67ms。

当然,经常玩 FPS 游戏的朋友肯定知道,吃鸡/CSGO 等 FPS 游戏推荐使用 144HZ 刷新率的显示器,144Hz 显示器特指每秒的刷新率达到 144Hz 的显示器。相较于普通显示器每秒60的刷新速度,画面显示更加流畅。因此144Hz显示器比较适用于视角时常保持高速运动的第一人称射击游戏。

不过,这个只是显示器提供的高刷新率特性,对于我们 Web 动画而言,是否支持还要看浏览器,而大多数浏览器刷新率为 60 次/秒。

直观感受,不同帧率的体验:

  • 帧率能够达到 50 ~ 60 FPS 的动画将会相当流畅,让人倍感舒适;
  • 帧率在 30 ~ 50 FPS 之间的动画,因各人敏感程度不同,舒适度因人而异;
  • 帧率在 30 FPS 以下的动画,让人感觉到明显的卡顿和不适感;
  • 帧率波动很大的动画,亦会使人感觉到卡顿。

OK,那么我们该如何准确的获取我们页面动画当前的 FPS 值呢?

法一:借助 Chrome 开发者工具

Chrome 提供给开发者的功能十分强大,在开发者工具中,我们进行如下选择调出FPS meter选项:

通过这个按钮,可以开启页面实时 Frame Rate (帧率) 观测及页面 GPU 使用率。

缺点:

  • 这个只能一次观测一到几个页面,而且需要人工实时观测
  • 数据只能是主观感受,并没有一个十分精确的数据不断上报或者被收集

因此,我们需要更加智能的方法。

法二:借助 Frame Timing API

在介绍下面这种方法前,继续做一些基础知识的科普。

Blink 内核早期架构

以 Chrome 浏览器内核 Blink 渲染页面为例。对早期的 Chrome 浏览器而言,每个页面 Tab 对应一个独立的 renderer 进程,Renderer 进程中包含了主线程和合成线程。早期 Chrome 内核架构:

其中,主线程主要负责:

  • Javascript 的计算与执行
  • CSS 样式计算
  • Layout 计算
  • 将页面元素绘制成位图(paint),也就是光栅化(Raster)
  • 将位图给合成线程

合成线程则主要负责:

  • 将位图(GraphicsLayer 层)以纹理(texture)的形式上传给 GPU
  • 计算页面的可见部分和即将可见部分(滚动)
  • CSS 动画处理
  • 通知 GPU 绘制位图到屏幕上

OK,云里雾里的,什么东西。其实知道了这两个线程之后,下一个概念是厘清 CSS 动画与 JS 动画的细微区别(当然它们都是 Web 动画)。

JS 动画与 CSS 动画的细微区别

对于 JS 动画而言,它们运行时的帧率即是主线程和合成线程加起来消耗的时间。对于流畅动画而言,我们希望它们每一帧的耗时保持在 16.67ms 之内;

而对于 CSS 动画而言,由于其流程不受主线程的影响,所以希望能得到合成线程的消耗的时间,而合成线程的绘制频率也反映了滚动和 CSS 动画的流程性。

上面主要想得出的一个结论是。如果我们能够知道主线程和合成线程每一帧消耗的时间,那么我们就能大致得出对应的 Web 动画的帧率。那么上面说到的Frame Timing API是否可以帮助我们拿到这个时间点呢。

什么是 Frame Timing API ?

Frame Timing API 是 Web Performance Timing API 标准中的其中一位成员。

Web Performance Timing API是 W3C 推出的一套性能API 标准,用于帮助开发者对网站各方面的性能进行精确的分析与控制,提升 Web 网站性能。

它包含许多子类 API,完成不同的功能,大致如下(摘自使用性能API快速分析web前端性能,当然你也可以看英文原版介绍:Web Performance Timing API):

怎么使用呢?以Navigation Timing, Performance Timeline, Resource Timing为例子,对于兼容它的浏览器,它以只读属性的形式对外暴露挂载在window.performance上。

在调试台 console 中打印window.performance,查看其中的 timing 属性:

这对象内一连串的变量表示什么呢,它表示我们页面整个加载过程中每一个重要的时间点,可以详细看看这张图:

通过这张图以及上面的window.performance.timing,我们就可以轻松的统计出页面每个重要节点的耗时,这就是Web Performance Timing API的强大之处,感兴趣的可以详细去研究研究,使用在页面统计上。

Frame Timing API 示意

好的,终于可以回归正题,借助Web Performance Timing API中的Frame Timing API,可以轻松的拿到每一帧中,主线程以及合成线程的时间。或者更加容易,直接拿到每一帧的耗时。

获取 Render 主线程和合成线程的记录,每条记录包含的信息基本如下,代码示意,(参考至Developer feedback needed: Frame Timing API):

var rendererEvents = window.performance.getEntriesByType("renderer");
var compositeThreadEvents = window.performance.getEntriesByType("composite");

或者是:

var observer = new PerformanceObserver(function(list) {
    var perfEntries = list.getEntries();
    for (var i = 0; i < perfEntries.length; i++) {
        console.log("frame: ", perfEntries[i]);
    }
});

// subscribe to Frame Timing
observer.observe({entryTypes: ['frame']});

每条记录包含的信息基本如下:

{
  sourceFrameNumber: 120,
  startTime: 1342.549374253
  cpuTime: 6.454313323
}

每个记录都包括唯一的 Frame Number、Frame 开始时间以及 cpuTime 时间。通过计算每一条记录的 startTime ,我们就可以算出每两帧间的间隔,从而得到动画的帧率是否能够达到 60 FPS。

不过!看看Web Performance Timing API整体的兼容性:

Frame Timing API 虽好,但是,现在Frame Timing API的兼容性不算很友好,额,不友好到什么程度呢。还没有任何浏览器支持,处于实验性阶段,属于面向未来编程。这你 TM 逗我呢?说了这么久完全不能用.....

法三:借助 requestAnimationFrame API

费了这么多笔墨描述 Frame Timing API 但最后因为兼容性问题完全没办法使用。不过不代表这么长篇幅的描述没有用,从上面的介绍,我们得知,如果我们可以到得到每一帧中的固定一个时间点,那么两者相减,也能够近似得到一帧所消耗的时间。

那么,我们再另辟蹊径。这次,我们借助兼容性不错的 requestAnimationFrame API。

// 语法
window.requestAnimationFrame(callback);

requestAnimationFrame大家应该都不陌生,方法告诉浏览器您希望执行动画并请求浏览器调用指定的函数在下一次重绘之前更新动画。

当你准备好更新屏幕画面时你就应用此方法。这会要求你的动画函数在浏览器下次重绘前执行。回调的次数常是每秒 60 次,大多数浏览器通常匹配 W3C 所建议的刷新率。

使用 requestAnimationFrame 计算 FPS 原理

原理是,正常而言 requestAnimationFrame 这个方法在一秒内会执行 60 次,也就是不掉帧的情况下。假设动画在时间 A 开始执行,在时间 B 结束,耗时 x ms。而中间 requestAnimationFrame 一共执行了 n 次,则此段动画的帧率大致为:n / (B - A)。

核心代码如下,能近似计算每秒页面帧率,以及我们额外记录一个 allFrameCount,用于记录 rAF 的执行次数,用于计算每次动画的帧率 :

var rAF = function () {
    return (
        window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60);
        }
    );
}();

var frame = 0;
var allFrameCount = 0;
var lastTime = Date.now();
var lastFameTime = Date.now();

var loop = function () {
    var now = Date.now();
    var fs = (now - lastFameTime);
    var fps = Math.round(1000 / fs);

    lastFameTime = now;
    // 不置 0,在动画的开头及结尾记录此值的差值算出 FPS
    allFrameCount++;
    frame++;

    if (now > 1000 + lastTime) {
        var fps = Math.round((frame * 1000) / (now - lastTime));
        console.log(`${new Date()} 1S内 FPS:`, fps);
        frame = 0;
        lastTime = now;
    };

    rAF(loop);
}

loop();

OK,寻找一个有动画不断运行的页面进行测试,可以看到代码运行如下:

这里,我使用了我之前制作的一个页面进行了测试,使用 Chrome 同时调出页面的 FPS meter,对比两边的实时 FPS 值,基本吻合。

测试页面,Solar System。你可以将上面的代码贴到这个页面的 console 中,测试一下数据:

对比右上角的 Frame Rate,帧率基本一致。在大部分情况下,这种方法可以很好的得出 Web 动画的帧率。

如果我们需要统计某个特定动画过程的帧率,只需要在动画开始和结尾两处分别记录allFrameCount这个数值大小,再除以中间消耗的时间,也可以得出特定动画过程的 FPS 值。

值得注意的是,这个方法计算的结果和真实的帧率肯定是存在误差的,因为它是将每两次主线程执行 javascript 的时间间隔当成一帧,而非上面说的主线程加合成线程所消耗的时间为一帧。但是对于现阶段而言,算是一种可取的方法。

以上就是如何计算Web动画帧率FPS的详细内容,更多关于计算Web动画帧率FPS的资料请关注我们其它相关文章!

(0)

相关推荐

  • Unity3D基于OnGUI实时显示FPS

    帧率(Frame rate)是用于测量显示帧数的量度.所谓的测量单位为每秒显示帧数(Frames per Second,简称:FPS)或"赫兹"(Hz).此词多用于影视制作和电子游戏.由于人类眼睛的特殊生理结构,如果所看画面之帧率高于16的时候,就会认为是连贯的,此现象称之为视觉暂留. 每秒的帧数(fps)或者说帧率表示图形处理器处理场时每秒钟能够更新的次数.高的帧率可以得到更流畅.更逼真的动画.一般来说30fps就是可以接受的,但是将性能提升至60fps则可以明显提升交互感和逼真感,

  • Android测量每秒帧数Frames Per Second (FPS)的方法

    本文实例讲述了Android测量每秒帧数Frames Per Second (FPS)的方法.分享给大家供大家参考.具体如下: MainThread.java: package net.obviam.droidz; import java.text.DecimalFormat; import android.graphics.Canvas; import android.util.Log; import android.view.SurfaceHolder; /** * @author impa

  • python 读取视频,处理后,实时计算帧数fps的方法

    实时计算每秒的帧数 cap = cv2.VideoCapture("DJI_0008.MOV") #cap = cv2.VideoCapture(0) # Define the codec and create VideoWriter object #fourcc = cv2.cv.FOURCC(*'XVID') fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output1.avi', fourcc, 2

  • Unity OnGUI实时显示游戏FPS

    FPS是什么? FPS (每秒传输帧数(Frames Per Second))[摘自百度百科] FPS是图像领域中的定义,是指画面每秒传输帧数,通俗来讲就是指动画或视频的画面数.FPS是测量用于保存.显示动态视频的信息数量.每秒钟帧数愈多,所显示的动作就会越流畅.通常,要避免动作不流畅的最低是30.某些计算机视频格式,每秒只能提供15帧. FPS"也可以理解为我们常说的"刷新率(单位为Hz)",例如我们常在CS游戏里说的"FPS值".我们在装机选购显卡和显

  • vue实现轮播图帧率播放

    本文实例为大家分享了vue实现轮播图帧率播放的具体代码,供大家参考,具体内容如下 需求 传入一个数组,数组中放的是目录名称,通过本目录名称,读取文件目录下的所有图片,并循环播放,形成一个每1s播放多少张图片的效果,最后目录播放完毕后,在跳到第一个目录循环播放. 核心: 用 webpack的一个API require.contex读取目录下的文件名,具体想了解的可以查一查. 代码 HTML <template> <div id="imgPlay" ref="c

  • 使用python-opencv读取视频,计算视频总帧数及FPS的实现

    如下所示: 1.计算总帧数 import os import cv2 video_cap = cv2.VideoCapture('ffmpeg_test.avi') frame_count = 0 all_frames = [] while(True): ret, frame = video_cap.read() if ret is False: break all_frames.append(frame) frame_count = frame_count + 1 # The value be

  • 如何计算Web动画帧率FPS

    目录 流畅动画的标准 法一:借助 Chrome 开发者工具 法二:借助 Frame Timing API Blink 内核早期架构 JS 动画与 CSS 动画的细微区别 什么是 Frame Timing API ? Frame Timing API 示意 法三:借助 requestAnimationFrame API 使用 requestAnimationFrame 计算 FPS 原理 流畅动画的标准 首先,理清一些概念.FPS 表示的是每秒钟画面更新次数.我们平时所看到的连续画面都是由一幅幅静

  • 详解盒子端CSS动画性能提升

    流畅动画的标准 理论上说,FPS 越高,动画会越流畅,目前大多数设备的屏幕刷新率为 60 次/秒,所以通常来讲 FPS 为 60frame/s 时动画效果最好,也就是每帧的消耗时间为 16.67ms. 直观感受,不同帧率的体验 帧率能够达到 50 - 60 FPS 的动画将会相当流畅,让人倍感舒适: 帧率在 30 - 50 FPS 之间的动画,因各人敏感程度不同,舒适度因人而异: 帧率在 30 FPS 以下的动画,让人感觉到明显的卡顿和不适感: 帧率波动很大的动画,亦会使人感觉到卡顿. 盒子端动

  • 使用requestAnimationFrame实现js动画性能好

    使用requestAnimationFrame实现js动画性能好.先给大家简单介绍下requestAnimationFrame比起setTimeout.setInterval有哪些优势? 示例一: requestAnimationFrame 比起 setTimeout.setInterval的优势主要有两点: 1.requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒6

  • React中常见的动画实现的几种方式

    现在,用户对于前端页面的要求已经不能满足于实现功能,更要有颜值,有趣味.除了整体 UI 的美观,在合适的地方添加合适的动画效果往往比静态页面更具有表现力,达到更自然的效果.比如,一个简单的 loading 动画或者页面切换效果不仅能缓解用户的等待情绪,甚至通过使用品牌 logo 等形式,默默达到品牌宣传的效果. React 作为最近几年比较流行的前端开发框架,提出了虚拟 DOM 概念,所有 DOM 的变化都先发生在虚拟 DOM 上,通过 DOM diff 来分析网页的实际变化,然后反映在真实 D

  • Android Lottie实现中秋月饼变明月动画特效实例

    目录 前言 Lottie 案例尝试 1. 集成依赖 2. 添加 LottieAnimationView 加载网络资源 3. 加载本地资源 4. 循环播放 & 动画监听 5. 暂停 & 继续 & 取消 小扩展 1. 硬件加速器 2. json 文件解析 总结 前言 小菜在 Android 端进行动画处理时主要用的是 Android 自带的三种动画形式,今天小菜简单尝试通过 Airbnb Lottie 展示一个中秋月饼变明月的小动画: Lottie Lottie 动画是 Airbnb

  • 巧妙使用python opencv库玩转视频帧率

    目录 需求背景 关于opencv 安装opencv opencv-python获取视频相关信息 需求背景 在很多时候我们需要抽取视频的某一帧做一些分析或修改等:比如笔者需求就是判断一个人在该视频中出现的频率,以判断他是否是这段视频的主角: 关于opencv OpenCV 是 Intel 开源计算机视觉库 (Computer Version) .它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法. OpenCV 拥有包括 300 多个 C 函数的跨平台的中.高

  • 分析Android Choreographer源码

    一.前言 目前大部分手机都是 60Hz 的刷新率,也就是 16.6ms 刷新一次,系统为了配合屏幕的刷新频率,将 Vsync 的周期也设置为 16.6 ms,每个 16.6 ms , Vsync 信号唤醒 Choreographer 来做 App 的绘制操作,这就是引入 Choreographer 的主要作用.了解 Choreographer 还可以帮助 App 开发者知道程序每一帧运行的基本原理,也可以加深对 Message.Handler.Looper.MessageQueue.Measur

  • Python 音视频剪辑快速入门教程

    目录 一.引言 二.Moviepy 简介 三.Moviepy 安装 四.音视频的加载和保存 五.音视频数据的访问 六.音视频变换 1.Clip 的 fl 方法 2.Clip 的 fl_time 方法 3.剪辑颜色变换 4.剪辑大小变换 5.剪辑内容变换 七.剪辑合成 1.概述 2.将多个剪辑拼接 3.多个剪辑同屏播放 4.将一系列图像构造成视频 5.其他几种生成视频方法简介 八.小结 一.引言 在这个短视频和自媒体大行其道的年代,音视频剪辑成为了大佬们的必备工具,现在有很多音视频剪辑的软件,如剪

  • JavaScript实现字符雨效果

    本文实例为大家分享了JavaScript实现字符雨效果的具体代码,供大家参考,具体内容如下 <html>     <head>         <meta charset="utf8"/>         <title>字符雨</title>         <style>             body {                 color:white;                 backgro

  • 用Python写飞机大战游戏之pygame入门(4):获取鼠标的位置及运动

    目标是拷贝微信的飞机大战,当然拷贝完以后大家就具备自己添加不同内容的能力了. 首先是要拿到一些图片素材,熟悉使用图像处理软件和绘画的人可以自己制作,并没有这项技能的同学只能和我一样从网上下载相应的素材了. 网上可以找到相应的这样的图片,注意,所有的元件图片要是png类型的图片,那样可以有透明的背景,否则会有白色的边框露出来. 找到素材以后我们就要开始搭建我们的飞机大战了. 微信上的飞机大战是由手指控制的,在电脑上,我们就先用鼠标代替了. 按照之前我们在天空上移动云的那个程序,我们可以知道该怎么做

随机推荐