马黑黑 发表于 2022-8-5 12:59

气球平滑移动的两种实现方式(附代码)

<style>
#papa {
        margin: auto;
        width: 740px;
        height: 660px;
        box-shadow: 3px 3px 24px #000;
        position: relative;
}
.box {
        position: absolute;
        width: 100px;
        height: 100px;
        background: green radial-gradient(at 35% 35%, lightgray, transparent);
        box-shadow: inset -8px -8px 80px -8px tan;
        border-radius: 50% 50% 25% 50%;
        transform: rotate(45deg);
        cursor: pointer;
}
.box::before {
        position: absolute;
        content: '';
        width: 26px;
        height: 6px;
        border: 2px solid #663399;
        border-radius: 0 0 50% 50% / 0 0 100% 100%;
        border-top: none;
        right: -20px;
        bottom: 0;
}
</style>

<div id="papa">
        <div class="box"></div>
</div>

<script>
let box = document.querySelector('.box');
let moveX = 0, moveY = 0, stepX = 1, stepY = 1.5, flag = true;

requestAnimationFrame(motion);

box.onclick = () => {
        flag = !flag;
        if(flag) requestAnimationFrame(motion);
}

function motion() {
        if(!flag) return false;
        moveX += stepX;
        moveY += stepY;
        box.style.left = moveX + 'px';
        box.style.top = moveY + 'px';
        requestAnimationFrame(motion);
        if(moveX < 0 || moveX > papa.offsetWidth - box.offsetWidth) stepX = -stepX;
        if(moveY < 0 || moveY > papa.offsetHeight - box.offsetHeight - 30) stepY = -stepY;
}
</script>

马黑黑 发表于 2022-8-5 13:01

本帖最后由 马黑黑 于 2022-8-5 13:03 编辑

实现方式一:requestAnimationFrame

<style>
#papa {
      margin: auto;
      width: 1024px;
      height: 660px;
      box-shadow: 3px 3px 24px #000;
      position: relative;
}
.box {
      position: absolute;
      width: 100px;
      height: 100px;
      background: green radial-gradient(at 35% 35%, lightgray, transparent);
      box-shadow: inset -8px -8px 80px -8px tan;
      border-radius: 50% 50% 25% 50%;
      transform: rotate(45deg);
      cursor: pointer;
}
.box::before {
      position: absolute;
      content: '';
      width: 26px;
      height: 6px;
      border: 2px solid #663399;
      border-radius: 0 0 50% 50% / 0 0 100% 100%;
      border-top: none;
      right: -20px;
      bottom: 0;
}
</style>

<div id="papa">
      <div class="box"></div>
</div>

<script>
let box = document.querySelector('.box');
let moveX = 0, moveY = 0, stepX = 1, stepY = 1.5, flag = true;

requestAnimationFrame(motion);

box.onclick = () => {
      flag = !flag;
      if(flag) requestAnimationFrame(motion);
}

function motion() {
      if(!flag) return false;
      moveX += stepX;
      moveY += stepY;
      box.style.left = moveX + 'px';
      box.style.top = moveY + 'px';
      requestAnimationFrame(motion);
      if(moveX < 0 || moveX > papa.offsetWidth - box.offsetWidth) stepX = -stepX;
      if(moveY < 0 || moveY > papa.offsetHeight - box.offsetHeight - 30) stepY = -stepY;
}
</script>

马黑黑 发表于 2022-8-5 13:05

实现方法二:setTimeout

将二楼标红的三行代码中红色部分替换为以下蓝色代码即可:

setTimeout(motion, 1000/60);

红影 发表于 2022-8-5 13:12

两种设置得到的效果都是差不多的吧?{:4_187:}

马黑黑 发表于 2022-8-5 13:16

原理解释:

requestAnimationFrame 是利用屏幕的刷新率来实现动画,在 1000/60 即大约 16.7 毫秒以内变换元素形态,肉眼觉察不出这个时间内的动作变化过程,从而觉得元素的变化是连续的。

60是保守估算,因为现在的显示器刷新率最低也应该是60。

requestAnimationFrame 可以视为也是一个定时器,其时间间隔大约是 16.7,或者更低。

setTimeout 定时器是通过设定的间隔时间去执行元素的变化,1000/60 非常接近显示器一次刷新所用的时间,所以用这个间隔时间,setTimeout 也能达到非常接近于 requestAnimationFrame 的效果。

requestAnimationFrame不消耗CPU资源,页面最小化或被遮挡时停止运行;

