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中的函数
Jan 22 Javascript
更优雅的事件触发兼容
Oct 24 Javascript
封装好的一个万能检测表单的方法
Jan 21 Javascript
js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
Feb 11 Javascript
JS加载iFrame出现空白问题的解决办法
May 13 Javascript
浅谈jQuery中hide和fadeOut的区别 show和fadeIn的区别
Aug 18 Javascript
ES6新特性六:promise对象实例详解
Apr 21 Javascript
Parcel.js + Vue 2.x 极速零配置打包体验教程
Dec 24 Javascript
vue实现文件上传功能
Aug 13 Javascript
vue 中几种传值方法(3种)
Nov 12 Javascript
JS关闭子窗口并且刷新上一个窗口的实现示例
Mar 10 Javascript
原生jQuery实现只显示年份下拉框
Dec 24 jQuery
深入理解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基于数组实现的分页函数实例
2014/08/20 PHP
学习php设计模式 php实现合成模式(composite)
2015/12/08 PHP
PHP常用设计模式之委托设计模式
2016/02/13 PHP
使用JavaScript创建新样式表和新样式规则
2016/06/14 PHP
javascript下数值型比较难点说明
2010/06/07 Javascript
Extjs4 GridPanel 的几种样式使用介绍
2013/04/18 Javascript
jQuery登陆判断简单实现代码
2013/04/21 Javascript
jquery实现鼠标滑过小图查看大图的方法
2015/07/20 Javascript
完美实现bootstrap分页查询
2015/12/09 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
jquery把int类型转换成字符串类型的方法
2016/10/07 Javascript
Javascript 创建类并动态添加属性及方法的简单实现
2016/10/20 Javascript
js实现弹窗暗层效果
2017/01/16 Javascript
JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码
2017/08/18 Javascript
jQuery中ajax请求后台返回json数据并渲染HTML的方法
2018/08/08 jQuery
Vue axios 将传递的json数据转为form data的例子
2019/10/29 Javascript
详解datagrid使用方法(重要)
2020/11/06 Javascript
python抓取网页中的图片示例
2014/02/28 Python
TensorFlow实现模型评估
2018/09/07 Python
python 基于TCP协议的套接字编程详解
2019/06/29 Python
Python 如何提高元组的可读性
2019/08/26 Python
python 输出列表元素实例(以空格/逗号为分隔符)
2019/12/25 Python
基于python3的socket聊天编程
2020/02/17 Python
opencv python 图片读取与显示图片窗口未响应问题的解决
2020/04/24 Python
python判断元素是否存在的实例方法
2020/09/24 Python
Html5实现文件异步上传功能
2017/05/19 HTML / CSS
自我评价的写作规则
2014/01/06 职场文书
打造完美自荐信
2014/01/24 职场文书
小学生自我评价范文
2014/01/25 职场文书
考博专家推荐信
2014/05/10 职场文书
运动会入场口号
2014/06/07 职场文书
2019职场实习报告该怎么写?
2019/07/01 职场文书
教你怎么用python实现字符串转日期
2021/05/24 Python
使用Vue3+Vant组件实现App搜索历史记录功能(示例代码)
2021/06/09 Vue.js
MySQL 5.7常见数据类型
2021/07/15 MySQL
win11怎么用快捷键锁屏? windows11锁屏的几种方法
2021/11/21 数码科技