JavaScript进阶之--DOM事件、动画(运动框架)

DOM事件

一、事件流

描述的是从页面中接收事件的顺序(当你点击一个容器里的子控件时,默认同时也点击了这个父容器)。

事件冒泡(ie):事件最开始由最具体的元素接收,然后逐级向上传播到最不具体的结点(子 -- 父 -- 祖父 --..--document )

事件捕获(ne):不具体的结点首先接收到事件,最具体的结点最后接收到,与冒泡相反


二、事件处理程序

1、HTML事件:直接在标签里添加的事件

<input id="btn" type="button" onclick="fun()" value="按钮"/>    //log()是定义在js中的一个函数

  缺点:HTML和JS代码紧密的耦合在一起

      2、DOM 0级事件:把一个函数赋值给一个事件 【ie】

var btn=document.getElementById('btn');
btn.onclick = function(){			//添加事件
	console.log('被点击了');
}
btn.onclick = null;		//删除事件

      3、DOM 2级事件:定义了两个方法用于处理和删除事件 (chrome)

addEventListener( ...)、removeEventListener(event, listener, useCapture) :第一个参数 要处理的事件名、第二个参数事件处理的函数、第三个布尔值,表明事件是在冒泡阶段(false)还是捕获阶段(true)时调用    

btn.addEventListener("click", function(){
	console.log('addEvent被点击的');
}, false);
btn.removeEventListener("click",fun,false);   //通过addEL添加的事件处理只能有removeEL删除

 4、IE 事件处理程序:添加 、删除事件 ( IE8之前只支持冒泡、欧普)

attachEvent( ...)、detachEvent(eventType, function) :第一个参数 事件处理名称、第二个 事件处理的函数

 

btn.attachEvent("onclick",log );     //注意是带 on 的

 

5、IE跨浏览器的事件处理程序:考虑兼容 ,需要封装一个对象方法

/**
 * 解决浏览器兼容 事件处理程序
 * @param {[type]} element 事件源
 * @param {[type]} type    事件处理类型(click/mouseover...)
 * @param {[type]} handler 处理事件
 */
function addHandler(element,type,handler){
	//如果支持DOM 2级事件处理程序
	if(element.addEventListener){
		element.addEventListener(type,handler,false);
	} else if(element.attachEvent){		//支持IE 的事件处理程序
		  element.attachEvent('on'+type,handler);
	  } else{		//支持DOM 0级
	  		element['on'+type]= handler;
	    }
}
//移除事件
function removeHandler(element,type,handler){
	//如果支持DOM 2级事件处理程序
	if(element.addEventListener){
		element.removeEventListener(type,handler);
	} else if(element.attachEvent){		//支持IE 的事件处理程序
		  element.detachEvent('on'+type,handler);
	  } else{		//支持DOM 0级
	  		element['on'+type]= null;
	    }
}//调用方法
addHandler(btn4,'click',fun);
removeHandler(btn4,'click',fun);

三、事件对象

触发DOM上事件产生的对象

1、DOM中的事件对象event ( 调用 :  event.type )  ---IE无用

    1)type :事件类型( click )

   2)target :事件目标( 事件源)

 3)stopPropagation():阻止事件冒泡

 4)preventDefault(): 阻止事件的默认行为 (a标签的跳转页面)

2、IE中的事件对象( window.event )

在使用event时要先做一个兼容性:var event= event || window.event;

1)type :事件类型( click )

2) srcElement:事件源  【IE8获取得到的类型是object】

3) cancelBubble:阻止事件冒泡(这是一个属性,true为阻止冒泡)

4) returnValue:阻止默认事件(false表示阻止事件默认行为)

3、封装方法解决兼容性

//封装事件方法的对象
		var eventUtil={
			//获取事件对象
			getEvent:function(event){
				return  event|| window.event;	//兼容IE
			},
			//获取事件对象类型
			getType:function (event){
				return event.type;

			},//事件源	
			getTarget:function (event){
				return event.target || event.srcElement;
			},//阻止事件冒泡
			stopPropagation:function (event){
				if(event.stopPropagation){		
					event.stopPropagation();
				} else{			//IE事件
					 event.cancelBubble=true;	
				  }
			},//阻止默认行为
			preventDefault:function (event){
				if(event.preventDefault){
					event.preventDefault();
				}  else{	//IE事件
					  event.returnValue=false;
				  }
			}
		}


四、事件类型

