一个简单的拖拽研究了快一周,恶心的我呦...好在终于整明白了,下面和大家一起交流下。拖拽原理:
鼠标按下时,记录当前鼠标和拖动层的坐标,并且拖动状态设为可拖动;
鼠标移动时,判断拖动状态,如果可拖动,那么根据当前的鼠标坐标以及鼠标按下时记录的初始坐标,计算出拖动层的位置,实行拖动;
鼠标弹起时,将拖动状态改为不可拖动。遇到的问题:
1.移动较快时,拖拽失效;
2.火狐中,拖拽动作与浏览器的某些功能有冲突,导致动作不流畅或失效;下面我一步步的把我的修改过程贴出来,大家一起交流啊~
鼠标按下时,记录当前鼠标和拖动层的坐标,并且拖动状态设为可拖动;
鼠标移动时,判断拖动状态,如果可拖动,那么根据当前的鼠标坐标以及鼠标按下时记录的初始坐标,计算出拖动层的位置,实行拖动;
鼠标弹起时,将拖动状态改为不可拖动。遇到的问题:
1.移动较快时,拖拽失效;
2.火狐中,拖拽动作与浏览器的某些功能有冲突,导致动作不流畅或失效;下面我一步步的把我的修改过程贴出来,大家一起交流啊~
解决方案 »
- 【window窗体返回值问题】
- 怎样在ASP页面里用GET方法得到变量字符串?
- removeChild方法,参数无效???
- javascript脚本放在<script src=xxx></script>中有错,直接放到<head>中的就无错???
- 简单的javascript问题
- 哪位给一份javascript 的帮助文档?
- history.back()能否只让某一个iframe返回?
- 如何预先截入图片,并显示?
- 使用insertRow动态添加的表格行,在页面提交后怎么才能保留下来?
- 怎么判断一个链接是否存在
- jQuery中的document.ready和js中的window.onload速度对比
- 请问highcharts这个图表库如何?
另外:Y0=parseInt(moveObj.style.top+0);//?不清楚为什么一定要+0
<html>
<head>
<style>
#move{cursor:move; position:absolute; width:100px; height:100px; background:green;}
</style><script language="javascript">
//载入完成时执行
window.onload=function(){
var moveable=false;//初始化是否可拖动
var X0,Y0,eX0,eY0;//声明变量
var moveObj=document.getElementById('move');//获取到拖动对象
//鼠标按下
moveObj.onmousedown=function(e){//e只是一个参数,表示一个事件,名称可随便起
e=e||event;//鼠标事件在火狐里存在内存中可供函数直接调用;在IE里存放在window对象中,即window.event
eX0= e.clientX;//记录下拖动对象的坐标X0,Y0
eY0= e.clientY;
X0=parseInt(moveObj.style.left+0);//记录下mousedown事件发生时,鼠标的坐标eX0,eY0
Y0=parseInt(moveObj.style.top+0);//?不清楚为什么一定要+0
moveable=true;//拖动状态改为可拖动
}
//鼠标移动
moveObj.onmousemove=function(e){
if (moveable==true)
{
e=e||event;
var eX1= e.clientX;
var eY1= e.clientY;
moveObj.style.left=X0+eX1-eX0+"px";//由鼠标刚按下时记录的各个初始值,计算当前拖动对象的坐标
moveObj.style.top=Y0+eY1-eY0+"px";
}
}
//鼠标弹起
moveObj.onmouseup=function(e){
if(moveable) moveable=false;//状态改为不可拖动
}
}
</script>
</head><body>
<div id="move"></div>
</body>
</html>
百度了下,还有另一种方式,就是把事件全加在document上,然后判断事件目标是否为要拖拽的元素。我感觉应该是这种方式浏览器可以及时地感应到任何一个位置发生的事件,不至于鼠标移得快了就跟不上了...(菜鸟,欢迎交流~)
<html>
<head>
<style>
.move{cursor:move; position:absolute; width:100px; height:100px; background:green;}
</style><script language="javascript">
var X0,Y0;
var dragAble=false;
var dragObj;
document.onmousedown=function(e){
var oDragHandle=e? e.target:event.srcElement;
if(oDragHandle.className=='move')
{
dragObj=oDragHandle;
e=e||event;
eX0= e.clientX;
eY0= e.clientY;
X0=parseInt(dragObj.style.left+0);
Y0=parseInt(dragObj.style.top+0);
dragAble=true;
}
}
document.onmousemove=function(e){
if(dragObj)
{
e=e||event;
var eX1= e.clientX;
var eY1= e.clientY;
dragObj.style.left=X0+eX1-eX0+"px";
dragObj.style.top=Y0+eY1-eY0+"px";
}
}document.onmouseup=function(e){
if(dragObj) dragObj=null;
}</script>
</head><body>
<div class="move"></div>
</body>
</html>
1.在拖动块里加上内容,不论是空标签还是嵌套别的东西,只要是有内容,就不会出现那个虚影的问题;
2.样式控制,禁止选中。-moz-user-select:none;/*火狐禁止选中*/
下面代码中采用的第二种办法。
<html>
<head>
<style>
.move{cursor:move; position:absolute; width:100px; height:100px; background:green;-moz-user-select:none;/*火狐禁止选中*/}
</style>
<script language="javascript">
var X0,Y0;
var dragAble=false;
var dragObj;
document.onmousedown=function(e){
var oDragHandle=e? e.target:event.srcElement;
if(oDragHandle.className=='move')
{
dragObj=oDragHandle;
e=e||event;
eX0= e.clientX;
eY0= e.clientY;
X0=parseInt(dragObj.style.left+0);
Y0=parseInt(dragObj.style.top+0);
dragAble=true;
}
}
document.onmousemove=function(e){
if(dragObj)
{
e=e||event;
var eX1= e.clientX;
var eY1= e.clientY;
dragObj.style.left=X0+eX1-eX0+"px";
dragObj.style.top=Y0+eY1-eY0+"px";
}
}
document.onmouseup=function(e){
if(dragObj) dragObj=null;
}</script>
</head><body>
<div class="move"><!--<br/>如果样式规定里此div可选,并且没有内容的话,火狐会有bug--></div>
</body>
</html>
短一点的话效率我不大清楚,不过对初学者来说肯定是容易理解点儿。
然后那个拖拽的实现方式上。我觉得思路应该只有这个思路了。还有那个+0,我觉得很别扭,明明parseInt()已经转成整形了,为什么要在里面写个+0呢?
这两天找到了一个更正规的事件处理方式,就是IE:attachEvent(),w3c:addEventListener()
例:window.attachEvent ? obj.attachEvent("onmousedown", Foo): obj.addEventListener("mousedown", Foo, false);添加了事件监听之后,我很吃惊的发现在IE里也可以像火狐那样支持“以传参数的形式获取事件对象了”,信不信大家可以自己试一下,下面是代码。<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<style>
.move{cursor:move; position:absolute; width:100px; height:100px; background:green;-moz-user-select:none;/*火狐禁止选中*/}
</style>
<script language="javascript">
var X0,Y0,eX0,eY0;
var dragAble=false;
var dragObj;
var ie = (document.all) ? true : false;//是否为IEfunction dragStart(e){//现在参数e在IE里也是是直接可以供函数使用的,比如第16行。
var oDragHandle;
if(ie){
oDragHandle = e.srcElement;
}else{
oDragHandle = e.target;
}
if(oDragHandle.className=='move')
{
dragObj=oDragHandle;
eX0= e.clientX;
eY0= e.clientY;
X0=parseInt(dragObj.style.left+0);
Y0=parseInt(dragObj.style.top+0);
dragAble=true;
}
}
//拖拽
function drag(e){
if(dragAble)
{
var eX1= e.clientX;
var eY1= e.clientY;
dragObj.style.left=X0+eX1-eX0+"px";
dragObj.style.top=Y0+eY1-eY0+"px";
}
}
//停止拖拽
function dragEnd(){
dragAble=false;
}
//事件监听浏览器兼容
function addListener(element,eName,fn){
if(ie){// ie
element.attachEvent("on"+eName,fn);
}else {// firefox , w3c
element.addEventListener(eName,fn,false);
}
}//添加事件监听
window.onload = function(){
addListener(document,"mousedown",dragStart);//鼠标按下开始拖拽
addListener(document,"mousemove",drag);//拖拽
addListener(document,"mouseup",dragEnd);//弹起停止拖拽
}
//注:添加了事件监听之后,IE里也可以像火狐里那样直接拿事件对象当函数的参数来用了,不必再window.event。
//但是不大清楚这是为什么,或者是说我还有什么地方理解错了,求交流。QQ:1140215489
</script>
</head><body>
<div class="move"><!--<br/>如果样式规定里此div可选,并且没有内容的话,火狐会有bug--></div>
<div class="move" style="background:blue;left:200px"></div>
</body>
</html>
X0=parseInt(dragObj.style.left+0);
Y0=parseInt(dragObj.style.top+0);
--如果初始没有设置div的top值,浏览器dragObj.style.left是个空字符串,+0是为了让X0初始为0;如果拖动块不在左上角就不能这么写了,得先设置上top,left值,因为Obj.style.left只能获取行内样式,所以得换一种方法来获取当前的样式值。
//获取当前渲染样式
function getNowStyle(element,styleName){
var nowValue=parseInt(ie?element.currentStyle[styleName]:window.getComputedStyle(element,null)[styleName]);
return nowValue;
}<!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=UTF-8" />
<style>
.move{
cursor:move;
position:absolute;
top:10px;/*必须要设置,不然在IE里获取的.top为auto,无法进行算术运算*/
left:400px;
width:100px;
height:100px;
background:green;
-moz-user-select:none;/*火狐禁止选中*/
}
.food{background:blue;width:100px;height:100px;}
</style>
<script language="javascript">
var X0,Y0,eX0,eY0;
var dragAble=false;
var dragObj;
var ie = (document.all) ? true : false;//是否为IE//开始拖拽
function dragStart(e){
var oDragHandle;
if(ie){
oDragHandle = e.srcElement;
}else{
oDragHandle = e.target;
}
if(oDragHandle.className=='move'){
dragObj=oDragHandle;
eX0= e.clientX;
eY0= e.clientY;
X0=getNowStyle(dragObj,"left");//获取当前样式值
Y0=getNowStyle(dragObj,"top");
show(X0,Y0);
dragAble=true;
}
}
//拖拽
function drag(e){
if(dragAble){
var eX1= e.clientX;
var eY1= e.clientY;
dragObj.style.left=X0+eX1-eX0+"px";
dragObj.style.top=Y0+eY1-eY0+"px";
}
}
//停止拖拽
function dragEnd(){
dragAble=false;
}
//事件监听浏览器兼容
function addListener(element,eName,fn){
if(ie){// ie
element.attachEvent("on"+eName,fn);
}else {// firefox , w3c
element.addEventListener(eName,fn,false);
}
}
//添加事件监听
window.onload = function(){
addListener(document,"mousedown",dragStart);//鼠标按下开始拖拽
addListener(document,"mousemove",drag);//拖拽
addListener(document,"mouseup",dragEnd);//弹起停止拖拽
}
//当前渲染样式
function getNowStyle(element,styleName){
var nowValue=parseInt(ie?element.currentStyle[styleName]:window.getComputedStyle(element,null)[styleName]);
return nowValue;
}</script>
</head>
<body>
<div class="move"><!--<br/>如果样式规定里此div可选,并且没有内容的话,火狐会有bug--></div>
<div class="food"></div>
</body>
</html>
2.可以添加一个卡喉函数来降低CPU损耗..
---仅供参考---<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></HEAD> <BODY style="height:800px;">
<div id="testDiv" style="width:200px; height:200px; background:#f00; position:absolute; cursor:move"></div>
<script type="text/javascript">
var start =
(function(){
var i, // count
o, // HTML DOM
x,y;
function moving(e)
{
if(i++^6)//like if(!(i++===6))
return;
o.style.left=(e.screenX-x)+'px';
o.style.top=(e.screenY-y)+'px';
i=0;
} function end(e)
{
if(window.addEventListener){
window.document.removeEventListener('mousemove',moving,false);
document.removeEventListener('mouseup',arguments.callee,false);
}else{
window.document.detachEvent('onmousemove',moving);
window.document.detachEvent('onmouseup',arguments.callee);
}
window.document.body.focus() // ff 3.0
}
return function(e,d)
{
i = 0;
x = e.screenX-d.offsetLeft;
y = e.screenY-d.offsetTop;
o = d;
if(window.addEventListener){
window.document.addEventListener('mousemove',moving,false)
window.document.addEventListener('mouseup',end,false)
}else{
window.document.attachEvent('onmousemove',moving)
window.document.attachEvent('onmouseup',end)
}
}
})();
document.getElementById('testDiv').onmousedown=function(e){
e=e || event;
start(e,this);
e.cancelBubble=true;
return false;
}
</script>
</BODY>
</HTML>
//注:添加了事件监听之后,IE里也可以像火狐里那样直接拿事件对象当函数的参数来用了,不必再window.event。
//但是不大清楚这是为什么,或者是说我还有什么地方理解错了,求交流。QQ:1140215489求高手解答
这里面的0可以不用添加的吧,获取的TOP值本生就是带单位的字符串,加个0没用吧
http://www.cnblogs.com/NNUF/archive/2012/04/02/2430132.html
<iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/jikeytang/yKeAk/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>