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 相关文章推荐
JS延迟加载(setTimeout) JS最后加载
Jul 15 Javascript
js函数中onmousedown和onclick的区别和联系探讨
May 19 Javascript
javascript禁止访客复制网页内容的实现代码
Aug 05 Javascript
JS实现超简单的鼠标拖动效果
Nov 02 Javascript
jquery插件Jplayer使用方法简析
Apr 22 Javascript
Reactjs实现通用分页组件的实例代码
Jan 19 Javascript
纯js实现html转pdf的简单实例(推荐)
Feb 16 Javascript
微信小程序 空白页重定向解决办法
Jun 27 Javascript
解决vue处理axios post请求传参的问题
Mar 05 Javascript
解决vue中使用Axios调用接口时出现的ie数据处理问题
Aug 13 Javascript
对layui中table组件工具栏的使用详解
Sep 19 Javascript
HTML+JS实现在线朗读器
Feb 15 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中鲜为人知的10个函数
2014/02/28 PHP
php采用session实现防止页面重复刷新
2015/12/24 PHP
php pdo操作数据库示例
2017/03/10 PHP
JQuery 弹出框定位实现方法
2010/12/02 Javascript
JavaScript图片放大技术(放大镜)实现代码分享
2013/11/14 Javascript
使用jQuery jqPlot插件绘制柱状图
2014/12/18 Javascript
一个php+js实时显示时间问题
2015/10/12 Javascript
Bootstrap精简教程
2015/11/27 Javascript
很棒的js Tab选项卡切换效果
2016/08/30 Javascript
Vue.js每天必学之构造器与生命周期
2016/09/05 Javascript
使用JS实现图片展示瀑布流效果的实例代码
2016/09/12 Javascript
JavaScript中的 attribute 和 jQuery中的 attr 方法浅析
2017/01/04 Javascript
详解基于angular-cli配置代理解决跨域请求问题
2017/07/05 Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
2017/12/14 Javascript
详解JSON和JSONP劫持以及解决方法
2019/03/08 Javascript
js数组相减简单示例【删除a数组所有与b数组相同元素】
2020/03/04 Javascript
[36:52]DOTA2真视界:基辅特锦赛总决赛
2017/05/21 DOTA
python判断端口是否打开的实现代码
2013/02/10 Python
linux下python使用sendmail发送邮件
2018/05/22 Python
python如何实现一个刷网页小程序
2018/11/27 Python
在python中,使用scatter绘制散点图的实例
2019/07/03 Python
python 单线程和异步协程工作方式解析
2019/09/28 Python
Python多进程编程常用方法解析
2020/03/26 Python
python 装饰器的实际作用有哪些
2020/09/07 Python
美的官方商城:Midea
2016/09/14 全球购物
Airbnb爱彼迎官网:成为爱彼迎房东,赚取收入
2019/03/14 全球购物
毕业生求职找工作的自我评价范文
2013/11/27 职场文书
汽车专业大学生职业生涯规划范文
2014/01/07 职场文书
恐龙的灭绝教学反思
2014/02/12 职场文书
爱国演讲稿400字
2014/05/07 职场文书
护士工作失误检讨书
2014/09/14 职场文书
十八大标语口号
2014/10/09 职场文书
承诺函格式模板
2015/01/21 职场文书
刘胡兰观后感
2015/06/16 职场文书
聊一聊python常用的编程模块
2021/05/14 Python
Sql Server之数据类型详解
2022/02/28 SQL Server