js简单的切割效果和容器的拖拽

参考:cloudgamer大神的博文(推荐)。

事件绑定:bind和bindAsEventListener。

bind(obj,fun)可以将函数fun绑定到对象obj上,但是在fun函数中绑定参数。

function bind(obj,fun) //将函数fun绑定到某个对象obj
	{
		return function()
		{
			return fun.apply(obj,arguments);
		}
	}

bindAsEventListener(obj,fun)同bind可以将函数fun绑定到对象obj上,但是可以在fun函数中绑定参数,同时会将event作为第一个参数。

var bindAsEventListener = function(obj, fun) //将函数绑定到对象的某个事件上,作为事件处理函数
	{
		var args = Array.prototype.slice.call(arguments).slice(2);
		return function(event) 
		{
			return fun.apply(obj, [event || window.event].concat(args));
		}
	}
如果传入参数形如bindAsEventListener(this,this.clickEvent,name,age....)的形式。那么bindAsEventListener首先会利用Array.prototype.slice.call(argument).slice(2)的方法,将arguments作为一个参数列表,利用call方法将arguments参数列表转化成为数组的参数传入到Array中去,然后再可以调用Array.slice(2)的方法截取从[2,arguments.length)的参数。具体测试代码为:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<script type="text/javascript">
	var array=new Array(1,2,3,4,5,6,7);
	array=array.slice(2); //截取数组[2,array.length)中的数据
	//alert(array);
	function  test(a,b,name,age,password)
	{
		alert(arguments); //arguments可以获取所有的参数列表
		alert(Array.prototype.slice.call(arguments).slice(2)); //截取从[2,arguments.length)的参数列表,弹出xuzengqiang,12,123456
	}
	test(1,2,"xuzengqiang",12,"123456");
</script>
<body>
</body>
</html>
bindAsEventListener最后的return语句中apply的参数列表为[event ||  window.event].contact(args);这里表示将event事件作为fun的第一个参数。args保存的参数列表作为fun的后续参数。

bindAsEventListener和bind的测试用例如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<script type="text/javascript">
	var bind=function(obj,fun)  //将函数fun绑定到对象obj上
	{
		return function()
		{
			return fun.apply(obj,arguments);
		}
	}
	var bindAsEventListener=function(obj,fun) 
	{
		var args = Array.prototype.slice.call(arguments).slice(2);
		return function(event) 
		{
			return fun.apply(obj, [event || window.event].concat(args)); //将事件event绑定到eventFun作为第一个参数
		}
	}
	var Class=
	{
		create:function()
		{
			return function()
			{
				this.initialize.apply(this,arguments);
			}
		}
	};
	var bindTest=Class.create();
	bindTest.prototype=
	{
		initialize:function(obj)
		{
			
			var $button=document.getElementById(obj);
			var name="xuzengqiang";
			//$button.οnclick=bindAsEventListener(this,this.clickEvent,name); //name作为clickEvent的参数
			$button.οnclick=bind(this,this.bindClick);
		},
		clickEvent:function(e,name)
		{
			alert(name+"你竟敢点击我!");
		},
		bindClick:function()
		{
			alert("绑定点击事件!");
		}
	}
	window.οnlοad=function()
	{
		new bindTest("bind");
	}
</script>
<body>
	<button id="bind">点击</button>
</body>
</html>

效果图预览:其中8个点可以任意方向拖动,用来改变容器大小,容器本身可以拖动。

实现:主要利用methoBind()绑定8个方向点的拖动函数,通过mousedown事件来触发this.dataInit进行数据初始化开始缩放,

this.dataInit主要设置缩放程序this._fun和缩放参数,然后利用mousemove事件触发resize方法进行拖放后容器样式的设置,mouseup触发Stop方法停止拖放。

缩放原理:

以向上拖动和向下拖动为例:

向上拖动的时候:下侧必须固定,同时高度也要发生变化

方式一:自增或自减,每次更新拖动前后的坐标,然后让高度自增或自减拖动前后的坐标差值,这样做相对而言叫麻烦,但是思路清晰,需要每次都更新拖动前的坐标,将这次拖动后的坐标作为下一次拖动前的坐标。

方式二:只记录鼠标按下时坐标位置,然后每次鼠标拖动的时候,只记录每次拖动后的坐标与鼠标按下时坐标和容器高度的变化,不需要进行高度自增或自减操作,只需进行赋值即可。推荐方式二:

首先记录高度的变化:

this.styleHeight=Math.max(this.sideDown-e.clientY,0);

top值的变化:(其中this.bottomPosition表示最底边的高度位置)

this.styleTop=this.bottomPosition-this.styleHeight;

top值和容器高度变化的分析:


向下拖动,这时候保证顶部不移动,top值不用发生改变,只需修改高度即可。

<span style="font-family:Microsoft YaHei;">this.styleHeight=Math.max(e.clientY-this.sideUp,0);</span>
高度分析:


其它方向分析同理。

div层的拖动原理:只需修改left和top值,width和height不会发生改变。

方式一:获取鼠标拖动前位置(startX,startY),然后当鼠标拖动的时候记录拖动后的坐标(e.clientX,e.clientY)。这个时候容器的left和top分别自增对应坐标的差值即可。

每拖动一次重新修改startX=e.clientX,startY=e.clientY即可。

this.styleLeft+=e.clientX-this.startX;
this.styleTop+=e.clientY-this.startY;
this.startX=e.clientX;
this.startY=e.clientY;  

方式二:同样只需记录鼠标按下的坐标,然后记录每次鼠标拖动后的坐标(e.clientX,e.clientY),找出拖动后的坐标与鼠标按下坐标和left、top值的关系。

以left变更为例:

this.styleLeft=e.clientX-this.dragLeft;

分析:


完整代码:(css样式方面不做分析)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />  
<title>test</title>  
<style type="text/css">  
	*{margin:0;padding:0}  
	.borderDiv{width:100px;height:100px;border:1px dashed #AFAFAF;position:absolute;top:100px;left:30px;
		cursor:move;z-index:4;}  
	.move{width:6px;height:6px;background:#FFFFFF;border:2px solid #AFAFAF;position:absolute;border-radius:10px;z-index:5;}  
	.left,.right{cursor:e-resize;top:50%;margin-top:-5px;}  
	.leftBottomMove,.rightTopMove{cursor:ne-resize}  
	.leftTopMove,.rightBottomMove{cursor:nw-resize}  
	.top,.bottom{cursor:n-resize}  
	.leftTopMove{top:-5px;left:-5px;}  
	.top{left:50%;margin-left:-5px;top:-5px}  
	.rightTopMove{right:-5px;top:-5px}  
	.left{left:-5px}  
	.right{right:-5px}  
	.leftBottomMove{bottom:-5px;left:-5px}  
	.bottom{bottom:-5px;left:50%;margin-left:-5px}  
	.rightBottomMove{bottom:-5px;right:-5px}  
</style>  
</head>  
  
<script type="text/javascript"> 
	var isIE=(document.all)?true:false; 
	function $()
	{
		if(arguments.length==1 && typeof arguments[0] == "string")
		{
			return document.getElementById(arguments[0]);
		}
	};
	var Class=
	{
		create:function()
		{
			return function()
			{
				this.initialize.apply(this,arguments);
			}
		}
	};
	Object.extend=function(destination,source) 
	{
		for(var property in source)
		{
			destination[property]=source[property];
		}
		return destination;
	};
	Object.prototype.extend=function(obj)
	{
		return Object.extend.apply(this,[this,obj]);
	};
	var Event=(function()
	{
		return {
			addEventHandler:function(target,eventType,fun) 
			{
				if(target.addEventListener)
				{
					target.addEventListener(eventType,fun,false);
				}
				else if(target.attachEvent)
				{
					target.attachEvent("on"+eventType,fun);
				}
				else
				{
					target["on"+eventType]=fun;
				}
			},
			removeEventHandler:function(target,eventType,fun)
			{
				if(target.removeEventListener)
				{
					target.removeEventListener(eventType,fun,false);
				}
				else if(target.detachEvent)
				{
					target.detachEvent("on"+eventType,fun);
				}
				else
				{
					target["on"+evenetType]=false;
				}
			}
		}
	}());
	function bind(obj,fun) //将函数fun绑定到某个对象obj
	{
		return function()
		{
			return fun.apply(obj,arguments);
		}
	}
	var bindAsEventListener = function(obj, fun) //将函数绑定到对象的某个事件上,作为事件处理函数
	{
		var args = Array.prototype.slice.call(arguments).slice(2);
		return function(event) 
		{
			return fun.apply(obj, [event || window.event].concat(args));
		}
	}
	//扩展document中的getElementsByClassName方法,即通过class类名的值获取元素对象
	document.getElementsByClassName=function(className)
	{
		var elements=new Array(),
			allElements=document.getElementsByTagName('*') || document.all; 
		for(var i=0,maxLen=allElements.length; i<maxLen; i++)
		{
			var child=allElements[i],
				classNames=child.className.split(' '); 
			for(var j=0,max=classNames.length;j<max;j++) //不推荐for(var j=0;j<classNames.length;j++)方式,因为每次都会计算长度
			{
				if(className==classNames[j])
				{
					elements.push(child);
					break;
				}
			}
		}
		return elements;
	}
	
	var SimpleDrag=Class.create();
	SimpleDrag.prototype=
	{
		initialize:function(obj,options) //obj为容器对象,
		{
			this.content=$(obj);
			this._resize = bindAsEventListener(this,this.resize);
			this._stop = bind(this,this.Stop);
		},
		setOptions:function(options) //参数设置
		{
		},
		methodBind:function(obj) //八个方向点方法绑定 
		{
			var current=document.getElementsByClassName(obj)[0],fun; //fun为方法
			if(!current) return ;
			switch(obj)
			{
				case "top":
					fun=this.up;
					break;	
				case "bottom":
					fun=this.down;
					break;	
				case "left":
					fun=this.left;
					break;
				case "right":
					fun=this.right;
					break;		
				case "leftTopMove":
					fun=this.leftUp;
					break;
				case "rightTopMove":
					fun=this.rightUp;
					break;	
				case "leftBottomMove":
					fun=this.leftDown;
					break;	
				case "rightBottomMove":
					fun=this.rightDown;
					break;					
				default: //否则对容器对象进行拖拽
					fun=this.drag;	
			}
			Event.addEventHandler(current,"mousedown",bindAsEventListener(this,this.dataInit,fun)); //fun作为dataInit的参数
		},
		dataInit:function(e,fun) //数据初始化
		{
			//防止事件冒泡,IE:e.cancelBubble=true,FF:e.stopPropagation()
			e.stopPropagation?e.stopPropagation():(e.cancelBubble=true);
			this._fun=fun;
			this.styleWidth=this.content.clientWidth; //容器可以宽度,不包括边框和滚动条
			this.styleHeight=this.content.clientHeight;
			this.styleLeft=this.content.offsetLeft; //容器向左偏移的距离
			this.styleTop=this.content.offsetTop;
			
			this.sideLeft = e.clientX - this.styleWidth; //左侧定位参数,e.clientX表示事件发生位置相对于浏览器的横坐标
			this.sideRight = e.clientX + this.styleWidth;
			this.sideUp = e.clientY - this.styleHeight;
			this.sideDown = e.clientY + this.styleHeight;
			
			this.dragLeft=e.clientX-this.styleLeft;
			this.dragTop=e.clientY-this.styleTop;
			
			this.rightPosition=this.styleWidth+this.styleLeft; //最右边的位置
			this.bottomPosition=this.styleHeight+this.styleTop; //最底部的位置
			
			Event.addEventHandler(document,"mousemove",this._resize);
			Event.addEventHandler(document,"mouseup",this._stop);
		},
		resize:function(e) //当拖动后重新修改容器的大小
		{
			this._fun(e); //改变
			with(this.content.style)
			{
				width=this.styleWidth+"px",height=this.styleHeight+"px";
				top=this.styleTop+"px",left=this.styleLeft+"px";
			}
		},
		up:function(e) //向上移动,此时容器的top值也要随之改变,从而保证下侧固定
		{
			this.styleHeight=Math.max(this.sideDown-e.clientY,0);
			this.styleTop=this.bottomPosition-this.styleHeight;
		},
		down:function(e)
		{
			this.styleHeight=Math.max(e.clientY-this.sideUp,0);
		},
		left:function(e)
		{
			this.styleWidth=Math.max(this.sideRight-e.clientX,0);
			this.styleLeft=this.rightPosition-this.styleWidth;
		},
		right:function(e)
		{
			this.styleWidth=Math.max(e.clientX-this.sideLeft,0);
		},
		leftUp:function(e)
		{
			this.left(e);
			this.up(e);
		},
		rightUp:function(e)
		{
			this.right(e);
			this.up(e);
		},
		leftDown:function(e)
		{
			this.left(e);
			this.down(e);
		},
		rightDown:function(e)
		{
			this.right(e);
			this.down(e);
		},
		drag:function(e)
		{
			this.styleLeft=e.clientX-this.dragLeft;
			this.styleTop=e.clientY-this.dragTop;
		},
		Stop:function() //停止缩放
		{
			Event.removeEventHandler(document,"mousemove",this._resize);
			Event.removeEventHandler(document,"mouseup",this._stop);
		}
	}
	window.οnlοad=function()
	{
		var resize=new SimpleDrag("borderDiv");
		resize.methodBind("top"); //向上移动
		resize.methodBind("bottom"); //向下移动
		resize.methodBind("left"); //向左移动
		resize.methodBind("right"); //向右移动
		resize.methodBind("leftTopMove");
		resize.methodBind("rightTopMove");
		resize.methodBind("leftBottomMove");
		resize.methodBind("rightBottomMove");
		resize.methodBind("borderDiv");
	}
</script>  
<body style="">  
	<div class="borderDiv" id="borderDiv">  
		<div class="leftTopMove move"></div>  
		<div class="top move"></div>  
		<div class="rightTopMove move"></div>  
		<div class="left move"></div>  
		<div class="right move"></div>  
		<div class="leftBottomMove move"></div>  
		<div class="bottom move"></div>  
		<div class="rightBottomMove move"></div> 
	</div> 
</body>  
</html>  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值