当前位置: 首页 > news >正文

在WebGL中创建动画

前言

在搭建WebGL开发环境中介绍了如何开始使用webgl进行绘制。
本篇文章介绍如何在WebGL中创建动画

动画的定义

动画是一种通过快速显示一系列图像(或帧)模拟运动的技术。

动画的分类

网页上的动画基本分为三类:

  • 声明式动画,如CSS动画和SVG动画,这类动画不需要js的介入,用户只需要说明元素如何运动,不需要定义每帧的内容
  • 基于脚本的动画,这种动画每一帧的执行都是靠js来控制的,这类动画包括
    • 通过更新DOM元素的样式对象
    • 在HTML5 2D画布上绘制对象
    • 通过WebGL来绘制对象,这也是本篇文章的重点
  • 基于文件的动画,这类动画的每帧内容包含在文件中,比如GIF动画,比如Flash动画。在浏览器中使用这种动画可能需要相应的插件。

WebGL使用动画

抛开技术不谈,我们先梳理一下使用webgl技术怎么实现一个动画,比如最简单的,让一个点移动,过程如下:

  1. 清空画布
  2. 上传顶点的位置
  3. 绘制顶点,到这一步,顶点并没有移动
  4. 我们需要经过一帧的时间,然后
  5. 再次清空画布
  6. 修改顶点的位置并上传,
  7. 重新绘制顶点

只要我们每一帧的时间足够短,我们就能看到一个点在画布上运动。

setInterval()

说明

setInterval()方法重复调用一个函数或执行一个代码片段,在每次调用之间具有固定的时间间隔。

定义

var intervalID = setInterval(func, [delay, arg1, arg2, ...]);

参数

  • func: 要重复调用的函数,每经过指定 delay 毫秒后执行一次。第一次调用发生在 delay 毫秒之后。
  • delay: 是每次延迟的毫秒数(一秒等于 1000 毫秒),函数的每次调用会在该延迟之后发生。如果未指定,则其默认值为 0,也就是每个事件循环都会执行一次
  • arg: 可选参数,当计时结束的时候,将被传递给 func 函数的附加参数。

返回值

它返回一个 interval ID,该 ID 唯一地标识时间间隔,因此你可以稍后通过调用 clearInterval() 来移除定时器。

setTimeout()

说明

setTimeout() 方法设置一个定时器,一旦定时器到期,就会执行一个函数或指定的代码片段。

定义

setTimeout(func, delay, arg1, arg2, /* … ,*/ argN)

参数

  • func: 经过指定 delay 毫秒后执行的函数。
  • delay: 定时器在执行指定的函数或代码之前应该等待的时间,单位是毫秒。如果省略该参数,则使用值 0,意味着“立即”执行,或者更准确地说,在下一个事件循环执行。
  • arg:附加参数,一旦定时器到期,它们会作为参数传递给 func指定的函数。

返回值

返回值 timeoutID 是一个正整数,表示由 setTimeout() 调用创建的定时器的编号。这个值可以传递给 clearTimeout() 来取消该定时器。

requestAnimationFrame

虽然Web开发人员很久以前就可以用setInterval和setTimeout函数创建动画,但是最近人们推荐另一种实现基于脚本的动画的方式。
requestAnimationFrame,与setInterval和setTimeout函数一样,后者也是HTML DOM窗口对象的一部分

requestAnimationFrame是一个全局函数,是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘,让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

关于requestAnimationFrame,需要注意一下几点:

  • requestAnimationFrame() 是一次性的,也就是说你使用接口后,浏览器会在下一次刷新时调用你传进去的回调函数,但是只有一次有效,若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用 requestAnimationFrame()
  • requestAnimationFrame的刷新频率是通过浏览器来控制的,而浏览器的刷新频率就是最佳刷新频率。
  • 浏览器也可以减速更新或暂停更新在某个不可见选项卡中正在运行的动画。这样,用这个方法不仅可以改善动画的性能,还可以节省电能,后者对于移动设备尤为重要。电池寿命通常是移动设备的一个重要因素。

