您的位置:首页 > Web前端 > JavaScript

JavaScript运动之缓冲运动

2017-05-10 21:28 295 查看

缓冲运动

逐渐变慢,最后停止

距离越远,速度越大

速度由距离决定

速度 = (目标值 - 当前值)/ 缩放系数

例子:缓冲菜单

- Bug:速度取整

- 跟随页面滚动的缓冲侧边栏

1.    潜在问题:目标值不是整数时


速度和距离成正比

<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
#div1 {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 50px;
}
#div2 {
width: 1px;
height: 300px;
position: absolute;
left: 300px;
top: 0;
background: black;
}
</style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<input type="button" value="Start" onclick="startMove()" />
<script type="text/javascript">
var oDiv = document.getElementById('div1');
function startMove() {
setInterval(function() {
//随着距离的减小,速度也越来越小,符合缓冲的要求,用距离(时刻变化)的十分之一
var speed = (300 - oDiv.offsetLeft) / 10;
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
document.title = oDiv.offsetLeft + ', ' + speed;
}, 30);
}
</script>
</body>
</html>


##### 最后在title上发现“291, 0.9”,也就是物体向右缓冲运动到291px的位置停下,最后时刻有一刻距离还剩9px,速度也就是0.9px,然后滑动向着291.9px的目标前进,但是px是最小的单位,291.9px,计算机就认为是291px,所以,也就永远停在291的位置了,还到不了300的最终位置

Math

Math.ceil(3.2) ==> 4
Math.ceil(-9.7) ==> -9
Math.floor(5.98) ==> 5


[b]所以,speed采用ceil方法向上取整即可,最后能跑到300的位置,分毫不差[/b]

function startMove() {
setInterval(function() {
//随着距离的减小,速度也越来越小,符合缓冲的要求,用距离(时刻变化)的十分之一
var speed = (300 - oDiv.offsetLeft) / 10;
speed = Math.ceil(speed);//划重点
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
document.title = oDiv.offsetLeft + ', ' + speed;
}, 30);
}


这样就完了吗?没有!如果物体左移,也就是比如把div1的left的初始left由0 –> 600,那么,依旧不能分毫无差,最后看title为“309, 0”,实际上,速度为-0.9,(下一刻向着目标308.1px的位置移动),此时Math.ceil()已经不好用了,得用Math.floor();

#div1 {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 600px;/*0 --> 600*/
top: 50px;
}
function startMove() {
setInterval(function() {
var speed = (300 - oDiv.offsetLeft) / 10;
speed = Math.floor(speed);//划重点
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
document.title = oDiv.offsetLeft + ', ' + speed;
}, 30);
}


综上所述:如果正向移动,为了让物体迈过那个不足1的坎,要帮助小数颠颠脚够着更大的整数(0.2 –>1,ceil),如果负向移动,为了让物体迈过不足-1的坎,要帮小数颠颠脚够着更小(绝对值更大)的整数(-0.1 –> -1, floor)

offsetWidth = width + border + padding;
offsetWidth = height + border + padding;
offsetWidth = width + border + padding;


function startMove() {
setInterval(function() {
var speed = (300 - oDiv.offsetLeft) / 10;
speed
ebca
= speed > 0 ? Math.ceil(speed) : Match.floor(speed);
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
document.title = oDiv.offsetLeft + ', ' + speed;
}, 30);
}


总结:但凡是用了缓冲运动的一定要记得速度取整,缓冲也就是速度不停的变化。

缓冲菜单

要求:在右下角有个红色div,无论浏览器怎么滚动,始终落脚在右下角

注意几个概念:
offsetWidth = width + border + padding;
offsetHeight = width + border + padding;
document.documentElement.scrollHeight:
内容可视区域的高度,真正展示网页内容的高度,客户端的界面要跑除,如果你用鼠标调节浏览器窗口的大小,那么这个值会变化。
document.documentElement.scrollHeight:就是3500px,上面已经设置了
网页被卷去的高:document.body.scrollTop
兼容:
var top = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;


综上所述:
在我们要获取文档实际高度时,最好用document.documentElement.scrollHeight
  在我们要获取视口实际高度时,用document.documentElement.clientHeight


<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
#div1 {
width: 100px;
height: 150px;
background: red;
position: absolute;
bottom: 0;
right: 0;
border: 3px solid blue;
padding: 20px;
}
</style>
</head>
<body style="height: 3500px;">
<div id="div1"></div>
<div id="div2"></div>
<script type="text/javascript">
window.onscroll = function() {
var oDiv = document.getElementById('div1');
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
oDiv.style.top = document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop + 'px';
};
</script>
</body>
</html>


上面这段代码就可以让红色物体div紧紧 ‘fix’到页面的右下角,但是,你滚动网页的时候发现div为了努力的紧跟右下角,很费力的在抖动,看起来很不自然,为了看起来自然,需要自写一个运动框架,不让他硬生生的跟着走,而是慢慢的缓缓的缓冲运动。

<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
#div1 {
width: 100px;
height: 150px;
background: red;
position: absolute;
bottom: 0;
right: 0;
border: 3px solid blue;
padding: 20px;
}
</style>
</head>
<body style="height: 3500px;">
<div id="div1"></div>
<div id="div2"></div>
<script type="text/javascript">
window.onscroll = function() {
var oDiv = document.getElementById('div1');
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
//oDiv.style.top = document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop + 'px';
startMove(document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop);
};

var timer = null;
function startMove(iTarget) {
var oDiv = document.getElementById('div1');
clearInterval(timer);
timer = setInterval(function() {
var speed = (iTarget - oDiv.offsetTop)/6;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if (oDiv.offsetTop == iTarget) {
clearInterval(timer);
} else {
oDiv.style.top = oDiv.offsetTop + speed + 'px';
}
}, 30);
}
</script>
</body>
</html>


对联悬浮框

不同上边案例悬浮在右下角,而是‘fix’到右边正中间位置

<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
#div1 {
width: 100px;
height: 150px;
background: red;
position: absolute;
bottom: 0;
right: 0;
border: 3px solid blue;
padding: 20px;
}
</style>
</head>
<body style="height: 3500px;">
<div id="div1"></div>
<div id="div2"></div>
<script type="text/javascript">
window.onscroll = function() {
var oDiv = document.getElementById('div1');
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
//其实仅仅就是参数iTarget的计算变了一下
startMove((document.documentElement.clientHeight - oDiv.offsetHeight) / 2 + scrollTop);
};

var timer = null;
function startMove(iTarget) {
var oDiv = document.getElementById('div1');
clearInterval(timer);
timer = setInterval(function() {
var speed = (iTarget - oDiv.offsetTop)/6;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if (oDiv.offsetTop == iTarget) {
clearInterval(timer);
} else {
oDiv.style.top = oDiv.offsetTop + speed + 'px';
}
}, 30);
}
</script>
</body>
</html>


代码写完了,发现红色div在右边中间以很小的振幅在不同的抖动,问题就出在除以2这里,除以2就可能出现小数的可能性

startMove((document.documentElement.clientHeight - oDiv.offsetHeight) / 2 + scrollTop);
改为:
startMove(parseInt(document.documentElement.clientHeight - oDiv.offsetHeight) / 2 + scrollTop));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript