首先对常见的运动做一个总结
一、运动总结
1、匀速运动
1.速度不变,临界判断尤为重要,判断不好可能超出目标点。可以用绝对值 Math.abs(now-target)<speed ,最后1次手动运动到目标点
2、缓冲运动
1.速度逐渐变小,是变减速运动,
2.临界问题就不用管了,速度最后会变为1个像素的移动(直接取整)
3.速度是逐渐减小为0,但是都是>0的,所以是单方向的运动
3、弹性运动
1.速度与缓冲运动一样逐渐变小,但是速度可以<0 ,所以是双方向的运动
2.是按一定比例摩擦力减小速度,并不是到目标点速度为0,所以在目标点的时候还有速度
3.使用范围比较窄,如果变换的属性 会越界,就不适合使用。
二、通用运动框架
1、我们在写一个物体运动的时候,基本上会有这么几个过程,以下归纳
1.清除当前物体定时器定时器
2.设置定时器
3.得到当前位置
4.计算速度
5.停止检查
6.运动
2.以下是框架代码
/**
* 通用运动框架,支持多个对象同时运动
* @param obj 运动对象
* @param json 需要变化的属性键值对 值为目的地的值
* @param func 运动完成后执行函数
*/
function startMove(obj,json,func){
//清除定时器
clearInterval(obj.timer);
//设置定时器
obj.timer = setInterval(function(){
//得到当前位置
var isStop = true;
for(var atrr in json){
var iNowPosition = null;
if(atrr == 'opacity'){
iNowPosition = parseInt(parseFloat(getStyle(obj,atrr))*100); //避免浮点数
}else{
iNowPosition = parseInt(getStyle(obj,atrr));
}
//计算速度
var iSpeed = (json[atrr]-iNowPosition)/8;
iSpeed = iSpeed>0 ?Math.ceil(iSpeed):Math.floor(iSpeed);
//停止检查
if(iNowPosition != json[atrr]){ //当所有的都到达才停止
isStop = false;
}else{
isStop = true;
}
if(atrr == 'opacity'){
obj.style.filter = 'alpha:opacity('+(iNowPosition+iSpeed)+')';
obj.style.opacity = (iNowPosition+iSpeed)/100;
}else{
obj.style[atrr] = iNowPosition + iSpeed + 'px'; //移动物体
}
}
if(isStop){
clearInterval(obj.timer);
if(func){
func();
}
}
},30)
}
3.以下是一个简单的例子,效果大家可以自己试试
<style type="text/css">
div {
width: 100px;
height: 100px;
background: red;
margin-top: 50px;
border: 1px solid red;
}
</style>
<script type="text/javascript">
window.onload = function () {
var oDivs = document.getElementsByTagName ('div');
oDivs[0].onmouseover = function () {
startMove (this, {width: 500});
}
oDivs[0].onmouseout = function () {
startMove (this, {width: 100});
}
oDivs[1].onmouseover = function () {
startMove (this, {height: 150});
}
oDivs[1].onmouseout = function () {
startMove (this, {height: 100});
}
oDivs[2].onmouseover = function () {
startMove (this, {'opacity': 100});
}
oDivs[2].onmouseout = function () {
startMove (this, {'opacity': 30});
}
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
4.注意事项
在写运动框架的时候,遇到了一些问题,和关键点,在此总结
1.开始运动前先删掉原来的定时器
2.运动和停止的处理分开并且不能同时执行
3.速度取整,最小单位不能小于1像素
4.不要用offsetWidth 它会包含除了内容以外 border padding 计算的时候会出现额外值,出现意外情况
5.多物体运动,所有的东西都不能公用,全部设置为该物体的属性
6.用数字进行计算的时候,注意用Number转一下。避免出错
7.js字符串转数字 str*1
8.运动处理中,如果有除法,则很容易出现小数,那么就要取整
9.尽量避免使用小数,用小数就会出问题,通过单位转换和省掉小数部分来避免
三、弹性运动框架
var iSpeed = 0;
var left = 0;
function flexMove(ele,iTarget){
clearInterval(ele.timer);
ele.timer = setInterval(function(){
iSpeed += (iTarget-ele.offsetLeft)/5;
iSpeed *= 0.7; //弹性运动,相当于有一个摩擦力,速度越来越小,方向不停的变化(由speed的正负来确定)
left += iSpeed //这个地方没有用offSetLeft 来算移动距离,因为不支持小数会自己省掉,造成误差
if(Math.abs(iSpeed) < 1 && Math.abs(iTarget - left) < 1){
clearInterval(ele.timer);
iSpeed = 0;
ele.style.left = iTarget + "px"; //当速度小于1个像素,或者距离目的地小于1个像素,则直接到达目标点
}else{
ele.style.left = left + "px"; //速度根据计算出来的speed不停叠加
}
},30)
}
1.下面是一个实例,实现了菜单下,1个小条的弹性运动
<style type="text/css">
li{ list-style: none;} img{ border: none;} ul{ padding: 0; margin: 0;}
#ul1 { width: 408px; margin: 0 auto; position: relative;}
#ul1 li{ width: 100px; height: 30px;line-height: 20px; border: 1px solid; float: left; text-align: center; }
#ul1 .bg{ background-color: red; height: 5px; border: 1px solid black; position: absolute;top:25px; left: 0; }
</style>
<script type="text/javascript">
window.onload = function(){
var bg = document.getElementsByClassName('bg')[0];
var ali = document.getElementById('ul1').getElementsByTagName('li');
for (var i = 0; i < ali.length-1; i++) {
var obj = ali[i];
obj.onmouseover = function(){
flexMove(bg,this.offsetLeft);
}
}
}
</script>
</head>
<body>
<ul id="ul1">
<li>相见相见</li>
<li>相见相见</li>
<li>相见相见</li>
<li>相见相见</li>
<li class="bg"></li>
</ul>
</body>