JavaScript实现元素的拖放

本文深入探讨HTML5拖放功能,介绍如何利用标准API简化拖放操作,提高Web应用界面便利性。涵盖事件处理、FileAPI应用及跨浏览器兼容性解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

了解:

以前的web应用程序中通过mousemove或者mouseup等原来的事件来实现模拟拖放(drop&drag)功能。但是在HTML5中已经将实现拖放功能事件来实现拖放功能事件与API标准化,可以简单的实现以前要花费大量代码才能实现的功能。

HTML5的拖放,不仅可以通过鼠标移动浏览器中显示的Web部件,还可以将桌面上的文件拖放到浏览器中。这就是显著的提高了web应用程序界面便利性的原因之一。灵活运用File API不仅可以访问桌面文件名等Meta信息,还可以访问文件的内容。使用被拖放到浏览器中的桌面文件数据,可以在浏览器上进行非常有用,有趣的处理。File API是缩小Web应用程序与桌面应用程序差别的技术。

实际上,HTML5的拖放事件并非新开发的规范。原来在Internet Explorer5中就已经出现此种功能,后来被HTML5吸收了。但是,HTML5中对其进行功能的强化,变得比原来强大得多。到目前为止,Internet Explorer中还没支持所有HTML5的拖放规范,只能说一定程度上可以使用。在Chrome5和Safari 5以后支持了几乎所有HTML5的拖放功能。现在对HTML5的拖放功能支持最好的是Firefox3.6以后版本。Firefox中也支持File API,遗憾的是到目前为止支持File API的只有Firefox与Internet Explorer 9。

(1)案例

HTML5的拖放功能是在原先Internet Explorer 5中实现的功能基础上重新制定的标准。但是新的HTML5的拖放功能与原Internet Explorer中实现方式有所差别,不具备完全的互换性。因此这里首先制作可在Firefox、Safari、Chrome中运行的实例,然后再制作可在Internet Explorer中运行的实例。

HTML代码部分:

<!--放置可拖动的图标,4个img元素,1个div元素-->
<!--注意:在div元素中设置为draggable="true"只有设置了此draggable属性,并将属性值设置为true后,div元素才能被拖动-->
<div id="srcarea">
	<img src="../../images/timg_1.jpg" alt="logo1" class="item" id="logo1">
	<img src="../../images/timg_2.jpg" alt="logo2" class="item" id="logo2">
	<img src="../../images/timg_3.jpg" alt="logo3" class="item" id="logo3">
	<img src="../../images/timg_4.jpg" alt="logo4" class="item" id="logo4">
	<div class="item" draggable="true" id="logo5"></div>
</div>
<div id="droparea">
<!--	拖动目的区域-->
</div>

注意:在div元素中设置为draggable="true"。只有设置了此draggable属性,并将属性值设置为true后,div元素才能被拖动。而img元素以及设置了href属性的a元素,都是默认可被拖动的,不需要再设置draggable属性。当前,支持draggable属性的浏览器只有Chrome 5(之后的版本)、Safari 5。在Firefox 3.6以后的版本中,不管有没有设置此属性,只要在dataTranfer对象的setData()方法中设置了消息,就可被拖动。尽管在较旧的Safari 4中不支持draggable属性,也可借助CSS的力量,让div元素变成可被拖动的。代码如下:

[draggable=true]{
    -webkit-user-drag:element;
}

先在拖动对象div元素中设置draggable="true",然后在CSS中追加上述代码。这样就相当于将设置的draggable="true"变得有意义了。使用这种CSS代码,不仅针对div元素,还可以将其他元素变成可被拖动。

CSS代码部分:

<style type="text/css">
	#srcarea,#droparea{
		width:1204px;
		height: 200px;
		background-color: lightgray;
		border: 2px inset gray;
		box-shadow: -1px -1px 2px 2px gray;
		box-sizing: border-box;
		margin: 0px auto 15px auto;
	}
	.item{
		width: 120px;
		margin-left:100px;
		height: auto;
		display: inline-block;
	}
	div.item{
		height: 100px!important;
		background-color: aqua;
	}
/*	兼容Safari 4*/
	[draggable=true]{
		-webkit-user-drag:element;
	}
</style>

此时的效果图(未添加JS)(Firefox运行环境)

添加JS(不考虑IE浏览器前提):

