运动框架实现思路:
1.速度(改变值Left、right、width、height、opacity)
2.缓冲运动
3.多物体运动
4.任意值变化
5.链式运动 (如:先宽后高)
6.同时运动 (如:宽高同时运动)
JS速度动画:
创建定时器:setInterval(function(){},30)
先清空定时器,在判断条件。clearinterval();
注意避免硬编码即在函数的判断之中直接使用具体的值如10,20等,应该把这些变化的值作为参数传入函数内部,即美观也方便后来的修改。
<!DOCTYPE html>
<html>
<head>
<title>动画</title>
<meta charset="utf-8">
<style type="text/css">
body,div,span{
margin: 0;
padding: 0;
}
#div1{
width: 200px;
height: 200px;
background: red;
position: relative;
left: -200px;
top: 0;
}
#div1 span{
width: 20px;
height: 50px;
background: blue;
position: absolute;
left: 200px;
top: 75px;
}
</style>
<script type="text/javascript">
window.οnlοad=function()
{
varoDiv=document.getElementById('div1');
oDiv.οnmοuseenter=function()
{
startMove(0);
}
oDiv.οnmοuseleave=function(){
startMove(-200);
}
}
var timer =null;
function startMove(iTarget){
clearInterval(timer);
varoDiv=document.getElementById('div1');
timer=setInterval(function(){
var speed=0;
if(oDiv.offsetLeft>iTarget) {
speed=-10;
}
else{
speed=10;
}
if(oDiv.offsetLeft == iTarget) {
clearInterval(timer);
}
else{
oDiv.style.left=oDiv.offsetLeft+speed+'px';
}
},35)
}
</script>
</head>
<body>
<div id="div1" ><span id="share">分享</span></div>
</body>
</html>
JS透明动画
<!-- 使用js实现透明度运动而不采用直接设置css的style.opacity属性来改变透明度,这是因为css的透明度的设置是一步到位,瞬时完成的,而使用js可以实现渐隐特效 -->
opacity是不透明度,opacity为0时表示不透明度是0也就是完全透明(效果等同于css的隐藏)
filter: alpha(opacity:30); /*IE浏览器专用,opacity属性值为0~100*/
opacity:0.3; /*所有主流浏览器都支持opacity属性。.
注意:IE8和早期版本支持另一种过滤器属性。像:filter:Alpha(opacity=50),而IE8版本之前的opacity属性值是0~1*/
【没有直接的属性可以改变透明度,需要定义一个alpha】
<!DOCTYPE html>
<html>
<head>
<title>透明度动画</title>
<meta charset="utf-8">
</head>
<style type="text/css">
body,div{
margin: 0;
padding: 0;
}
#div1{
width: 200px;
height: 200px;
background: red;
filter: alpha{opacity:30};
opacity:0.3;
}
</style>
<script type="text/javascript">
window.οnlοad=function()
{
var oDiv=document.getElementById('div1');
oDiv.οnmοuseοver=function()
{
startMove(100);
}
oDiv.οnmοuseοut=function()
{
startMove(30);
}
}
var timer=null;
var alpha=30;
function startMove(iTarget)
{
varoDiv=document.getElementById('div1');
clearInterval(timer);
timer=setInterval(function(){
var speed=0;
if (alpha>iTarget)
{
speed=-10;
}
else{
speed=10;
}
if (alpha==iTarget)
{
clearInterval(timer);
}
else{
alpha+=speed;
oDiv.style.filter='alpha(opacity:'+alpha+')';
oDiv.style.opacity=alpha/100;
}
},30)
}
</script>
<body>
<div id="div1"></div>
</body>
</html>
JS缓冲动画
缓冲运动中:向上取整Math.ceil(),向下取整Math.floor()
由于数值设置的原因,div移动到一定px后,进行相减再除20的运算后会出现小数,比如0.75,比如这时div移动到了290,程序里写到div的left=oDiv.offsetLeft+speed+'px',那么div的left就是290.75px,此时speed速度为0.75。而浏览器是不允许出现小数的,会把0.75去掉,那么就速度为0 不动了。那么div的left就变成了290,下次执行时div的left是290,算出来速度还是0.75,浏览器又省略了小数,结果就是div停在了290px,到不了目标点300。
所以向右移动 速度为正 就将变成小数的速度 向上取整 为1
向左移动 速度为负 就将变成负小数的速度向下取整
取整原因:因为有除法,当offsetLeft值变的越来越小时,最后相除会使speed变成小数,从而offsetLeft与speed相加会有小数,又因显示器的最小像素单位是1px,所以浏览器默认向下取整(变小,即floor),将小数省略,小数省略后,最终的值会变小,从而导致程序无法进入if判断,进入死循环。
这一点可以用console.log(speed)可以验证,speed的log会一直输出,因为程序死循环了
Math.floor()向取整;
Math.ceil()向上取整;
Math.round()四舍五入;
var speed = speed>0?Math.ceil(speed):Math.floor(speed);
如果(目标值-当前值)/10 不能整除的话。运动到最后,是1~9之间的数字来除以10,结果是个小于1的小数,如果用Math.floor(speed)向下取整,那就是0,speed=0,意味着不再发生变化。也就是说,当速度大于0的时候,如果用Math.floor(speed),最后不到10个像素的时候,就不会动了。所以要用Math.ceil向上取整。同理,当速度<0时,要用Math.ceil()取整。
<!DOCTYPE html>
<html>
<head>
<title>动画</title>
<meta charset="utf-8">
<style type="text/css">
body,div,span{
margin: 0;
padding: 0;
}
#div1{
width: 200px;
height: 200px;
background: red;
position: relative;
left: -200px;
top: 0;
}
#div1 span{
width: 20px;
height: 50px;
background: blue;
position: absolute;
left: 200px;
top: 75px;
}
</style>
<script type="text/javascript">
window.οnlοad=function()
{
varoDiv=document.getElementById('div1');
oDiv.οnmοuseenter=function()
{
startMove(0);
}
oDiv.οnmοuseleave=function(){
startMove(-200);
}
}
var timer =null;
function startMove(iTarget){
clearInterval(timer);
varoDiv=document.getElementById('div1');
timer=setInterval(function(){
varspeed=(iTarget-oDiv.offsetLeft)/20;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
if(oDiv.offsetLeft == iTarget) {
clearInterval(timer);
}
else{
oDiv.style.left=oDiv.offsetLeft+speed+'px';
}
},35)
}
</script>
</head>
<body>
<div id="div1" ><span id="share">分享</span></div>
</body>
</html>
多物体动画:
HTML代码:
<!DOCTYPE html>
<html>
<head>
<title>JS链式动画</title>
<meta charset="utf-8">
</head>
<style type="text/css">
body,ul,li{
margin: 0;
padding: 0;
}
ul,li{
list-style: none;
}
ul li{
width: 200px;
height: 100px;
background: yellow;
margin-bottom: 20px;
border: 4px solid #000;
filter:alpha(opacity:30);
opacity: 0.3;
}
</style>
<script src="js/move.js"></script>
<script type="text/javascript">
window.οnlοad=function(){
varLi=document.getElementById('li1');
Li.οnmοuseοver=function(){
startMove(Li,'width',400,function(){
startMove(Li,'height',200,function(){
startMove(Li,'opacity',100);
});
});
}
Li.οnmοuseοut=function(){
startMove(Li,'opacity',30,function(){
startMove(Li,'height',100,function(){
startMove(Li,'width',200);
});
});
}
}
</script>
<body>
<ul>
<li d="li1"></li>
</ul>
</body>
</html>
JS方法:
function getStyle(obj,attr){
if (obj.currentStyle) {
returnobj.currentStyle[attr];
}
else{
returngetComputedStyle(obj,false)[attr];
}
}
//var timer=null;
function startMove(obj,attr,iTarget,fn){
clearInterval(obj.timer);
obj.timer=setInterval(function(){
//1.取当前的值
varicur=0;
if(attr=='opacity') {
icur= parseFloat(getStyle(obj,attr))*100;
}
else{
icur =parseInt(getStyle(obj,attr));
}
//2.算速度
var speed =(iTarget-icur)/8;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
//3.检测停止
if (icur==iTarget) {
clearInterval(obj.timer);
if (fn) {
fn();
}
}
else{
if (attr=='opacity') {
obj.style.filter='alpha(opacity:'+(icur+speed)+')';
obj.style.opacity=(icur+speed)/100;
}else{
obj.style[attr]=icur+speed+'px';
}
}
},30)
}
parseFloat() 解析一个字符串并返回一个浮点数。
parseInt() 解析一个字符串并返回一个整数。
var iNum1 =parseInt("12345red"); //返回 12345
var iNum1 =parseInt("0xA"); //返回 10
var iNum1 =parseInt("56.9"); //返回 56
var iNum1 =parseInt("red"); //返回 NaN
var fNum1 =parseFloat("12345red"); //返回 12345
var fNum2 =parseFloat("0xA"); //返回 NaN
var fNum3 =parseFloat("11.2"); //返回 11.2
var fNum4 =parseFloat("11.22.33"); //返回 11.22
var fNum5 =parseFloat("0102"); //返回 102
var fNum1 =parseFloat("red"); //返回 NaN
所有offset属性的值都会包括边框值和padding,需要用getstyle属性来实现。
obj.currentStyle[attr];//针对IE浏览器
obj.getComputerStyle(obj,false)[attr];//针对FireFox浏览器
getstyle封装属性时注意区别opacity,可以把传入属性是透明度的情况挑出来,单独进行改写,区别有正常height,width整型转换用parseInt,但是透明度要用parseFloat,最后取值是应该加上math.round()让结果四舍五入在正确范围内。赋值转换要注意兼容问题,IE是filter,其他浏览器是opacity
链式动画:
链式动画:一个动画执行完毕后,紧接着自动执行另一个动画。
实现:给startMove函数添加一个参数func,用于传入一个函数。
function getStyle(obj,attr){
if (obj.currentStyle) {
returnobj.currentStyle[attr];
}
else{
returngetComputedStyle(obj,false)[attr];
}
}
//var timer=null;
functionstartMove(obj,attr,iTarget,fn){
clearInterval(obj.timer);
obj.timer=setInterval(function(){
//1.取当前的值
varicur=0;
if(attr=='opacity') {
icur= parseFloat(getStyle(obj,attr))*100;
}
else{
icur= parseInt(getStyle(obj,attr));
}
//2.算速度
var speed =(iTarget-icur)/8;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
//3.检测停止
if (icur==iTarget) {
clearInterval(obj.timer);
if (fn) {
fn();
}
}
else{
if (attr=='opacity') {
obj.style.filter='alpha(opacity:'+(icur+speed)+')';
obj.style.opacity=(icur+speed)/100;
}else{
obj.style[attr]=icur+speed+'px';
}
}
},30)
}
同时运动的运动框架:
function getStyle(obj,attr)
{
if (obj.currentStyle)
{
return obj.currentStyle[attr];
}
else
{
return getComputedStyle(obj,false)[attr];
}
}
//var timer=null;
function startMove(obj,json,fn)
{
var flag=true;//假设
clearInterval(obj.timer);
obj.timer=setInterval(function()
{
for(var attr in json)
{
//1.取当前的值
variCur=0;
if(attr=='opacity')
{
iCur= parseFloat(getStyle(obj,attr))*100;
}
else
{
iCur= parseInt(getStyle(obj,attr));
}
//2.算速度
var iSpeed=(json[attr]-iCur)/8;
iSpeed=iSpeed>0?Math.ceil(iSpeed):Math.floor(iSpeed);
//3.检测停止
if (iCur!=json[attr])
{
flag=false;
}
if (attr=='opacity')
{
obj.style.filter='alpha(opacity:'+(iCur+iSpeed)+')';
obj.style.opacity=(iCur+iSpeed)/100;
}
else
{
obj.style[attr]=iCur+iSpeed+'px';
}
}
if (flag)
{
clearInterval(obj.timer);
if (fn)
{
fn();
}
}
},30)
}