JavaScript运动框架 解决速度正负取整问题(一)


Posted in Javascript onMay 17, 2017

这里说的运动是指缓冲运动,缓冲运动会使物体逐渐‘着陆',而不是‘硬着陆',到达目标位置的过程中速度越来越慢,看起来很舒服。

缓冲的特点:

  • 速度随着距离的缩短而降低
  • 速度 = (目标值 - 当前值) / 缩放系数;
  • 速度一定要是整数

比如,一个div从最左边运动到left等于400的位置停下,可以如下实现:

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>运动框架(一)</title>
 <style type="text/css">
  * {
   padding: 0;
   margin: 0;
  }
  #div1 {
   width: 100px;
   height: 100px;
   background: orange;
   position: absolute;
  }
  #div2 {
   width: 1px;
   height: 300px;
   background: black;
   position: absolute;
   left: 400px;
  }
  #btn1 {
   width: 60px;
   height: 40px;
   background: #fff;
   position: absolute;
   left: 10px;
   top: 150px;
  }
 </style>
</head>
<body>
 <div id="div1"></div>
 <div id="div2"></div>
 <input id="btn1" type="button" value="start" onclick="startMove()" />
 <script type="text/javascript">
  var oDiv = document.getElementById('div1');
  var oBtn = document.getElementById('btn1');
  var timer = null;
  function startMove() {
   /* 每次启动定时器应该把上次的定时器清理掉,
    因为有的人会多次点击按钮,多次启动定时器,速度会叠加越来越快!
   */
   clearInterval(timer);
   timer = setInterval(function() {
    //每次速度都随着距离的缩短而变慢
    var speed = (400 - oDiv.offsetLeft) / 10;
    if (oDiv.offsetLeft == 400) {
     clearInterval(timer); 
    } else {
     oDiv.style.left = oDiv.offsetLeft + speed + 'px';
     document.title = oDiv.offsetLeft + ' , ' + speed;
    }
   }, 30);
  }
 </script>
</body>
</html>

JavaScript运动框架 解决速度正负取整问题(一)

JavaScript运动框架 解决速度正负取整问题(一)

你会发现,启动按钮之后,div并没有准确到达400的位置,再看看title上打印的实际目标和速度,我们发现最终落脚点是396,速度为0.4,我们知道:1px是最小单位,没有小数的概念,所以0.4px是没有的概念,会被计算机认为是0px,仔细分析,当div运行到396px的时候,还剩下4px,速度为4/10 = 0.4,下一个单位时间(30ms)向前运行0.4px,实际上是0,所以永远的停下来了,而且永远不会执行清除定时器这一步!
怎么解决,Math中有个方法叫向上取整,也就是让速度取整,向上取整,努力帮助div跨过这一步

Math.ceil(3.2) ==> 4
Math.ceil(-9.7) ==> -9
Math.floor(5.98) ==> 5
function startMove() {
 clearInterval(timer);
 timer = setInterval(function() {
  var speed = (400 - oDiv.offsetLeft) / 10;
  speed = Math.ceil(speed);//划重点,划重点
  if (oDiv.offsetLeft == 400) {
   clearInterval(timer);
  } else {
   oDiv.style.left = oDiv.offsetLeft + speed + 'px';
   document.title = oDiv.offsetLeft + ' , ' + speed;
  }
 }, 30);
}

JavaScript运动框架 解决速度正负取整问题(一)

当然了,div除了可以正向运动,也可以负向运动,比如,从800运动到400.
如果不取整的话,依旧不能准确到达400。

#div1 {
 width: 100px;
 height: 100px;
 background: orange;
 position: absolute;
 left: 800px;/*0 --> 800*/
}

JavaScript运动框架 解决速度正负取整问题(一)

function startMove() {
 clearInterval(timer);
 timer = setInterval(function() {
  var speed = (400 - oDiv.offsetLeft) / 10;
  console.log('speed = ' + speed);
  speed = Math.floor(speed);//划重点,划重点,划重点
  if (oDiv.offsetLeft == 400) {
   clearInterval(timer);
  } else {
   oDiv.style.left = oDiv.offsetLeft + speed + 'px';
   document.title = oDiv.offsetLeft + ' , ' + speed;
  }
 }, 30);
}

JavaScript运动框架 解决速度正负取整问题(一)

总结:

正向运动(速度 > 0), Math.ceil(speed);
反向运动(速度 < 0), Math.floor(speed);

var speed = (iTarget - cur) / 系数;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
function startMove(iTarget) {
 setInterval(function() {
  var speed = (iTarget- oDiv.offsetLeft) / 10;
  speed = speed > 0 ? Math.ceil(speed) : Match.floor(speed);
  oDiv.style.left = oDiv.offsetLeft + speed + 'px';
 }, 30);
}