// JavaScript Document
//不考虑IE浏览器的前提
(function(){
	/*——--------------------
	*页面导入时的处理
	*-----------------------*/
	window.addEventListener("load",function(){
		//取得拖动元素
		var els=document.querySelectorAll("#srcarea [class=item]");
		for(var i=0;i<els.length;i++){
			//给拖动元素追加dragstart事件的处理代码
			els[i].addEventListener('dragstart',function(evt){
				var elm=evt.target;
				evt.dataTransfer.setData("Text",elm.id);
				evt.stopPropagation();
			},false);
		}
		//给容纳领域追加各种事件处理
		var droparea=document.getElementById("droparea");
		droparea.addEventListener("dragenter",function(evt){
			evt.preventDefault();
		},false);
		droparea.addEventListener("dragover",function(evt){
			evt.preventDefault();
		},false);
		droparea.addEventListener("drop",function(evt){
			var elm=evt.target;
			var id=evt.dataTransfer.getData("Text");
			var target=document.getElementById(id);
			if(target){
				droparea.appendChild(target);
			}
			evt.preventDefault();
		},false);
	},false);
})();

效果图(Firefox(左)、IE(右)):

  

可以清晰的看出:在IE中不可以拖放图片和div元素。

在上述代码中相关的事件:

拖动对象元素的相关事件
事件名称事件发生时机
dragstart拖动开始
drag拖动中(连续发生)
dragend拖动结束时

 

接受方元素相关的事件
事件名称事件发生时机
dragenter拖动元素进入时
dragleave拖动元素拖出时
dragover拖动中(在进入过程中连续发生)
drop拖动元素被放下时

在上述代码中,setData()方法的第1个参数中设置代表数据格式的字符串,如“Text”代码文本类型数据,这样第2个参数中必需设置文本数据。还可以设置“URL”等。标准中规定不管是大写还是小写,一律变换成小写字母。但是到目前为止不是所有的浏览器都遵循了这一标准。为了与IE相统一,设置为“Text”、“URL”比较适合。在dropstart事件使用stopPropagation()方法,为了不让事件传到父元素中,即父元素不会响应对应事件。如果父元素也是被悲拖动的元素,有可能发生意想不到的错误,因此填写stopPropagation()方法十分必要。在dragenter、dragover、drop三种事件的处理。所有的处理中都追加了preventDefault()方法,以抑制浏览器的默认动作。

JS代码兼容IE

// JavaScript Document
//兼容IE
//在IE的事件绑定与其他浏览器有所不同,有自己的方式。
(function(){
 //页面导入时处理
 add_event_listener(window,"load",function(){
	//取得拖动元素
	var els=get_draggable_items();
	for(var i=0;i<els.length;i++){
		//给拖动元素追加dragstart事件的处理代码
		add_event_listener(els[i],'dragstart',function(evt){
			var elm=event_target(evt);
			evt.dataTransfer.setData("Text",elm.id);
			stop_propagation(evt);
		});
		
	}
	//给接收方区域追加各种事件处理
	var droparea=document.getElementById("droparea");
	add_event_listener(droparea,'dragenter',prevent_default);
	add_event_listener(droparea,'dragover',prevent_default);
	add_event_listener(droparea,"drop",function(evt){
		var e=event_target(evt);
		var id=evt.dataTransfer.getData('Text');
		var target=document.getElementById(id);
		if(target){
			droparea.appendChild(target);
		}
		prevent_default(evt);
		
	});
});
//取得拖动元素
function get_draggable_items(){
	var els=null;
	if(document.querySelectorAll){
		els=document.querySelectorAll("#srcarea [class=item]");
	}else{
		var srcarea=document.getElementById("srcarea");
		els=[];
		for(var i=0;i<srcarea.childNodes.length;i++){
			var el=srcarea.childNodes.item[i];
			if(el.className==='item'){
				els.push(el);
			}
		}
	}
	return els;
}
//设置事件侦听
function add_event_listener(elm,type,func){
	if(!elm){return false;}
	if(elm.addEventListener){
		//兼容非IE
		elm.addEventListener(type,func,false);
	}else if(elm.attachEvent){
		//兼容IE
		elm.attachEvent('on'+type,func);
	}else{
		return false;
	}
	return true;
}
//抑制默认动作
function prevent_default(evt){
	if(evt&&evt.preventDefault){
		evt.preventDefault();
	}else if(window.event){
		//兼容IE
		window.event.returnValue=false;
	}
}
//停止事件上传
function stop_propagation(evt){
	if(evt&&evt.stopPropagation){
		evt.stopPropagation();
	}else if(window.event){
		//兼容IE
		window.event.cancelBubble=true;
	}
}
//取得事件发生元素
function event_target(evt){
	if(evt && evt.target){
		if(evt.target.nodeType===3){
			return evt.target.parentNode;
		}else{
			return evt.target;
		}
	}else if(window.event&&window.event.srcElement){
		return window.event.srcElement;
	}else{
		return null;
	}
}
 })();

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值