定义

requestAnimationFrame(callback)

参数

callback:当你的动画需要更新时,为下一次重绘所调用的函数。该回调函数会传入一个参数,表示 requestAnimationFrame() 开始执行回调函数的时间戳。
注意:在同一个帧中的多个回调函数,它们每一个都会接受到一个相同的时间戳,即使在计算上一个回调函数的工作负载期间已经消耗了一些时间。该时间戳是一个十进制数,单位为毫秒,最小精度为 1ms

返回值

一个long整数,请求 ID,是回调列表中唯一的标识。是个非零值,没有别的意义。你可以传这个值给window.cancelAnimationFrame() 以取消回调函数请求。

下面是一个使用requestAnimationFrame设置动画的例子

// 所有动画回调的集合
var animCallbacks=new Array();/*** 设置刷新* @param {*} fps 刷新率* @param {*} updateCallback 回调函数,处理每帧的逻辑 */
function setUpdate(fps,updateCallback)
{updateCallback.interval = 1000/fps;updateCallback.lastTime = undefined;animCallbacks.push(updateCallback);if(animCallbacks.length==1){tick();}
}/*** 时钟,用于确定是否需要刷新*/
function tick(timeStamp)
{requestAnimationFrame(tick.bind(this));animCallbacks.forEach(callback => {if(!callback){return;}if(callback.lastTime == undefined){callback.lastTime = timeStamp;}if(timeStamp && timeStamp - callback.lastTime>=callback.interval){callback.lastTime = timeStamp;callback();}});
}

完整代码已上传gitlab

相关文章:

  • 使用PySpark处理DataFrame以拆分数组列
  • 2024美赛数学建模C题思路分析 - 网球的动量
  • 【考研408】计算机网络笔记
  • Centos8保姆级安装教程
  • 过年手机推荐
  • day32 买卖股票的最佳时机Ⅱ 跳跃游戏 跳跃游戏Ⅱ
  • springboot jar包编写启动start.sh
  • AI新宠Arc浏览器真可以取代Chrome吗?
  • C#入门及进阶教程|C#基本语法(五):控制台应用程序与格式化输出
  • 【NTN 卫星通信】TN 和 NTN的Inter-PLMN应用场景
  • 【Django】Cookie和Session的使用
  • python将.db数据库文件转成Excel文档
  • VCG 网格中点细分
  • VMware虚拟机安装macOS
  • 政安晨:示例演绎Python语言的字符串与字典
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Git学习与使用心得(1)—— 初始化
  • HTTP那些事
  • HTTP中GET与POST的区别 99%的错误认识
  • Laravel Telescope:优雅的应用调试工具
  • sessionStorage和localStorage
  • Tornado学习笔记(1)
  • 给Prometheus造假数据的方法
  • 首页查询功能的一次实现过程
  • 小程序01:wepy框架整合iview webapp UI
  • ​Java并发新构件之Exchanger
  • #Linux(make工具和makefile文件以及makefile语法)
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (过滤器)Filter和(监听器)listener
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (学习日记)2024.01.09
  • (一)基于IDEA的JAVA基础1
  • (转)Mysql的优化设置
  • .NET MVC 验证码
  • .NET 回调、接口回调、 委托
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .net反编译工具
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .NET中使用Protobuffer 实现序列化和反序列化
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • [2024] 十大免费电脑数据恢复软件——轻松恢复电脑上已删除文件
  • [BUG]vscode插件live server无法自动打开浏览器
  • [C#7] 1.Tuples(元组)
  • [codevs 2822] 爱在心中 【tarjan 算法】
  • [Excel VBA]单元格区域引用方式的小结
  • [FT]chatglm2微调
  • [iOS开发]iOS中TabBar中间按钮凸起的实现
  • [JavaScript] JavaScript事件注册,事件委托,冒泡,捕获,事件流
  • [LeetCode] Minimum Path Sum