1、键盘事件
keyDown:按下键盘上的任意键触发,按住不放则重复触发
keyPress:按下键盘上的字符键触发,按住不放则重复触发
keyUp:释放键盘上的键时触发

keyCode:根据键盘码确定按下的键,从event中获取
document.keyUp=function(event){	 var event=event || window.event;  console.log(event.keyCode); }

动画

一、速度动画

/**
		 * 实现对象的左右移动
		 * @param  {[type]} obj    目标对象
		 * @param  {[type]} target 移动终点
		 * @param  {[type]} speed  移动速度
		 * @return {[type]}        无返回
		 */
		function move(obj,target,speed){
			clearInterval(obj.timer);	//清空计时器,
			obj.timer=setInterval(function(){	//自定义定时器
				var left=obj.offsetLeft;	//number 数值				
				if(left>target){	//当前位置在目标值的右边,则速度为负
					speed=speed <0 ? speed:-speed;	//速度值,保持为负数
					console.log('speed'+speed);	
				} 
				//如果移动的某一时间段在一定的范围内,则直接设为目标值
				if( Math.abs( Math.abs(left)-Math.abs(target) ) < Math.abs(speed)  ){
					obj.style.left=target+'px';		//达到目标值
					console.log('=='+left);
					clearInterval(obj.timer);
				} else{
					left+=speed;	//移动
					obj.style.left=left+'px';
					console.log('left'+left);
				}	
				
			},50);
		}

二、透明度动画

<!-- 样式-->
div{
	width: 200px;
	height: 200px;
	background-color: blue;
	filter:alpha(opacity:10);	/*滤镜效果*/
	opacity:0.1;
}
var alpha=10;	//先获取opacity的值
/**
* 改变透明度的动画 ---要先取得当前对象的opacity(透明度)
* @param  {[type]} obj    目标对象
* @param  {[type]} target 目标透明度值  0-1
* @param  {[type]} speed  变化速度  1-100
* @return {[type]}        无返回值
*/
function changeOpacity(obj,target,speed){

clearInterval(obj.timer);		//清除

obj.timer=setInterval(function(){	//自定义的定时器
	var current=alpha/100;	//当前透明度0-1		

	if(current>target){	    //当前透明度更低,更不透明(越接近1)
		speed=speed <0 ? speed:-speed;	//速度值,保持为负数
		console.log('speed'+speed);	
	} 
	//如果透明度的变化将达到目标值,则直接设为目标值
	if( Math.abs( Math.abs(current)-Math.abs(target) ) < Math.abs(speed/100)  ){
		obj.style.filter='alpha(opacity:'+target*100+')';		//达到目标值
		obj.style.opacity=target;	//设为目标值

		clearInterval(obj.timer);
	}  else{
		alpha+=speed;	//改变透明度  0-100
		console.log("alpha"+alpha);
		obj.style.filter='alpha(opacity:'+alpha+')';		
		obj.style.opacity=alpha/100;	//设置透明度属性

	  }	
	
},50);

}


//解决多物体同时运行的冲突

obj.alpha=10;   //通过自定义属性的方式获取到透明度的值




三、缓冲动画

/**
		 * 缓冲运动,速度是逐渐变小
		 * @param  {[type]} obj    目标对象
		 * @param  {[type]} target 移动终点
		 * @param  {[type]} speed  移动速度(可不传参
		 * @return {[type]}        无返回
		 */
		function move(obj,target,speed){

			clearInterval(obj.timer);	//清空计时器,
			obj.timer=setInterval(function(){	//自定义定时器
				var left=obj.offsetLeft;	//number 数值	
				speed=(target-left)/10;
				console.log("speed1::"+speed);
				speed= speed > 0 ? Math.ceil(speed) : Math.floor(speed);
								//解决小数【注意是向上/向下取整
				console.log("speed2::"+speed);
				//如果移动的某一时间段在一定的范围内,则直接设为目标值
				if(left==target){
						//达到目标值
					clearInterval(obj.timer);
				} else{
					obj.style.left=left+speed+'px';
				 }	
			},50);
		}


四、自定义属性的动画

获取样式:作用请看 来源(当变化宽高,而设定css样式时有border属性,最后变化是不一样的 )

