- 浏览: 1823894 次
文章分类
最新评论
-
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>
相关推荐
而且我已经把windows和linux的vmtools包,以及解决拖拽的问题脚本Drag&Drop_FixPatch一并加入进来,欢迎大家下载使用。 注意:因为大小问题,我分为两卷: VMware6.0深度完美汉化版+vmtools+Drag&Drop_FixPatch(1) ...
使用Drag&Drop接受文件名的输入框(13KB)
NULL 博文链接:https://mingren135.iteye.com/blog/2095635
而且我已经把windows和linux的vmtools包,以及解决拖拽的问题脚本Drag&Drop_FixPatch一并加入进来,欢迎大家下载使用。 注意:因为大小问题,我分为两卷: VMware6.0深度完美汉化版+vmtools+Drag&Drop_FixPatch(1) ...
很不错的drag & drop,类似于igoogle,在个人主页上都用得上,没有设置保存功能,有兴趣的朋友可以自己试一下
Window下拖放操作Drag & Drop 全解析
Drag & drop source code android
WPF 实现了两个listbox之间拖动,drag&drop,并且有上下按钮控制listbox里面元素的移动,还有拖动时边框变色,1分,你值得拥有。
Enhanced Drag & Drop(3KB)
eclipse rcp 关于拖动的文档,里面也有代码例子,但不是完整demo
IOS应用源码之【类库与框架】DragKit - an iOS framework for enabling drag & drop behavior
IOS应用源码之【类库与框架】-DragKit - an iOS framework for enabling drag & drop behavior.rar
【类库与框架】★★★★★-DragKit - an iOS framework for enabling drag & drop【类库与框架】★★★★★-DragKit - an iOS framework for enabling drag & drop 1.适合学生学习研究参考 2.适合个人学习研究参考 3...
wpf拖拽移动列表项的功能,两个datagrid中可以互相拖拽并移动一行数据
drag和drop事件
Ole Drag and Drop Example.
基于 Windows Shell 的拖放支持,跨应用。
一个不错的示例,自己也收藏一下.