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 相关文章推荐
JQuery 网站换肤功能实现代码
Nov 02 Javascript
document.getElementById的简写方式(获取id对象的简略写法)
Sep 10 Javascript
jquery的ajax简单结构示例代码
Feb 17 Javascript
jQuery自带的一些常用方法总结
Sep 03 Javascript
Javascript基础教程之函数对象和属性
Jan 18 Javascript
JavaScript简单实现鼠标移动切换图片的方法
Feb 23 Javascript
微信小程序 开发之全局配置
May 05 Javascript
JavaScript正则表达式校验与递归函数实际应用实例解析
Aug 04 Javascript
JS非空验证及邮箱验证的实例
Aug 11 Javascript
深入Vue-Router路由嵌套理解
Aug 13 Javascript
微信小程序获取用户信息及手机号(后端TP5.0)
Sep 12 Javascript
vue实现鼠标移过出现下拉二级菜单功能
Dec 12 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编程入门的基本语法知识点总结
2016/01/26 PHP
PHP5.5.15+Apache2.4.10+MySQL5.6.20配置方法分享
2016/05/06 PHP
Yii2第三方类库插件Imagine的安装和使用
2017/07/06 PHP
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
PHP之认识(二)关于Traits的用法详解
2019/04/11 PHP
node.js解决获取图片真实文件类型的问题
2014/12/20 Javascript
JavaScript实现打字效果的方法
2015/07/10 Javascript
谈一谈javascript中继承的多种方式
2016/02/19 Javascript
JavaScript实现99乘法表及隔行变色实例代码
2016/02/24 Javascript
微信jssdk在iframe页面失效问题的解决措施
2016/03/03 Javascript
拥Bootstrap入怀——导航栏篇
2016/05/30 Javascript
浅谈js中的引用和复制(传值和传址)
2016/09/18 Javascript
Angular之指令Directive用法详解
2017/03/01 Javascript
原生JS实现图片无缝滚动方法(附带封装的运动框架)
2017/10/01 Javascript
深入理解JS的事件绑定、事件流模型
2018/05/13 Javascript
JS实现的贪吃蛇游戏案例详解
2019/05/01 Javascript
angular6开发steps步骤条组件
2019/07/04 Javascript
JS实现动态倒计时功能(天数、时、分、秒)
2019/12/12 Javascript
详解Python中的__getitem__方法与slice对象的切片操作
2016/06/27 Python
tensorflow训练中出现nan问题的解决
2018/02/10 Python
对python插入数据库和生成插入sql的示例讲解
2018/11/14 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
django中间键重定向实例方法
2019/11/10 Python
学习Python列表的基础知识汇总
2020/03/10 Python
使用Python-OpenCV消除图像中孤立的小区域操作
2020/07/05 Python
利用Pycharm + Django搭建一个简单Python Web项目的步骤
2020/10/22 Python
python 窃取摄像头照片的实现示例
2021/01/08 Python
神经网络训练采用gpu设置的方式
2021/03/03 Python
工业设计专业自荐书
2014/06/05 职场文书
青年标兵事迹材料
2014/08/16 职场文书
支部书记四风对照材料
2014/08/28 职场文书
学校法制宣传日活动总结
2014/11/01 职场文书
山楂树之恋观后感
2015/06/11 职场文书
感恩教师节主题班会
2015/08/12 职场文书
Java Socket实现Redis客户端的详细说明
2021/05/26 Redis
JavaScript如何优化逻辑判断代码详解
2021/06/08 Javascript