/**
		 * 获取对象的样式
		 * @param  {[type]} obj  目标对象
		 * @param  {[type]} attr 样式参数
		 * @return {[type]}      对应的样式值
		 */
		function getStyle(obj,attr){
			console.log(typeof attr);
			if(obj.currentStyle){
				return obj.currentStyle[attr];		//ie浏览器
			}  else {
				 return getComputedStyle(obj,false)[attr];	//火狐
			  }
		}
		//调用:
		console.log(getStyle(box,'width')); 
/**
		 * 自定义属性的动画,改变样式【宽高等单位为px的属性】
		 * @param  {[type]} obj    目标对象
		 * @param  {[type]} target 变化结果
		 * @param  {[type]} attr   变化的属性
		 */
		function move(obj,target,attr){

			clearInterval(obj.timer);		//清空计时器,
			obj.timer=setInterval(function(){		//自定义定时器
				var myStyle=parseInt( getStyle(obj,attr) );	 //获取当前属性值,并转化为number
				console.log(myStyle);
				var speed=(target-myStyle)/10;
				speed= speed > 0 ? Math.ceil(speed) : Math.floor(speed);
				if(myStyle==target){
						//达到目标值
					clearInterval(obj.timer);
				} else{
					obj.style[attr] = myStyle+speed+'px';
				 }	
			},50);
		}
//透明度属性
//传参数时,透明度为0-100,对应0-1
	if(attr==='opacity'){	//判断是否为透明度
		var myStyle=parseFloat( getStyle(obj,'opacity') )*100 ;	//小数
		myStyle=Math.round(myStyle); //四舍五入解决不精确
	}
	if(attr==='opacity'){
		obj.style.filter='alpha(opacity:'+myStyle+speed+')';	
			//设置透明度
		obj.style[attr]=(myStyle+speed)/100 ;	
	

五、链式动画(连续动画)

增加函数参数,当执行完动画后,调用了此回调函数,再次进行动画

function move(obj,target,attr,fun){
	....
	if(myStyle==target){
			//达到目标值
		clearInterval(obj.timer);
		if(fun){		//判断是否有值
			fun();		  //设为并执行函数
		}
	}
}
box.οnmοuseοver=function(){
	move(box,100,'opacity',function(){	//回调函数
		move(box,100,'width',400);
	});	


五、完成动画--运动框架--实现多物体同时进行 多动画





	
   
   
	运动框架--速度动画
	


	
   
   
<script type="text/javascript"> var box=document.getElementById('box'); var box2=document.getElementById('box2'); box.οnmοuseοver=function(){ var json={'width':201,'height':300,'opacity':20}; move(box,json); move(box2,json); } box.οnmοuseοut=function(){ var json2={'width':200,'height':200,'opacity':100}; move(box,json2); move(box2,json2); } /** * 运动框架--可完成多物体同时进行 多个动画 * @param {[type]} obj 对象 * @param {[type]} jsonTarAttr json={"变化的属性attr":变化的目标值} * @param {[type]} fun 回调函数 */ function move(obj,jsonTarAttr,fun){ clearInterval(obj.timer); //清空计时器, obj.timer=setInterval(function(){ //自定义定时器 for(var attr in jsonTarAttr){ //遍历json var flag=true; //解决当一个动画已经完成时,清除了定时器使后续的动画还未完成就结束 if(attr==='opacity'){ var myStyle=parseFloat( getStyle(obj,'opacity') )*100 ; //小数 myStyle=Math.round(myStyle); //四舍五入解决不精确 } else{ var myStyle=parseInt( getStyle(obj,attr) ); } var speed=(jsonTarAttr[attr]-myStyle)/10; speed= speed > 0 ? Math.ceil(speed) : Math.floor(speed); if(myStyle!=jsonTarAttr[attr]){ flag=false; //动画为全部完成的标记 console.log("d"); if(attr==='opacity'){ obj.style.filter='alpha(opacity:'+myStyle+speed+')'; //设置透明度 obj.style[attr]=(myStyle+speed)/100 ; } else { obj.style[attr] = myStyle+speed+'px'; } } } if(flag){ //动画全部完成 clearInterval(obj.timer); if(fun){ fun(); //设为并执行函数 } } },50); } /** * 获取对象的样式 * @param {[type]} obj 目标对象 * @param {[type]} attr 样式参数 * @return {[type]} 对应的样式值 */ function getStyle(obj,attr){ if(obj.currentStyle){ return obj.currentStyle[attr]; //ie浏览器 } else { return getComputedStyle(obj,false)[attr]; //火狐 } } </script>















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芒果-橙

谢谢啦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值