速度取整,是为了最后时刻速度(绝对值)变大,跨过那一槛,不然只能停留在附近!

如果速度不取整,最后的结果就是停在目标值附近,还差几个像素,这个值最后算出来的速度的绝对值肯定小于1,导致还差几像素跨不过去了,如果你这时候让速度取整达到1,最后几个像素的距离其实就是匀速前行了,每次(30ms)都行走1px,因为最后几次都速度算出来都是1,1px 1px的行走到目的地!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery offset函数应用实例
Nov 14 Javascript
jquery的$getjson调用并获取远程的JSON字符串问题
Dec 10 Javascript
javascript中的return和闭包函数浅析
Jun 06 Javascript
javascript折半查找详解
Jan 26 Javascript
ECMAScript6块级作用域及新变量声明(let)
Jun 12 Javascript
jQuery unbind()方法实例详解
Jan 19 Javascript
javascript DIV实现跟随鼠标移动
Mar 19 Javascript
jQuery Ajax 上传文件处理方式介绍(推荐)
Jun 30 Javascript
jquery获取transform里的值实现方法
Dec 12 jQuery
解析Vue.js中的组件
Feb 02 Javascript
React如何实现浏览器打印部分内容详析
May 19 Javascript
js正则匹配markdown里的图片标签的实现
Mar 24 Javascript
深入理解Commonjs规范及Node模块实现
May 17 #Javascript
JavaScript限制在客户区可见范围的拖拽(解决scrollLeft和scrollTop的问题)(2)
May 17 #Javascript
vue学习笔记之vue1.0和vue2.0的区别介绍
May 17 #Javascript
Angular.JS中的this指向详解
May 17 #Javascript
websocket+node.js实现实时聊天系统问题咨询
May 17 #Javascript
JavaScript简单拖拽效果(1)
May 17 #Javascript
node.js连接MongoDB数据库的2种方法教程
May 17 #Javascript
You might like
我的论坛源代码(十)
2006/10/09 PHP
windows xp下安装pear
2006/12/02 PHP
PHP 利用AJAX获取网页并输出的实现代码(Zjmainstay)
2012/08/31 PHP
php 去除html标记--strip_tags与htmlspecialchars的区别详解
2013/06/26 PHP
JavaScript 嵌套函数指向this对象错误的解决方法
2010/03/15 Javascript
javascript的回调函数应用示例
2014/02/20 Javascript
JavaScript代码轻松实现网页内容禁止复制(代码简单)
2015/10/23 Javascript
原生JavaScript实现Ajax的方法
2016/04/07 Javascript
JS实现的表格行上下移动操作示例
2016/08/03 Javascript
基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)
2016/09/02 Javascript
React Native悬浮按钮组件的示例代码
2018/04/05 Javascript
VUE Error: getaddrinfo ENOTFOUND localhost
2018/05/03 Javascript
详解vue中组件参数
2018/07/09 Javascript
angular 内存溢出的问题解决
2018/07/12 Javascript
Vue.js子组件向父组件通信的方法实例代码详解
2018/12/10 Javascript
JavaScript对JSON数组简单排序操作示例
2019/01/31 Javascript
关于layui 弹出层一闪而过就消失的解决方法
2019/09/09 Javascript
11个Javascript小技巧帮你提升代码质量(小结)
2020/12/28 Javascript
[01:02:17]2014 DOTA2华西杯精英邀请赛 5 24 DK VS VG
2014/05/26 DOTA
[01:44]《为梦想出发》—联想杯DOTA2完美世界全国高校联赛
2015/09/30 DOTA
python中的装饰器详解
2015/04/13 Python
Python线程的两种编程方式
2015/04/14 Python
python2.7无法使用pip的解决方法(安装easy_install)
2018/04/03 Python
python利用小波分析进行特征提取的实例
2019/01/09 Python
Python3.5面向对象程序设计之类的继承和多态详解
2019/04/24 Python
python使用socket 先读取长度,在读取报文内容示例
2019/09/26 Python
flask 实现token机制的示例代码
2019/11/07 Python
PyTorch 随机数生成占用 CPU 过高的解决方法
2020/01/13 Python
python MultipartEncoder传输zip文件实例
2020/04/07 Python
Python实现异步IO的示例
2020/11/05 Python
特罗佩亚包官方网站:Tropea
2017/01/03 全球购物
新闻专业个人自我评价
2013/09/21 职场文书
情况说明书格式及范文
2019/06/24 职场文书
女人创业励志语录,句句蕴含能量,激发你的潜能
2019/08/20 职场文书
python用海龟绘图写贪吃蛇游戏
2021/06/18 Python
python如何读取和存储dict()与.json格式文件
2022/06/25 Python