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下操作css的float属性的特殊写法
Aug 22 Javascript
自己动手制作jquery插件之自动添加删除行功能介绍
Oct 14 Javascript
extjs ColumnChart设置不同的颜色实现代码
May 17 Javascript
js中opener与parent的区别详细解析
Jan 14 Javascript
JavaScript点击按钮后弹出透明浮动层的方法
May 11 Javascript
Angularjs 实现一个幻灯片示例代码
Sep 08 Javascript
JavaScript数据结构链表知识详解
Nov 21 Javascript
Flask中获取小程序Request数据的两种方法
May 12 Javascript
JS原生带小白点轮播图实例讲解
Jul 22 Javascript
Node.js自定义实现文件路由功能
Sep 22 Javascript
JavaScript中this用法学习笔记
Mar 17 Javascript
微信小程序动态添加和删除组件的现实
Feb 28 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
Search File Contents PHP 搜索目录文本内容的代码
2010/02/21 PHP
PHP下 Mongodb 连接远程数据库的实例代码
2017/08/30 PHP
js验证表单第二部分
2006/11/25 Javascript
Javascript 面试题随笔
2011/03/31 Javascript
Dom操作之兼容技巧分享
2011/09/20 Javascript
js实现身份证号码验证的简单实例
2014/02/19 Javascript
js实现用户注册协议倒计时的方法
2015/01/21 Javascript
JS文字球状放大效果代码分享
2015/08/19 Javascript
js实现点击图片自动提交action的简单方法
2016/10/16 Javascript
js print打印网页指定区域内容的简单实例
2016/11/01 Javascript
JS仿京东移动端手指拨动切换轮播图效果
2020/04/10 Javascript
Javascript 实现计算器时间功能详解及实例(二)
2017/01/08 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
2017/02/19 Javascript
JavaScript获取tr td 的三种方式全面总结(推荐)
2017/08/15 Javascript
JavaScript设计模式之观察者模式实例详解
2019/01/16 Javascript
[01:10]DOTA2次级职业联赛 - EP战队宣传片
2014/12/01 DOTA
[00:43]TI7不朽珍藏III——幽鬼不朽展示
2017/07/15 DOTA
Python 正则表达式入门(中级篇)
2016/12/07 Python
Python将多个excel表格合并为一个表格
2021/02/22 Python
scrapy爬虫完整实例
2018/01/25 Python
浅谈Python Opencv中gamma变换的使用详解
2018/04/02 Python
Python数据处理numpy.median的实例讲解
2018/04/02 Python
python实现下载pop3邮件保存到本地
2018/06/19 Python
Django实现发送邮件功能
2019/07/18 Python
分享PyCharm的几个使用技巧
2019/11/10 Python
详解HTML5 录音的踩坑之旅
2017/12/26 HTML / CSS
光电信息专业应届生求职信
2013/10/07 职场文书
保险专业自荐信范文
2014/02/20 职场文书
《罗布泊,消逝的仙湖》教学反思
2014/03/01 职场文书
走进敬老院活动总结
2014/07/10 职场文书
先进基层党组织事迹材料
2014/12/25 职场文书
导游词之桂林
2019/08/20 职场文书
导游词之镇江西津古渡
2019/11/06 职场文书
PyCharm 安装与使用配置教程(windows,mac通用)
2021/05/12 Python
Python下opencv库的安装过程及问题汇总
2021/06/11 Python
《勇者辞职不干了》上卷BD发售宣传CM公开
2022/04/08 日漫