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 相关文章推荐
IE php关于强制下载文件的代码
Aug 23 Javascript
JavaScript中的toDateString()方法使用详解
Jun 12 Javascript
JavaScript实现广告的关闭与显示效果实例
Jul 02 Javascript
JavaScript类型检测之typeof 和 instanceof 的缺陷与优化
Jan 13 Javascript
jquery div模态窗口的简单实例
May 28 Javascript
Javascript学习之谈谈JS的全局变量跟局部变量(推荐)
Aug 28 Javascript
实现easyui的datagrid导出为excel的示例代码
Nov 10 Javascript
基于复选框demo(分享)
Sep 27 Javascript
微信小程序slider组件使用详解
Jan 31 Javascript
vue中本地静态图片路径写法
Mar 06 Javascript
vue+webpack中配置ESLint
Nov 07 Javascript
微信小程序webview组件交互,内联h5页面并网页实现微信支付实现解析
Aug 16 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
php日历[测试通过]
2008/03/27 PHP
php实现多张图片上传加水印技巧
2013/04/18 PHP
PHP APC配置文件2套和参数详解
2014/06/11 PHP
PHP 使用 Imagick 裁切/生成缩略图/添加水印自动检测和处理 GIF
2016/02/19 PHP
php实现数组纵向转横向并过滤重复值的方法分析
2017/05/29 PHP
PHP xpath提取网页数据内容代码解析
2020/07/16 PHP
javascript 读取XML数据,在页面中展现、编辑、保存的实现
2009/10/27 Javascript
JS 文件大小判断的实现代码
2010/04/07 Javascript
myEvent.js javascript跨浏览器事件框架
2011/10/24 Javascript
JavaScript中5种调用函数的方法
2015/03/12 Javascript
javascript基于DOM实现权限选择实例分析
2015/05/14 Javascript
js控制文本框输入的字符类型方法汇总
2015/06/19 Javascript
基于jQuery实现的无刷新表格分页实例
2016/02/17 Javascript
vue,angular,avalon这三种MVVM框架优缺点
2016/04/27 Javascript
JS数组操作中的经典算法实例讲解
2017/07/26 Javascript
图文介绍Vue父组件向子组件传值
2018/02/17 Javascript
jQuery中复合选择器简单用法示例
2018/03/31 jQuery
详解vue 单页应用(spa)前端路由实现原理
2018/04/04 Javascript
详解如何使用微信小程序云函数发送短信验证码
2019/03/13 Javascript
全面了解JavaScript的作用域链
2019/04/03 Javascript
微信小程序scroll-view点击项自动居中效果的实现
2020/03/25 Javascript
vue实现可移动的悬浮按钮
2021/03/04 Vue.js
python列表的常用操作方法小结
2016/05/21 Python
python实现随机森林random forest的原理及方法
2017/12/21 Python
Python使用min、max函数查找二维数据矩阵中最小、最大值的方法
2018/05/15 Python
python中ASCII码和字符的转换方法
2018/07/09 Python
Jupyter Notebook 文件默认目录的查看以及更改步骤
2020/04/14 Python
CSS3实现苹果手机解锁的字体闪亮效果示例
2021/01/05 HTML / CSS
HTML5移动端手机网站开发流程
2016/04/25 HTML / CSS
Skip Hop官网:好莱坞宝宝挚爱品牌
2018/06/17 全球购物
大学自荐信
2013/12/12 职场文书
政治思想表现评语
2014/05/04 职场文书
2015新年寄语(一句话)
2014/12/08 职场文书
证券区域经理岗位职责
2015/04/10 职场文书
钱学森电影观后感
2015/06/04 职场文书
寒假生活随笔
2015/08/15 职场文书