setTimeout 消耗一定的CPU资源,页面最小化或不可见时依然执行任务,且容易受干扰从而偶尔有丢帧的现象。

马黑黑 发表于 2022-8-5 13:18

红影 发表于 2022-8-5 13:12
两种设置得到的效果都是差不多的吧?

看五楼

加林森 发表于 2022-8-5 14:45

不消耗CPU资源最好。

马黑黑 发表于 2022-8-5 19:05

加林森 发表于 2022-8-5 14:45
不消耗CPU资源最好。

用setTimeout定时器消耗的也只是九牛一毛可以忽略不计

加林森 发表于 2022-8-5 20:53

马黑黑 发表于 2022-8-5 19:05
用setTimeout定时器消耗的也只是九牛一毛可以忽略不计

哦,知道了。

马黑黑 发表于 2022-8-5 21:17

加林森 发表于 2022-8-5 20:53
哦,知道了。

{:4_190:}

红影 发表于 2022-8-5 22:13

马黑黑 发表于 2022-8-5 13:18
看五楼

这个太专业了点。黑黑厉害{:4_187:}

马黑黑 发表于 2022-8-5 22:28

红影 发表于 2022-8-5 22:13
这个太专业了点。黑黑厉害

去学习、研究,谁都可以略知一二

小辣椒 发表于 2022-8-5 22:28

这个我好像一点看不懂{:4_201:}

小辣椒 发表于 2022-8-5 22:29

继续看看,去实践一下看看

小辣椒 发表于 2022-8-5 22:31

请求动画帧
“requestAnimationFrame字面意思:请求动画帧。官方解释:帧动画。就是可以一帧一帧的执行动画。 那么问题来了,这个一帧的执行频率是多久?答案是:与屏幕的刷新频率同步。 也可以认为:让浏览器在显示器屏幕下次刷新时,执行一帧;那么显示器多次刷新屏幕,就执行了多帧;如果速度够快,就会形成动画。 那么显示器的刷新屏幕,也就是屏幕的刷新频率又是什么呢?”

小辣椒 发表于 2022-8-5 22:32

黑黑我平时就这么看。一点点理解的,没有办法 笨咋办{:4_201:}

马黑黑 发表于 2022-8-5 22:38

小辣椒 发表于 2022-8-5 22:31
请求动画帧
“requestAnimationFrame字面意思:请求动画帧。官方解释:帧动画。就是可以一帧一帧的执行动画 ...

这个是requestAnimationFrame的工作原理解释。语法则是:

requestAnimationFrame(函数)

函数是自己编写的,比如让元素 id="box" 的元素左移:

let x = 0;

move(); //调用函数

function move() {
    let x = x + 1;
    if(x > 1000) x = 0; //1000像素后重来
    box.style.left = x + 'px';
    requestAnimationFrame(move); //递归调用本函数
}

这是简单的示例。

马黑黑 发表于 2022-8-5 22:39

小辣椒 发表于 2022-8-5 22:32
黑黑我平时就这么看。一点点理解的,没有办法 笨咋办

能理解个大概就行。JS难度很大的。

小辣椒 发表于 2022-8-5 22:50

马黑黑 发表于 2022-8-5 22:39
能理解个大概就行。JS难度很大的。

黑黑我把我加进去的代码发你在这里。你看看我错误在哪里

马黑黑 发表于 2022-8-5 23:18

小辣椒 发表于 2022-8-5 22:50
黑黑我把我加进去的代码发你在这里。你看看我错误在哪里

两个HTML错误:

一、严重错误:重复使用 id="名称" 的盒子

<div id="papa">
      <span id="tit">我想有个家--买得起这个房产吗</span>
      <span id="ball"></span>
</div>

<div id="papa">
         <img id="zlu " src="https://pic.imgdb.cn/item/62ecc29e8c61dc3b8e215099.gif" alt="" />
      </div>


改为:

<div id="papa">
      <img id="zlu" src="https://pic.imgdb.cn/item/62ecc29e8c61dc3b8e215099.gif" alt="" />
      <span id="tit">我想有个家--买得起这个房产吗</span>
      <span id="ball"></span>
</div>

注意:一切都是放在 papa 盒子内,而不是放在它之外。id="名称" 的东东,只能有一次。

二、小错误:红色部分多了一个空格

<img id="zlu " src="https://pic.imgdb.cn/item/62ecc29e8c61dc3b8e215099.gif" alt="" />
页: [1] 2
查看完整版本: 气球平滑移动的两种实现方式(附代码)