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 相关文章推荐
JavaScript 比较时间大小的代码
Apr 24 Javascript
JavaScript之自定义类型
May 04 Javascript
JavaScript闭包详解
Feb 02 Javascript
深入理解Node.js的HTTP模块
Oct 12 Javascript
angular ngClick阻止冒泡使用默认行为的方法
Nov 03 Javascript
基于Vue的移动端图片裁剪组件功能
Nov 28 Javascript
vue 子组件向父组件传值方法
Feb 26 Javascript
vue使用监听实现全选反选功能
Jul 06 Javascript
vue将后台数据时间戳转换成日期格式
Jul 31 Javascript
javaScript中indexOf用法技巧
Nov 26 Javascript
vue项目打包为APP,静态资源正常显示,但API请求不到数据的操作
Sep 12 Javascript
JavaScript实现淘宝商品图切换效果
Apr 29 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
Breeze 文章管理系统 v1.0.0正式发布
2006/12/14 PHP
php+mysql实现用户注册登陆的方法
2015/01/03 PHP
PHP二维数组去重实例分析
2016/11/18 PHP
使用jQuery向asp.net Mvc传递复杂json数据-ModelBinder篇
2010/05/07 Javascript
给html超链接设置事件不使用href来完成跳
2014/04/20 Javascript
ff chrome和ie下全局动态定位的异同及全局高度的取法
2014/06/30 Javascript
Node.js中使用事件发射器模式实现事件绑定详解
2014/08/15 Javascript
js实现缓冲运动效果的方法
2015/04/10 Javascript
Jquery 垂直多级手风琴菜单附源码下载
2015/11/17 Javascript
jQuery之简单的表单验证实例
2016/07/07 Javascript
利用jquery实现下拉框的禁用与启用
2016/12/07 Javascript
详解axios在node.js中的post使用
2017/04/27 Javascript
jQuery tip提示插件(实例分享)
2017/04/28 jQuery
webpack构建react多页面应用详解
2017/09/15 Javascript
微信小程序request请求后台接口php的实例详解
2017/09/20 Javascript
vue生命周期和react生命周期对比【推荐】
2018/09/19 Javascript
微信小程序ibeacon三点定位详解
2018/10/31 Javascript
基于Vue SEO的四种方案(小结)
2019/07/01 Javascript
微信小程序利用button控制条件标签的变量问题
2020/03/15 Javascript
vue - props 声明数组和对象操作
2020/07/30 Javascript
[01:39]2014DOTA2国际邀请赛 Newbee经理CU专访队伍火力全开
2014/07/15 DOTA
[33:23]Secret vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[01:02:38]DOTA2-DPC中国联赛定级赛 LBZS vs Phoenix BO3第二场 1月10日
2021/03/11 DOTA
Python2和Python3中print的用法示例总结
2017/10/25 Python
Python采集猫眼两万条数据 对《无名之辈》影评进行分析
2018/12/05 Python
详解Python list和numpy array的存储和读取方法
2019/11/06 Python
Python使用psutil获取进程信息的例子
2019/12/17 Python
Python如何实现Paramiko的二次封装
2021/01/30 Python
详解canvas在圆弧周围绘制文本的两种写法
2018/05/22 HTML / CSS
Html5踩坑记之mandMobile使用小记
2020/04/02 HTML / CSS
父亲生日宴会答谢词
2014/01/10 职场文书
初中生自我评价
2014/02/01 职场文书
可贵的沉默教学反思
2014/02/06 职场文书
党员公开承诺书内容
2014/05/20 职场文书
妇女工作先进事迹
2014/08/17 职场文书
观看焦裕禄观后感
2015/06/09 职场文书