- 浏览: 1885766 次
文章分类
最新评论
-
coosummer:
推荐使用http://buttoncssgenerator.c ...
CSS控制<a>标签变为button -
Allen_J_Will:
哥们,事情没有你说的那么简单,很大的一个项目中,依赖jar包的 ...
struts中java.lang.NoClassDefFoundError: com/opensymphony/xwork2/util/TextUtils的解决办法
使用HTML5的drag&drop做一个数独游戏
数独是很好玩的游戏,之前我用jQuery做了一个数独游戏,因为用javaScript来实现drag和drap非常麻烦,jQuery的UI提供了一套非常不错的drag和drap(以后就简称DnD算了),方便我们开发。现在HTML5支持原生的DnD了,那我们来学习下,并且将原先的数独游戏迁移到HTML5的DnD应用来。
先简单的了解下HTML5的DnD事件模型,事件发生在源元素(被拖动的元素)和目标元素(被进入的元素)上,为了简单的描述,我们将源元素称为src,目标元素叫des。
drag:src[拖动中] | dragstart:src[开始拖动] |
dragenter:des[进入目标] | |
dragover:des[在目标移动] | |
dragleave:des[离开目标] | |
drop:des[释放拖动] | |
dragend:src[拖动完成] |
e.dataTransfer.effectAllowed,只能在dragstart事件设置,值为以下之一:"none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", and "uninitialized"
e.dataTransfer.dropEffect,返回拖来的行为,对应上面的effectAllowed,值是:"none", "copy", "link", and "move"
e.target,可以得到当前事件的dom对象,比如你可以得到e.target.innerHTML,或者设置e.target.classList.add,或者e.target.classList.remove
e.dataTransfer.setData(foramt,value),为拖动赋值,foramt的值是为了描述值的类型,一般有text/plain 和text/uri-list
e.dataTransfer.getData(foramt),获取被拖来的元素通过setData存储的值
e.stopPropagation,阻止事件冒泡,这样可以防止子元素的拖动处理被带到父元素事件中(触发父元素事件),在IE中可以用e.cancelBubble = true
e.preventDefault,阻止默认事件发生,也可以简单的写return false,在IE中可以用e.returnValue = false
有了上面的基本概念,我们先做一个小小的模型,来测试几个技术要点:监视拖放事件,改变元素在拖放中的样式,传递值和检查值什么的
在body里面,我们声明了10个div元素,并且都标记允许拖放
- <body>
- <divstyle="width:50px;height:50px;background-color:Red;"draggable="true">
- 1
- </div>
- <divstyle="width:50px;height:50px;background-color:Yellow;"draggable="true">
- 2
- </div>
- <divstyle="width:50px;height:50px;background-color:Blue;"draggable="true">
- 3
- </div>
- <divstyle="width:50px;height:50px;background-color:Lime;"draggable="true">
- 4
- </div>
- <divstyle="width:50px;height:50px;background-color:Maroon;"draggable="true">
- 5
- </div>
- <divstyle="width:50px;height:50px;background-color:Black;"draggable="true">
- 6
- </div>
- <divstyle="width:50px;height:50px;background-color:Orange;"draggable="true">
- 7
- </div>
- <divstyle="width:50px;height:50px;background-color:Olive;"draggable="true">
- 8
- </div>
- <divstyle="width:50px;height:50px;background-color:Teal;"draggable="true">
- 9
- </div>
- <divstyle="width:50px;height:50px;background-color:Green;"draggable="true">
- 10
- </div>
- </body>
首选我们做一个用于输出调式的小工具代码
- $.log=function(msg){
- console.log(msg);
- }
第一步,编写dragStart事件函数
- functionhandleDragStart(e){
- this.style.opacity="0.5";
- e.dataTransfer.effectAllowed="move";
- e.dataTransfer.setData("text/plain",this.innerHTML);
- //$.log(this.innerHTML);
- //$.log(e.target.innerHTML);
- //$.log(e.srcElement.innerHTML);
- [].forEach.call(document.querySelectorAll("div"),
- function(item){
- vara=parseInt(e.target.innerHTML);
- varb=parseInt(item.innerHTML);
- if(a%b!=0&&b%a!=0){
- item.style.opacity="0.1";
- }
- });
- }
1 对事件来讲this、e.target和e.srcElement都是同一对象
2 在forEach中,this是指item,所以forEach中,我们要用e.target来引用
但是一测试我们就发现虽然元素可以拖拉,但并没有事件激活,那是应为我们没有为元素绑定事件,所以现在我们用addEventListener来将元素和事件绑定
- $(
- function(){
- [].forEach.call(document.querySelectorAll("div"),
- function(item){
- item.addEventListener("dragstart",handleDragStart,false);
- }
- );
- }
- );
第二步,当我们拖放完成后,所有div恢复原先颜色,那自然是编写handleDragEnd
- functionhandleDragEnd(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- [].forEach.call(document.querySelectorAll("div"),
- function(item){
- item.style.opacity="1";
- }
- );
- }
- $(
- function(){
- [].forEach.call(document.querySelectorAll("div"),
- function(item){
- item.addEventListener("dragstart",handleDragStart,false);
- item.addEventListener("dragend",handleDragEnd,false);
- }
- );
- }
- );
我们先需要为目标元素定义些事件函数
- functionhandleDragEnter(e){
- $.log(e);
- }
- functionhandleDragOver(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- $.log(e);
- returnfalse;
- }
- functionhandleDragLeave(e){
- $.log(e);
- }
- functionhandleDrop(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- console.log(e);
- returnfalse;
- }
注意我们使用了preventDefault和stopPropagation消除了浏览器默认的一些动作。
显然这些事件不是所有的元素都有的,只有互为倍数才有,所以我们要去修改handleDragStart函数了
修改后的代码大致如下
- functionhandleDragStart(e){
- this.style.opacity="0.5";
- e.dataTransfer.effectAllowed="move";
- e.dataTransfer.setData("text/plain",this.innerHTML);
- //$.log(this.innerHTML);
- //$.log(e.target.innerHTML);
- //$.log(e.srcElement.innerHTML);
- //$.log(this.innerHTML);
- [].forEach.call(document.querySelectorAll("div"),
- function(item){
- vara=parseInt(e.target.innerHTML);
- varb=parseInt(item.innerHTML);
- if(a%b!=0&&b%a!=0){
- item.style.opacity="0.1";
- }
- else{
- item.addEventListener("dragover",handleDragOver,false);
- item.addEventListener("dragenter",handleDragEnter,false);
- item.addEventListener("dragleave",handleDragLeave,false);
- item.addEventListener("drop",handleDrop,false);
- }
- });
- }
- functionhandleDragEnd(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- [].forEach.call(document.querySelectorAll("div"),
- function(item){
- item.style.opacity="1";
- item.removeEventListener("dragover",handleDragOver,false);
- item.removeEventListener("dragenter",handleDragEnter,false);
- item.removeEventListener("dragleave",handleDragLeave,false);
- item.removeEventListener("drop",handleDrop,false);
- }
- );
- }
- functionhandleDrop(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- this.innerHTML=parseInt(this.innerHTML)+parseInt(e.dataTransfer.getData("text/plain"))
- console.log(e);
- returnfalse;
- }
最后,我感觉黑色的字不好看,我们修改下初始化的函数
- $(
- function(){
- [].forEach.call(document.querySelectorAll("div"),
- function(item){
- item.addEventListener("dragstart",handleDragStart,false);
- item.addEventListener("dragend",handleDragEnd,false);
- item.style.color="White";
- }
- );
- }
- );
好了,现在这个无聊的拖动作品,至少可以打发下你的时间,对不,欣赏下自己的作品吧,接下来,我们开始做正式做数独游戏了。
第一步,我们先生成一个1-9的数字对象矩形,这个矩形可以拖动。
先设计htmltag
- <olid="numberBox"style="list-style-type:none;width:90px;height:90px;">
- </ol>
- #numberBox>li
- {
- width:30px;
- height:25px;
- text-align:center;
- font-size:20px;
- padding-top:5px;
- float:left;
- color:White;
- }
- $(
- function(){
- [{number:1,bgcolor:"#C71585"},{number:2,bgcolor:"#800080"},{number:3,bgcolor:"#B8860B"},
- {number:4,bgcolor:"rgb(0,0,128)"},{number:5,bgcolor:"rgb(30,144,255)"},
- {number:6,bgcolor:"rgb(255,165,0)"},
- {number:7,bgcolor:"hsl(0,75%,50%)"},{number:8,bgcolor:"hsl(30,50%,50%)"},
- {number:9,bgcolor:"hsl(120,75%,38%)"}].forEach(
- function(key,index){
- $.log(key);
- varli=$("<li>").html(key.number).css("backgroundColor",key.bgcolor).attr("draggable","true");
- $.log(li);
- li[0].addEventListener("dragstart",function(){
- },false);
- $("#numberBox").append(li);
- }
- );
- }
- );
好,然后你运行下页面,可以看到一个九宫格,并且每一个格子都可以拖动。
第二步,我们要类似的创建我们填数字得的区域了。
首先还是htmlTag
- <olid="player"style="list-style-type:none;width:450px;height:450px;">
- </ol>
- #player.default
- {
- float:left;
- width:48px;
- height:33px;
- border:solid1pxrgb(0,0,0);
- font-size:20px;
- padding-top:15px;
- text-align:center;
- background-color:#B8860B;
- }
- #player.fix
- {
- float:left;
- width:48px;
- height:33px;
- border:solid1pxrgb(0,0,0);
- font-size:20px;
- padding-top:15px;
- text-align:center;
- background-color:#FFFABC;
- }
- #player.ation
- {
- float:left;
- width:48px;
- height:33px;
- border:solid1pxrgb(0,0,0);
- font-size:20px;
- padding-top:15px;
- text-align:center;
- background-color:#FFA07A;
- }
- $(
- function(){
- "500000300090500400004000700051037289302080604008052137035000900609000823080023006".split("").forEach(
- function(item,index){
- $.log(item);
- varli=$("<li>")
- if(item!="0"){
- li.addClass("fix");
- li[0].innerHTML=item;
- }
- else{
- li[0].classList.add("default");
- li[0].addEventListener("dragenter",
- function(e){
- $.log(e);
- },false);
- li[0].addEventListener("dragover",
- function(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- $.log(e);
- returnfalse;
- },false);
- li[0].addEventListener("dragleave",
- function(e){
- },false);
- li[0].addEventListener("drop",
- function(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- },false);
- }
- $("#player").append(li);
- }
- );
- }
- );
第三步:我们拖动数字之后,希望可以填数字的区域有明显的颜色变化并给出提示,同时固定区域不可以拖进去,其他区域可以拖进去,并且拖动的时候要send值。
有了前面的知识,我们马上知道去哪里改事件控制了:dragstart事件
- $(
- function(){
- [{number:1,bgcolor:"#C71585"},{number:2,bgcolor:"#800080"},{number:3,bgcolor:"#B8860B"},
- {number:4,bgcolor:"rgb(0,0,128)"},{number:5,bgcolor:"rgb(30,144,255)"},
- {number:6,bgcolor:"rgb(255,165,0)"},
- {number:7,bgcolor:"hsl(0,75%,50%)"},{number:8,bgcolor:"hsl(30,50%,50%)"},
- {number:9,bgcolor:"hsl(120,75%,38%)"}].forEach(
- function(key,index){
- //$.log(key);
- varli=$("<li>").html(key.number).css("backgroundColor",key.bgcolor).attr("draggable","true");
- //$.log(li);
- li[0].addEventListener("dragstart",function(e){
- e.dataTransfer.effectAllowed="copyMove";
- e.dataTransfer.setData("text/plain",this.innerHTML);
- $.log(this.innerHTML);
- [].forEach.call(document.querySelectorAll("#player.default"),
- function(item){
- //$.log(item);
- item.classList.remove("default");
- item.classList.add("ation");
- });
- },false);
- li[0].addEventListener("dragend",function(){
- [].forEach.call(document.querySelectorAll("#player.ation"),
- function(item){
- item.classList.remove("ation");
- item.classList.add("default");
- });
- },false);
- $("#numberBox").append(li);
- }
- );
- }
- );
第四步,我们接受值,并且判断这个值是否存在行列冲突,如果冲突就提示,否则改写
- $(
- function(){
- "500000300090500400004000700051037289302080604008052137035000900609000823080023006".split("").forEach(
- function(item,index){
- $.log(item);
- varli=$("<li>")
- if(item!="0"){
- li.addClass("fix");
- li[0].innerHTML=item;
- }
- else{
- li[0].classList.add("default");
- li[0].addEventListener("dragenter",
- function(e){
- $.log(e);
- },false);
- li[0].addEventListener("dragover",
- function(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- $.log(e);
- returnfalse;
- },false);
- li[0].addEventListener("dragleave",
- function(e){
- },false);
- li[0].addEventListener("drop",
- function(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- varsendData=e.dataTransfer.getData("text/plain");
- //获得#player>li矩阵数组
- varmatrix=Array.prototype.slice.call(document.querySelectorAll("#player>li"));
- varcurrIndex=matrix.indexOf(this);//获得当前元素的位置
- varrowIndex=currIndex-currIndex%9;//行开始的位置
- varcolIndex=currIndex%9//列开始的位置
- for(vari=rowIndex;i<rowIndex+9;i++){
- if(i!=currIndex&&matrix[i].innerHTML==sendData){
- alert("对不起行上有数据重复,请小心哦!亲");
- return;
- }
- }
- for(vari=colIndex;i<81;i=i+9){
- if(i!=currIndex&&matrix[i].innerHTML==sendData){
- alert("对不起列上有数据重复,请小心哦!亲");
- return;
- }
- }
- this.innerHTML=sendData;
- },false);
- }
- $("#player").append(li);
- }
- );
- }
- );
现在你可以开始玩啦,虽然颜色不怎么好看,但至少可以玩,对不,我们第一个html5的实用游戏。我后期的blog打算再做些类似新浪微博的“你画我猜”还有“接龙游戏”。
下面是完整的代码,你要懒的话,就直接copy吧
- <!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <htmlxmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title></title>
- <scriptsrc=../../"js/jquery-1.7.1.min.js"type="text/javascript"></script>
- <scripttype="text/javascript">
- $.log=function(msg){
- console.log(msg);
- }
- $(
- function(){
- [{number:1,bgcolor:"#C71585"},{number:2,bgcolor:"#800080"},{number:3,bgcolor:"#B8860B"},
- {number:4,bgcolor:"rgb(0,0,128)"},{number:5,bgcolor:"rgb(30,144,255)"},
- {number:6,bgcolor:"rgb(255,165,0)"},
- {number:7,bgcolor:"hsl(0,75%,50%)"},{number:8,bgcolor:"hsl(30,50%,50%)"},
- {number:9,bgcolor:"hsl(120,75%,38%)"}].forEach(
- function(key,index){
- //$.log(key);
- varli=$("<li>").html(key.number).css("backgroundColor",key.bgcolor).attr("draggable","true");
- //$.log(li);
- li[0].addEventListener("dragstart",function(e){
- e.dataTransfer.effectAllowed="copyMove";
- e.dataTransfer.setData("text/plain",this.innerHTML);
- $.log(this.innerHTML);
- [].forEach.call(document.querySelectorAll("#player.default"),
- function(item){
- //$.log(item);
- item.classList.remove("default");
- item.classList.add("ation");
- });
- },false);
- li[0].addEventListener("dragend",function(){
- [].forEach.call(document.querySelectorAll("#player.ation"),
- function(item){
- item.classList.remove("ation");
- item.classList.add("default");
- });
- },false);
- $("#numberBox").append(li);
- }
- );
- }
- );
- $(
- function(){
- "500000300090500400004000700051037289302080604008052137035000900609000823080023006".split("").forEach(
- function(item,index){
- $.log(item);
- varli=$("<li>")
- if(item!="0"){
- li.addClass("fix");
- li[0].innerHTML=item;
- }
- else{
- li[0].classList.add("default");
- li[0].addEventListener("dragenter",
- function(e){
- $.log(e);
- },false);
- li[0].addEventListener("dragover",
- function(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- $.log(e);
- returnfalse;
- },false);
- li[0].addEventListener("dragleave",
- function(e){
- },false);
- li[0].addEventListener("drop",
- function(e){
- if(e.preventDefault){
- e.preventDefault();//不要执行与事件关联的默认动作
- }
- if(e.stopPropagation){
- e.stopPropagation();//停止事件的传播
- }
- varsendData=e.dataTransfer.getData("text/plain");
- //获得#player>li矩阵数组
- varmatrix=Array.prototype.slice.call(document.querySelectorAll("#player>li"));
- varcurrIndex=matrix.indexOf(this);//获得当前元素的位置
- varrowIndex=currIndex-currIndex%9;//行开始的位置
- varcolIndex=currIndex%9//列开始的位置
- for(vari=rowIndex;i<rowIndex+9;i++){
- if(i!=currIndex&&matrix[i].innerHTML==sendData){
- alert("对不起行上有数据重复,请小心哦!亲");
- return;
- }
- }
- for(vari=colIndex;i<81;i=i+9){
- if(i!=currIndex&&matrix[i].innerHTML==sendData){
- alert("对不起列上有数据重复,请小心哦!亲");
- return;
- }
- }
- this.innerHTML=sendData;
- },false);
- }
- $("#player").append(li);
- }
- );
- }
- );
- </script>
- <styletype="text/css">
- #numberBox>li
- {
- width:30px;
- height:25px;
- text-align:center;
- font-size:20px;
- padding-top:5px;
- float:left;
- color:White;
- }
- #player.default
- {
- float:left;
- width:48px;
- height:33px;
- border:solid1pxrgb(0,0,0);
- font-size:20px;
- padding-top:15px;
- text-align:center;
- background-color:#B8860B;
- }
- #player.fix
- {
- float:left;
- width:48px;
- height:33px;
- border:solid1pxrgb(0,0,0);
- font-size:20px;
- padding-top:15px;
- text-align:center;
- background-color:#FFFABC;
- }
- #player.ation
- {
- float:left;
- width:48px;
- height:33px;
- border:solid1pxrgb(0,0,0);
- font-size:20px;
- padding-top:15px;
- text-align:center;
- background-color:#FFA07A;
- }
- </style>
- </head>
- <body>
- <olid="numberBox"style="list-style-type:none;width:90px;height:90px;">
- </ol>
- <olid="player"style="list-style-type:none;width:450px;height:450px;">
- </ol>
- </body>
相关推荐
总之,【深度VMware6.0完美精简汉化版+Drag&Drop_FixPatch】是一个专为中国用户设计的VMware Workstation优化版本,它解决了原版软件的某些不便,并提供了一个更加友好、高效的使用环境。用户可以通过下载这个版本来...
而且我已经把windows和linux的vmtools包,以及解决拖拽的问题脚本Drag&Drop_FixPatch一并加入进来,欢迎大家下载使用。 注意:因为大小问题,我分为两卷: VMware6.0深度完美汉化版+vmtools+Drag&Drop_FixPatch(1) ...
HTML5实践Drag&Drop HTML5作为现代网页开发的标准,引入了许多新的特性和API,其中一项就是拖放(Drag&Drop)功能。这项技术允许用户通过鼠标或触控设备将元素从一个位置拖动到另一个位置,极大地提升了用户体验。...
总的来说,“使用Drag&Drop接受文件名的输入框”是一个提升用户友好性的实用功能,它结合了现代UI设计趋势和技术,使用户操作更加便捷。通过学习和应用这种技术,开发者能够创造出更加高效且直观的应用程序。
在Windows环境下,Shell API提供了对拖放操作的基本支持,而Drag&Drop VCL则将这些底层接口包装为易于使用的VCL组件,方便开发者快速集成到Delphi项目中。 Drag&Drop VCL的核心组件通常包括TDragObject、...
综合以上信息,我们可以推断这是一个使用PHP开发的、具有拖放功能的个性化首页服务。用户可以通过拖放小部件来定制他们的个人主页,尽管目前版本可能没有保存设置的功能,需要开发者进一步完善。对于想要学习如何在...
而且我已经把windows和linux的vmtools包,以及解决拖拽的问题脚本Drag&Drop_FixPatch一并加入进来,欢迎大家下载使用。 注意:因为大小问题,我分为两卷: VMware6.0深度完美汉化版+vmtools+Drag&Drop_FixPatch(1) ...
在Windows Presentation Foundation (WPF) 中,拖放(Drag&Drop)功能是一种常见的用户交互方式,允许用户通过鼠标操作将项目从一个位置移动到另一个位置。在这个特定的场景中,"WPF Drag&Drop"指的是在两个DataGrid...
5. **Drag and Drop Operations**: 拖放操作有多种类型,如`DND.DROP_COPY`(复制)、`DND.DROP_MOVE`(移动)和`DND.DROP_DEFAULT`(默认)。在`DragSourceAdapter`和`DropTargetAdapter`中,你可以根据需要重写...
Optimize your workflow with Drag and Drop Import for Blender. Quickly and easily import files by dragging them from your file explorer and dropping them into Blender’s 3D Viewport or Outliner. No ...
Windows 操作系统中拖放操作(Drag & Drop)是一种常用的用户交互方式,允许用户在不同的程序窗口之间、同一个程序的不同窗口之间或同一程序同一窗口的不同控件之间进行移动、复制和粘贴等操作。拖放操作是在操作...
在Android开发中,拖放(Drag & Drop)功能是一种用户友好的交互方式,允许用户通过手势将一个元素从一处移动到另一处。本资源提供的"Drag & Drop source code android"包含了一个实现Android拖放功能的源代码示例,...
"Drag & Drop Modules" 是一个关于使用拖放功能在JavaScript虚拟机2(JSVM2)中构建模块化应用的示例。这个主题涉及到前端开发中的交互设计和模块化编程两个重要概念。 首先,让我们深入了解“Drag & Drop”技术。...
JavaScript中的拖放(Drag & Drop)功能是一种交互式技术,允许用户通过鼠标操作将元素从一个位置拖动到另一个位置,常用于文件管理、界面构建和游戏开发等场景。在这个"Drag & Drop in JavaScript"项目中,我们可能...
标题“Drag & Drop Files to Delete.zip”提示我们这是一个与JavaScript相关的项目,可能涉及到文件操作,特别是拖放(Drag & Drop)功能,用于删除文件。在Web开发中,这种功能允许用户通过简单的拖放操作来处理...
在Windows Presentation Foundation (WPF) 中,`ListBox` 是一个常用的数据展示控件,它可以用来显示一系列可选择的项。本教程将详细讲解如何在两个`ListBox`之间实现拖放(Drag & Drop)功能,以及如何添加上下按钮...
在我们的例子中,“Drag&drop.zip”项目包含了一个测试示例,展示了如何在两个列表框(QListWidget)之间进行拖放操作。 在Qt 5.6中,启用拖放功能通常需要以下步骤: 1. **启用拖放功能**:对于每个列表框,需要...
标题“Enhanced Drag & Drop(3KB)”暗示我们讨论的主题是关于增强拖放功能的代码实现,这通常涉及用户界面(UI)交互的优化。在编程领域,拖放功能允许用户通过鼠标操作来移动或复制对象,使得软件更加用户友好。...