马黑黑 发表于 2022-3-8 19:52

JS请求动画之requestAnimationFrame运用举例

本帖最后由 马黑黑 于 2022-3-8 23:28 编辑

JS之requestAnimationFrame运用举例 | 马黑黑

requestAnimationFrame,字面含义是请求动画帧,这是利用屏幕刷新行为而开发的对接显卡和监视器的API接口,理论上不占用系统内存和CPU资源,但要运行于GPU主线程之上,若主线程十分繁忙,动画运行效果可能不会理想。

requestAnimationFrame() 需要一个参数,比如自定义函数,语法如下:

window.requestAnimationFrame(go);

下面通过实例来领略 requestAnimationFrame 如何运行动画。我们要达成的目标是模拟marquee左右移动文字,为了实现这个动画,我们需要两个div盒子,一个是父盒子,负责提供运动场地,一个子盒子即运动员。先看CSS代码:

<style>
#paBox {
      margin: auto;
      width: 600px;
      position: relative;
}
#marq {
      width: 100px;
      height: 20px;
      line-height: 20px;
      position: relative;
}
</style>

值得注意的是:① 移动需要定位,所以两个盒子都有position设置;② 父盒子的宽度必须大于子盒子的宽度;③ 我们用 # 号定义CSS选择器,它是基于id而定义的,是HTML里同一页只能用一次的标签标识。

下面看HTML代码,很简单,无需解释:

<div id="paBox">
      <div id="marq">花潮论坛</div>
</div>

接着就是JS代码了,这是动画实现的核心内容:

<script>

var paBox = document.getElementById('paBox'); //父盒子句柄
var marq = document.getElementById('marq'); //移动盒子句柄
var xx = 0; //移动初始位置: 元素left值
var speed = 1; //移动速度: 数字越大越快
//移动函数
function go(){
      xx += speed; //位置变更
      //xx即元素left值大于等于父盒子减去自身宽度或 小于等于0时 speed 变为负值
      if (xx >= paBox.clientWidth - marq.clientWidth || xx <= 0) speed = -speed;
      marq.style.left = xx + 'px'; //令对象移动:其实是改变对象的left值
      window.requestAnimationFrame(go); //请求动画
}
window.requestAnimationFrame(go); //首次启动动画

</script>

go()函数中并没有使用定时器,而是通过 requestAnimationFrame() 来调用自己,这是非常精巧的设计,当然,第一推动力需要“上帝之手”,所以在JS语句流中要启动一次动画,然后动画就能持久地运行下去,直至浏览器关闭。这是不是传说中的永动机呢?

go()函数中的算法也值得细细体会:if语句里,|| 表示“或者”的意思,就是说,当 xx 的值大于等于特定值或小于等于0之时,speed 都要变为负数,这样,自左向右移动时 xx 值是没执行一次动画就自动增加的,反之是自动减少的。顺便提一下,若需要不同的运动宽度或范围,可以直接修改if语句,直接设定大于等于和小于等于后面的值即可。如果需要文字只是一个方向移动,则需要修改子盒子的left值和JS代码里go函数的if语句,这里暂时不提,会在后续的回复中进行探讨。

最后再强调一下:两个盒子都必须设定position值,一般建议使用relative和absolute。设定position的原因是JS是通过改变对象的left值来达成移动的目的,而元素不定位就会处于永远静止的状态。

红影 发表于 2022-3-8 20:27

xx += speed; //位置变更

speed不是速度么,为什么这个语句成了位置变更?

小辣椒 发表于 2022-3-8 20:32

看不懂,学习一下{:4_187:}

红影 发表于 2022-3-8 20:46

去试了一下,原来是来回移动的。var speed = 1,可以是小数么?

马黑黑 发表于 2022-3-8 21:18

红影 发表于 2022-3-8 20:46
去试了一下,原来是来回移动的。var speed = 1,可以是小数么?

可以试试,但不建议,移动可能会比较缓慢。一个像素一个像素移动已经不错了。

东篱闲人 发表于 2022-3-8 21:20

这个黑客是真黑啊,一点看不懂。。。{:5_158:}

红影 发表于 2022-3-8 22:41

马黑黑 发表于 2022-3-8 21:18
可以试试,但不建议,移动可能会比较缓慢。一个像素一个像素移动已经不错了。

嗯嗯,尤其父元素比较大的时候,太慢的移动会时间更长。

马黑黑 发表于 2022-3-8 23:09

红影 发表于 2022-3-8 22:41
嗯嗯,尤其父元素比较大的时候,太慢的移动会时间更长。

正解

马黑黑 发表于 2022-3-8 23:10

红影 发表于 2022-3-8 20:27
xx += speed; //位置变更

speed不是速度么,为什么这个语句成了位置变更?

xx变更,不是speed,我这里是把speed加到了xx的值,xx是改变移动对象的依据,它不变更对象就不能移动

马黑黑 发表于 2022-3-8 23:26

东篱闲人 发表于 2022-3-8 21:20
这个黑客是真黑啊,一点看不懂。。。

{:5_108:}

加林森 发表于 2022-3-9 09:59

继续来学习

红影 发表于 2022-3-9 10:56

马黑黑 发表于 2022-3-8 23:10
xx变更,不是speed,我这里是把speed加到了xx的值,xx是改变移动对象的依据,它不变更对象就不能移动

xx必须变化这个知道,为什么要用速度去加,我的理解,速度是有单位的,不是纯粹的数值。

马黑黑 发表于 2022-3-9 11:23

本帖最后由 马黑黑 于 2022-3-9 11:24 编辑

红影 发表于 2022-3-9 10:56
xx必须变化这个知道,为什么要用速度去加,我的理解,速度是有单位的,不是纯粹的数值。
这里,JS定义的speed变量,是一个数值变量,不带单位,不要理解为生活中的速度。

JS要操作实体HTML元素,比如改变其 left 值,先给数值,再给单位。下面语句假如盒子的操作句柄是 c :

var k = c.clientLeft || 0; //获取元素的left值:若获取不到则设定为 0
c.style.left = k + 100 + "px";

上面,先获取HTML特定元素的 left 值,然后赋值给元素的CSS样式设定,k+100 是在原 left 值基础上再加 100,单位是像素,所以后面要给上 + "px" 的内容,因为CSS需要这样表达才能生效。

红影 发表于 2022-3-9 13:16

马黑黑 发表于 2022-3-9 11:23
这里,JS定义的speed变量,是一个数值变量,不带单位,不要理解为生活中的速度。

JS要操作实体HTML元 ...

“不要理解为生活中的速度”

嗯嗯,现在明白了。谢谢黑黑{:4_187:}

马黑黑 发表于 2022-3-9 14:02

红影 发表于 2022-3-9 13:16
“不要理解为生活中的速度”

嗯嗯,现在明白了。谢谢黑黑

{:5_108:}
页: [1]
查看完整版本: JS请求动画之requestAnimationFrame运用举例