html5教程-使用HTML5的drag&drop做一个数独游戏

发布时间:2018-12-18 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了html5教程-使用HTML5的drag&drop做一个数独游戏脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。
数独是很好玩的游戏,之前我用jQuery做了一个数独游戏,因为用javaScript来实现drag和drap非常麻烦,jQuery的UI提供了一套非常不错的drag和drap(以后就简称DnD算了),方便我们开发。现在HTML5支持原生的DnD了,那我们来学习下,并且将原先的数独游戏迁移到HTML5的DnD应用来。

html5教程-使用HTML5的drag&drop做一个数独游戏




先简单的了解下HTML5的DnD事件模型,事件发生在源元素(被拖动的元素)和目标元素(被进入的元素)上,为了简单的描述,我们将源元素称为src,目标元素叫des。
 
drag:src[拖动中] dragstart:src[开始拖动]
 dragenter:des[进入目标]
 dragover:des[在目标移动]
 dragleave:des[离开目标]
 drop:des[释放拖动]
 dragend:src[拖动完成]
所有的事件我们知道肯定都应该给我们一个event对象,帮助我们获得一些信息或我们来设置一些信息,以上事件都可以得到一个event,如果我们的事件函数是function(e)那
 
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个p元素,并且都标记允许拖放
 
1. <body>
2.     <p style="width: 50px; height: 50px; background-color: Red;" draggable="true">
3.         1
4.     </p>
5.     <p style="width: 50px; height: 50px; background-color: Yellow;" draggable="true">
6.         2
7.     </p>
8.     <p style="width: 50px; height: 50px; background-color: Blue;" draggable="true">
9.         3
10.     </p>
11.     <p style="width: 50px; height: 50px; background-color: Lime;" draggable="true">
12.         4
13.     </p>
14.     <p style="width: 50px; height: 50px; background-color: Maroon;" draggable="true">
15.         5
16.     </p>
17.     <p style="width: 50px; height: 50px; background-color: Black;" draggable="true">
18.         6
19.     </p>
20.     <p style="width: 50px; height: 50px; background-color: Orange;" draggable="true">
21.         7
22.     </p>
23.     <p style="width: 50px; height: 50px; background-color: Olive;" draggable="true">
24.         8
25.     </p>
26.     <p style="width: 50px; height: 50px; background-color: Teal;" draggable="true">
27.         9
28.     </p>
29.     <p style="width: 50px; height: 50px; background-color: Green;" draggable="true">
30.         10
31.     </p>
32. </body>
现在我们想做一个应用,只有相互有倍数关系的p之间才可用拖放。
 
首选我们做一个用于输出调式的小工具代码
1. $.log = function(msg) {
2.     console.log(msg);
3. }
 
这个我们可以方便的$.log()输出,而不要写冗长的console.log了
 
第一步,编写dragStart事件函数
1. function handleDragStart(e) {
2.     this.style.opacity = "0.5";
3.     e.dataTransfer.effectAllowed = "move";
4.     e.dataTransfer.setData("text/plain", this.innerHTML);
5.     //$.log(this.innerHTML);
6.     //$.log(e.target.innerHTML);
7.     //$.log(e.srcElement.innerHTML);
8.     [ ].forEach.call(document.querySelectorAll("p"),
9.     function(item) {
10.         var a = parseInt(e.target.innerHTML);
11.         var b = parseInt(item.innerHTML);
12.         if (a % b != 0 && b % a != 0) {
13.             item.style.opacity = "0.1";
14. 
15.         }
16.     });
17. }
 
以上的代码有几个要点
 
1 对事件来讲this、e.target和e.srcElement都是同一对象
2 在forEach中,this是指item,所以forEach中,我们要用e.target来引用
但是一测试我们就发现虽然元素可以拖拉,但并没有事件激活,那是应为我们没有为元素绑定事件,所以现在我们用addEventListener来将元素和事件绑定
1. $(
2. function() {
3.     [ ].forEach.call(document.querySelectorAll("p"),
4. function(item) {
5.      item.addEventListener("dragstart", handleDragStart, false); 
6. }
7. );
8. }
9. );
 
现在我们可以看到,当任意元素拖动的时候,不和其元素有相互倍数的元素变了很淡了。
 
第二步,当我们拖放完成后,所有p恢复原先颜色,那自然是编写handleDragEnd
1. function handleDragEnd(e) {
2.     if (e.preventDefault) {
3.         e.preventDefault(); //不要执行与事件关联的默认动作
4.     }
5.     [ ].forEach.call(document.querySelectorAll("p"),
6.     function(item) {
7.         item.style.opacity = "1";
8.     }
9.     );
10. }
 
记得将上面的事件做绑定哦,应该类似以下代码
1. $(
2. function() {
3.     [ ].forEach.call(document.querySelectorAll("p"),
4. function(item) {
5.      item.addEventListener("dragstart", handleDragStart, false);
6.      item.addEventListener("dragend", handleDragEnd, false); 
7. }
8. );
9. }
10. );
第三步,我们要通知那些互为倍数的元素允许我们做拖入操作
 
我们先需要为目标元素定义些事件函数
1. function handleDragEnter(e) {
2.     $.log(e);
3. }
4. 
5. function handleDragOver(e) {
6.     if (e.preventDefault) {
7.         e.preventDefault(); //不要执行与事件关联的默认动作
8.     }
9.     if (e.stopPropagation) {
10.         e.stopPropagation(); //停止事件的传播
11.     }
12.     $.log(e);
13.     return false;
14. }
15. 
16. 
17. function handleDragLeave(e) {
18.     $.log(e);
19. }
20. 
21. function handleDrop(e) {
22.     if (e.preventDefault) {
23.         e.preventDefault(); //不要执行与事件关联的默认动作
24.     }
25.     if (e.stopPropagation) {
26.         e.stopPropagation(); //停止事件的传播
27.     }
28.     console.log(e);
29.     return false;
30. }
 
 
注意我们使用了preventDefault和stopPropagation消除了浏览器默认的一些动作。
显然这些事件不是所有的元素都有的,只有互为倍数才有,所以我们要去修改handleDragStart函数了
修改后的代码大致如下
1. function handleDragStart(e) {
2.     this.style.opacity = "0.5";
3.     e.dataTransfer.effectAllowed = "move";
4.     e.dataTransfer.setData("text/plain", this.innerHTML);
5.     //$.log(this.innerHTML);
6.     //$.log(e.target.innerHTML);
7.     //$.log(e.srcElement.innerHTML);
8.     //$.log(this.innerHTML);
9.     [ ].forEach.call(document.querySelectorAll("p"),
10.     function(item) {
11.         var a = parseInt(e.target.innerHTML);
12.         var b = parseInt(item.innerHTML);
13.         if (a % b != 0 && b % a != 0) {
14.             item.style.opacity = "0.1";
15.         }
16.         else {
17.             item.addEventListener("dragover", handleDragOver, false);
18.             item.addEventListener("dragenter", handleDragEnter, false);
19.             item.addEventListener("dragleave", handleDragLeave, false);
20.             item.addEventListener("drop", handleDrop, false);
21.         }
22.     });
23. }
 
现在你可以发现,当我们拖动互为倍数的元素是,视觉效果明显是允许拖入,否则就不允许了。当然记得在handleDragEnd函数中要恢复哦
1. function handleDragEnd(e) {
2.     if (e.preventDefault) {
3.         e.preventDefault(); //不要执行与事件关联的默认动作
4.     }
5.     [ ].forEach.call(document.querySelectorAll("p"),
6.     function(item) {
7.         item.style.opacity = "1";
8.         item.removeEventListener("dragover", handleDragOver, false);
9.         item.removeEventListener("dragenter", handleDragEnter, false);
10.         item.removeEventListener("dragleave", handleDragLeave, false);
11.         item.removeEventListener("drop", handleDrop, false);
12.     }
13.     );
14. }
第四步,当我们在可以放置的元素上结束拖放后,我们希望两个元素的值累计,并出现在被放置的元素里面,我们需要修改handleDrop函数
1. function handleDrop(e) {
2.     if (e.preventDefault) {
3.         e.preventDefault(); //不要执行与事件关联的默认动作
4.     }
5.     if (e.stopPropagation) {
6.         e.stopPropagation(); //停止事件的传播
7.     }
8.     this.innerHTML = parseInt(this.innerHTML)+parseInt(e.dataTransfer.getData("text/plain"))
9.     console.log(e);
10.     return false;
11. }
好了,到现在为止,准备知识都差不多了,而且作品我们也可以得意的玩玩,你可以发现p被累计都,再次拖拉的时候,是重新计算相互的倍数的,对不?
 
最后,我感觉黑色的字不好看,我们修改下初始化的函数
1. $(
2. function() {
3.     [ ].forEach.call(document.querySelectorAll("p"),
4. function(item) {
5.     item.addEventListener("dragstart", handleDragStart, false);
6.     item.addEventListener("dragend", handleDragEnd, false);
7.     item.style.color = "White";
8. }
9. );
10. }
11. );
 
 
好了,现在这个无聊的拖动作品,至少可以打发下你的时间,对不,欣赏下自己的作品吧,接下来,我们开始做正式做数独游戏了。
第一步,我们先生成一个1-9的数字对象矩形,这个矩形可以拖动。
先设计htmltag
1. <ol id="numberBox" style="list-style-type: none; width: 90px; height: 90px;">
2. </ol>
 
 
然后准备些样式
1. [css]
2. 
3. #numberBox > li  
4. 
5. {  
6. 
7.     width: 30px;  
8. 
9.     height: 25px;  
10. 
11.     text-align: center;  
12. 
13.     font-size: 20px;  
14. 
15.     padding-top: 5px;  
16. 
17.     float: left;  
18. 
19.     color: White;  
20. 
21. }  
最后是脚本
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     [{ number: 1, bgcolor: "#C71585" }, { number: 2, bgcolor: "#800080" }, { number: 3, bgcolor: "#B8860B" },  
8. 
9.     { number: 4, bgcolor: "rgb(0,0,128)" }, { number: 5, bgcolor: "rgb(30,144,255)" },   
10. 
11.     { number: 6, bgcolor: "rgb(255,165,0)" },  
12. 
13.      { number: 7, bgcolor: "hsl(0,75%,50%)" }, { number: 8, bgcolor: "hsl(30,50%,50%)" },   
14. 
15.      { number: 9, bgcolor: "hsl(120,75%,38%)"}].forEach(  
16. 
17.      function(key, index) {  
18. 
19.      $.log(key);  
20. 
21.          var li = $("<li>").html(key.number).css("backgroundColor", key.bgcolor).attr("draggable","true");  
22. 
23.          $.log(li);  
24. 
25.          li[0].addEventListener("dragstart", function() {  
26. 
27.          }, false);  
28. 
29.          $("#numberBox").append(li);  
30. 
31.      }  
32. 
33.      );  
34. 
35. }  
36. 
37. );  
好,然后你运行下页面,可以看到一个九宫格,并且每一个格子都可以拖动。
第二步,我们要类似的创建我们填数字得的区域了。
首先还是htmlTag
1. [html]
2. 
3. <ol id="player" style="list-style-type: none; width: 450px; height: 450px;">  
4. 
5. </ol>  
然后是样式设定
1. [css]
2. 
3. #player .default  
4. 
5. {  
6. 
7.     float: left;  
8. 
9.     width: 48px;  
10. 
11.     height: 33px;  
12. 
13.     border: solid 1px rgb(0,0,0);  
14. 
15.     font-size: 20px;  
16. 
17.     padding-top: 15px;  
18. 
19.     text-align: center;  
20. 
21.     background-color: #B8860B;  
22. 
23. }  
24. 
25. #player .fix  
26. 
27. {  
28. 
29.     float: left;  
30. 
31.     width: 48px;  
32. 
33.     height: 33px;  
34. 
35.     border: solid 1px rgb(0,0,0);  
36. 
37.     font-size: 20px;  
38. 
39.     padding-top: 15px;  
40. 
41.     text-align: center;  
42. 
43.     background-color: #FFFABC;  
44. 
45. }  
46. 
47. #player .ation  
48. 
49. {  
50. 
51.     float: left;  
52. 
53.     width: 48px;  
54. 
55.     height: 33px;  
56. 
57.     border: solid 1px rgb(0,0,0);  
58. 
59.     font-size: 20px;  
60. 
61.     padding-top: 15px;  
62. 
63.     text-align: center;  
64. 
65.     background-color: #FFA07A;  
66. 
67. }  
然后初始化这个区域。数独填字区域有的格子有值有的没有值,我用0表示没有值将来你可以填制,非0表示是固定区不可以改 www.2cto.com
现在你已经可以在页面上看到一个非常威武的“独”字了!
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     "500000300090500400004000700051037289302080604008052137035000900609000823080023006".split("").forEach(  
8. 
9.     function(item, index) {  
10. 
11.         $.log(item);  
12. 
13.         var li = $("<li>")  
14. 
15.         if (item != "0") {  
16. 
17.             li.addClass("fix");  
18. 
19.             li[0].innerHTML = item;  
20. 
21.         }  
22. 
23.         else {  
24. 
25.             li[0].classList.add("default");  
26. 
27.             li[0].addEventListener("dragenter",  
28. 
29.             function(e) {  
30. 
31.                 $.log(e);  
32. 
33.             }, false);  
34. 
35.   
36. 
37.             li[0].addEventListener("dragover",  
38. 
39.             function(e) {  
40. 
41.                 if (e.preventDefault) {  
42. 
43.                     e.preventDefault(); //不要执行与事件关联的默认动作  
44. 
45.                 }  
46. 
47.                 if (e.stopPropagation) {  
48. 
49.                     e.stopPropagation(); //停止事件的传播  
50. 
51.                 }  
52. 
53.                 $.log(e);  
54. 
55.                 return false;  
56. 
57.             }, false);  
58. 
59.   
60. 
61.             li[0].addEventListener("dragleave",  
62. 
63.             function(e) {  
64. 
65.             }, false);  
66. 
67.   
68. 
69.             li[0].addEventListener("drop",  
70. 
71.             function(e) {  
72. 
73.                 if (e.preventDefault) {  
74. 
75.                     e.preventDefault(); //不要执行与事件关联的默认动作  
76. 
77.                 }  
78. 
79.                 if (e.stopPropagation) {  
80. 
81.                     e.stopPropagation(); //停止事件的传播  
82. 
83.                 }  
84. 
85.   
86. 
87.             }, false);  
88. 
89.         }  
90. 
91.         $("#player").append(li);  
92. 
93.     }  
94. 
95.     );  
96. 
97. }  
98. 
99. );  

第三步:我们拖动数字之后,希望可以填数字的区域有明显的颜色变化并给出提示,同时固定区域不可以拖进去,其他区域可以拖进去,并且拖动的时候要send值。
有了前面的知识,我们马上知道去哪里改事件控制了:dragstart事件
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     [{ number: 1, bgcolor: "#C71585" }, { number: 2, bgcolor: "#800080" }, { number: 3, bgcolor: "#B8860B" },  
8. 
9.     { number: 4, bgcolor: "rgb(0,0,128)" }, { number: 5, bgcolor: "rgb(30,144,255)" },  
10. 
11.     { number: 6, bgcolor: "rgb(255,165,0)" },  
12. 
13.      { number: 7, bgcolor: "hsl(0,75%,50%)" }, { number: 8, bgcolor: "hsl(30,50%,50%)" },  
14. 
15.      { number: 9, bgcolor: "hsl(120,75%,38%)"}].forEach(  
16. 
17.      function(key, index) {  
18. 
19.          //$.log(key);  
20. 
21.          var li = $("<li>").html(key.number).css("backgroundColor", key.bgcolor).attr("draggable", "true");  
22. 
23.          //$.log(li);  
24. 
25.          li[0].addEventListener("dragstart", function(e) {  
26. 
27.              e.dataTransfer.effectAllowed = "copyMove";  
28. 
29.              e.dataTransfer.setData("text/plain", this.innerHTML);  
30. 
31.              $.log(this.innerHTML);  
32. 
33.              [ ].forEach.call(document.querySelectorAll("#player .default"),  
34. 
35.          function(item) {  
36. 
37.              //$.log(item);  
38. 
39.              item.classList.remove("default");  
40. 
41.              item.classList.add("ation");  
42. 
43.          });  
44. 
45.          }, false);  
46. 
47.   
48. 
49.          li[0].addEventListener("dragend", function() {  
50. 
51.              [ ].forEach.call(document.querySelectorAll("#player .ation"),  
52. 
53.          function(item) {  
54. 
55.              item.classList.remove("ation");  
56. 
57.              item.classList.add("default");  
58. 
59.          });  
60. 
61.          }, false);  
62. 
63.   
64. 
65.          $("#numberBox").append(li);  
66. 
67.      }  
68. 
69.      );  
70. 
71. }  
72. 
73. );  
 
 
现在你可以测试下了,当你拖动数字的时候,有明显的颜色改变,并且不同的区域你的鼠标样式也不同哦。
第四步,我们接受值,并且判断这个值是否存在行列冲突,如果冲突就提示,否则改写
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     "500000300090500400004000700051037289302080604008052137035000900609000823080023006".split("").forEach(  
8. 
9.     function(item, index) {  
10. 
11.         $.log(item);  
12. 
13.         var li = $("<li>")  
14. 
15.         if (item != "0") {  
16. 
17.             li.addClass("fix");  
18. 
19.             li[0].innerHTML = item;  
20. 
21.         }  
22. 
23.         else {  
24. 
25.             li[0].classList.add("default");  
26. 
27.             li[0].addEventListener("dragenter",  
28. 
29.             function(e) {  
30. 
31.                 $.log(e);  
32. 
33.             }, false);  
34. 
35.   
36. 
37.             li[0].addEventListener("dragover",  
38. 
39.             function(e) {  
40. 
41.                 if (e.preventDefault) {  
42. 
43.                     e.preventDefault(); //不要执行与事件关联的默认动作  
44. 
45.                 }  
46. 
47.                 if (e.stopPropagation) {  
48. 
49.                     e.stopPropagation(); //停止事件的传播  
50. 
51.                 }  
52. 
53.                 $.log(e);  
54. 
55.                 return false;  
56. 
57.             }, false);  
58. 
59.   
60. 
61.             li[0].addEventListener("dragleave",  
62. 
63.             function(e) {  
64. 
65.             }, false);  
66. 
67.   
68. 
69.             li[0].addEventListener("drop",  
70. 
71.             function(e) {  
72. 
73.                 if (e.preventDefault) {  
74. 
75.                     e.preventDefault(); //不要执行与事件关联的默认动作  
76. 
77.                 }  
78. 
79.                 if (e.stopPropagation) {  
80. 
81.                     e.stopPropagation(); //停止事件的传播  
82. 
83.                 }  
84. 
85.   
86. 
87.                 var sendData = e.dataTransfer.getData("text/plain");  
88. 
89.                 //获得#player>li矩阵数组  
90. 
91.                 var matrix = Array.prototype.slice.call(document.querySelectorAll("#player>li"));   
92. 
93.                 var currIndex = matrix.indexOf(this); //获得当前元素的位置  
94. 
95.                 var rowIndex = currIndex - currIndex % 9; //行开始的位置  
96. 
97.                 var colIndex = currIndex % 9//列开始的位置  
98. 
99.                 for (var i = rowIndex; i < rowIndex + 9; i++) {  
100. 
101.                     if (i != currIndex && matrix[i].innerHTML == sendData) {  
102. 
103.                         alert("对不起行上有数据重复,请小心哦!亲");  
104. 
105.                         return;  
106. 
107.                     }  
108. 
109.                 }  
110. 
111.                 for (var i = colIndex; i < 81; ii = i + 9) {  
112. 
113.                     if (i != currIndex && matrix[i].innerHTML == sendData) {  
114. 
115.                         alert("对不起列上有数据重复,请小心哦!亲");  
116. 
117.                         return;  
118. 
119.                     }  
120. 
121.                 }  
122. 
123.                 this.innerHTML = sendData;  
124. 
125.   
126. 
127.             }, false);  
128. 
129.         }  
130. 
131.         $("#player").append(li);  
132. 
133.     }  
134. 
135.     );  
136. 
137. }  
138. 
139. );  
140. 
141.  
现在你可以开始玩啦,虽然颜色不怎么好看,但至少可以玩,对不,我们第一个html5的实用游戏。我后期的blog打算再做些类似新浪微博的“你画我猜”还有“接龙游戏”。

 

 


摘自 shyleoking的专栏

数独是很好玩的游戏,之前我用jQuery做了一个数独游戏,因为用javaScript来实现drag和drap非常麻烦,jQuery的UI提供了一套非常不错的drag和drap(以后就简称DnD算了),方便我们开发。现在HTML5支持原生的DnD了,那我们来学习下,并且将原先的数独游戏迁移到HTML5的DnD应用来。

html5教程-使用HTML5的drag&drop做一个数独游戏




先简单的了解下HTML5的DnD事件模型,事件发生在源元素(被拖动的元素)和目标元素(被进入的元素)上,为了简单的描述,我们将源元素称为src,目标元素叫des。
 
drag:src[拖动中] dragstart:src[开始拖动]
 dragenter:des[进入目标]
 dragover:des[在目标移动]
 dragleave:des[离开目标]
 drop:des[释放拖动]
 dragend:src[拖动完成]
所有的事件我们知道肯定都应该给我们一个event对象,帮助我们获得一些信息或我们来设置一些信息,以上事件都可以得到一个event,如果我们的事件函数是function(e)那
 
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个p元素,并且都标记允许拖放
 
1. <body>
2.     <p style="width: 50px; height: 50px; background-color: Red;" draggable="true">
3.         1
4.     </p>
5.     <p style="width: 50px; height: 50px; background-color: Yellow;" draggable="true">
6.         2
7.     </p>
8.     <p style="width: 50px; height: 50px; background-color: Blue;" draggable="true">
9.         3
10.     </p>
11.     <p style="width: 50px; height: 50px; background-color: Lime;" draggable="true">
12.         4
13.     </p>
14.     <p style="width: 50px; height: 50px; background-color: Maroon;" draggable="true">
15.         5
16.     </p>
17.     <p style="width: 50px; height: 50px; background-color: Black;" draggable="true">
18.         6
19.     </p>
20.     <p style="width: 50px; height: 50px; background-color: Orange;" draggable="true">
21.         7
22.     </p>
23.     <p style="width: 50px; height: 50px; background-color: Olive;" draggable="true">
24.         8
25.     </p>
26.     <p style="width: 50px; height: 50px; background-color: Teal;" draggable="true">
27.         9
28.     </p>
29.     <p style="width: 50px; height: 50px; background-color: Green;" draggable="true">
30.         10
31.     </p>
32. </body>
现在我们想做一个应用,只有相互有倍数关系的p之间才可用拖放。
 
首选我们做一个用于输出调式的小工具代码
1. $.log = function(msg) {
2.     console.log(msg);
3. }
 
这个我们可以方便的$.log()输出,而不要写冗长的console.log了
 
第一步,编写dragStart事件函数
1. function handleDragStart(e) {
2.     this.style.opacity = "0.5";
3.     e.dataTransfer.effectAllowed = "move";
4.     e.dataTransfer.setData("text/plain", this.innerHTML);
5.     //$.log(this.innerHTML);
6.     //$.log(e.target.innerHTML);
7.     //$.log(e.srcElement.innerHTML);
8.     [ ].forEach.call(document.querySelectorAll("p"),
9.     function(item) {
10.         var a = parseInt(e.target.innerHTML);
11.         var b = parseInt(item.innerHTML);
12.         if (a % b != 0 && b % a != 0) {
13.             item.style.opacity = "0.1";
14. 
15.         }
16.     });
17. }
 
以上的代码有几个要点
 
1 对事件来讲this、e.target和e.srcElement都是同一对象
2 在forEach中,this是指item,所以forEach中,我们要用e.target来引用
但是一测试我们就发现虽然元素可以拖拉,但并没有事件激活,那是应为我们没有为元素绑定事件,所以现在我们用addEventListener来将元素和事件绑定
1. $(
2. function() {
3.     [ ].forEach.call(document.querySelectorAll("p"),
4. function(item) {
5.      item.addEventListener("dragstart", handleDragStart, false); 
6. }
7. );
8. }
9. );
 
现在我们可以看到,当任意元素拖动的时候,不和其元素有相互倍数的元素变了很淡了。
 
第二步,当我们拖放完成后,所有p恢复原先颜色,那自然是编写handleDragEnd
1. function handleDragEnd(e) {
2.     if (e.preventDefault) {
3.         e.preventDefault(); //不要执行与事件关联的默认动作
4.     }
5.     [ ].forEach.call(document.querySelectorAll("p"),
6.     function(item) {
7.         item.style.opacity = "1";
8.     }
9.     );
10. }
 
记得将上面的事件做绑定哦,应该类似以下代码
1. $(
2. function() {
3.     [ ].forEach.call(document.querySelectorAll("p"),
4. function(item) {
5.      item.addEventListener("dragstart", handleDragStart, false);
6.      item.addEventListener("dragend", handleDragEnd, false); 
7. }
8. );
9. }
10. );
第三步,我们要通知那些互为倍数的元素允许我们做拖入操作
 
我们先需要为目标元素定义些事件函数
1. function handleDragEnter(e) {
2.     $.log(e);
3. }
4. 
5. function handleDragOver(e) {
6.     if (e.preventDefault) {
7.         e.preventDefault(); //不要执行与事件关联的默认动作
8.     }
9.     if (e.stopPropagation) {
10.         e.stopPropagation(); //停止事件的传播
11.     }
12.     $.log(e);
13.     return false;
14. }
15. 
16. 
17. function handleDragLeave(e) {
18.     $.log(e);
19. }
20. 
21. function handleDrop(e) {
22.     if (e.preventDefault) {
23.         e.preventDefault(); //不要执行与事件关联的默认动作
24.     }
25.     if (e.stopPropagation) {
26.         e.stopPropagation(); //停止事件的传播
27.     }
28.     console.log(e);
29.     return false;
30. }
 
 
注意我们使用了preventDefault和stopPropagation消除了浏览器默认的一些动作。
显然这些事件不是所有的元素都有的,只有互为倍数才有,所以我们要去修改handleDragStart函数了
修改后的代码大致如下
1. function handleDragStart(e) {
2.     this.style.opacity = "0.5";
3.     e.dataTransfer.effectAllowed = "move";
4.     e.dataTransfer.setData("text/plain", this.innerHTML);
5.     //$.log(this.innerHTML);
6.     //$.log(e.target.innerHTML);
7.     //$.log(e.srcElement.innerHTML);
8.     //$.log(this.innerHTML);
9.     [ ].forEach.call(document.querySelectorAll("p"),
10.     function(item) {
11.         var a = parseInt(e.target.innerHTML);
12.         var b = parseInt(item.innerHTML);
13.         if (a % b != 0 && b % a != 0) {
14.             item.style.opacity = "0.1";
15.         }
16.         else {
17.             item.addEventListener("dragover", handleDragOver, false);
18.             item.addEventListener("dragenter", handleDragEnter, false);
19.             item.addEventListener("dragleave", handleDragLeave, false);
20.             item.addEventListener("drop", handleDrop, false);
21.         }
22.     });
23. }
 
现在你可以发现,当我们拖动互为倍数的元素是,视觉效果明显是允许拖入,否则就不允许了。当然记得在handleDragEnd函数中要恢复哦
1. function handleDragEnd(e) {
2.     if (e.preventDefault) {
3.         e.preventDefault(); //不要执行与事件关联的默认动作
4.     }
5.     [ ].forEach.call(document.querySelectorAll("p"),
6.     function(item) {
7.         item.style.opacity = "1";
8.         item.removeEventListener("dragover", handleDragOver, false);
9.         item.removeEventListener("dragenter", handleDragEnter, false);
10.         item.removeEventListener("dragleave", handleDragLeave, false);
11.         item.removeEventListener("drop", handleDrop, false);
12.     }
13.     );
14. }
第四步,当我们在可以放置的元素上结束拖放后,我们希望两个元素的值累计,并出现在被放置的元素里面,我们需要修改handleDrop函数
1. function handleDrop(e) {
2.     if (e.preventDefault) {
3.         e.preventDefault(); //不要执行与事件关联的默认动作
4.     }
5.     if (e.stopPropagation) {
6.         e.stopPropagation(); //停止事件的传播
7.     }
8.     this.innerHTML = parseInt(this.innerHTML)+parseInt(e.dataTransfer.getData("text/plain"))
9.     console.log(e);
10.     return false;
11. }
好了,到现在为止,准备知识都差不多了,而且作品我们也可以得意的玩玩,你可以发现p被累计都,再次拖拉的时候,是重新计算相互的倍数的,对不?
 
最后,我感觉黑色的字不好看,我们修改下初始化的函数
1. $(
2. function() {
3.     [ ].forEach.call(document.querySelectorAll("p"),
4. function(item) {
5.     item.addEventListener("dragstart", handleDragStart, false);
6.     item.addEventListener("dragend", handleDragEnd, false);
7.     item.style.color = "White";
8. }
9. );
10. }
11. );
 
 
好了,现在这个无聊的拖动作品,至少可以打发下你的时间,对不,欣赏下自己的作品吧,接下来,我们开始做正式做数独游戏了。
第一步,我们先生成一个1-9的数字对象矩形,这个矩形可以拖动。
先设计htmltag
1. <ol id="numberBox" style="list-style-type: none; width: 90px; height: 90px;">
2. </ol>
 
 
然后准备些样式
1. [css]
2. 
3. #numberBox > li  
4. 
5. {  
6. 
7.     width: 30px;  
8. 
9.     height: 25px;  
10. 
11.     text-align: center;  
12. 
13.     font-size: 20px;  
14. 
15.     padding-top: 5px;  
16. 
17.     float: left;  
18. 
19.     color: White;  
20. 
21. }  
最后是脚本
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     [{ number: 1, bgcolor: "#C71585" }, { number: 2, bgcolor: "#800080" }, { number: 3, bgcolor: "#B8860B" },  
8. 
9.     { number: 4, bgcolor: "rgb(0,0,128)" }, { number: 5, bgcolor: "rgb(30,144,255)" },   
10. 
11.     { number: 6, bgcolor: "rgb(255,165,0)" },  
12. 
13.      { number: 7, bgcolor: "hsl(0,75%,50%)" }, { number: 8, bgcolor: "hsl(30,50%,50%)" },   
14. 
15.      { number: 9, bgcolor: "hsl(120,75%,38%)"}].forEach(  
16. 
17.      function(key, index) {  
18. 
19.      $.log(key);  
20. 
21.          var li = $("<li>").html(key.number).css("backgroundColor", key.bgcolor).attr("draggable","true");  
22. 
23.          $.log(li);  
24. 
25.          li[0].addEventListener("dragstart", function() {  
26. 
27.          }, false);  
28. 
29.          $("#numberBox").append(li);  
30. 
31.      }  
32. 
33.      );  
34. 
35. }  
36. 
37. );  
好,然后你运行下页面,可以看到一个九宫格,并且每一个格子都可以拖动。
第二步,我们要类似的创建我们填数字得的区域了。
首先还是htmlTag
1. [html]
2. 
3. <ol id="player" style="list-style-type: none; width: 450px; height: 450px;">  
4. 
5. </ol>  
然后是样式设定
1. [css]
2. 
3. #player .default  
4. 
5. {  
6. 
7.     float: left;  
8. 
9.     width: 48px;  
10. 
11.     height: 33px;  
12. 
13.     border: solid 1px rgb(0,0,0);  
14. 
15.     font-size: 20px;  
16. 
17.     padding-top: 15px;  
18. 
19.     text-align: center;  
20. 
21.     background-color: #B8860B;  
22. 
23. }  
24. 
25. #player .fix  
26. 
27. {  
28. 
29.     float: left;  
30. 
31.     width: 48px;  
32. 
33.     height: 33px;  
34. 
35.     border: solid 1px rgb(0,0,0);  
36. 
37.     font-size: 20px;  
38. 
39.     padding-top: 15px;  
40. 
41.     text-align: center;  
42. 
43.     background-color: #FFFABC;  
44. 
45. }  
46. 
47. #player .ation  
48. 
49. {  
50. 
51.     float: left;  
52. 
53.     width: 48px;  
54. 
55.     height: 33px;  
56. 
57.     border: solid 1px rgb(0,0,0);  
58. 
59.     font-size: 20px;  
60. 
61.     padding-top: 15px;  
62. 
63.     text-align: center;  
64. 
65.     background-color: #FFA07A;  
66. 
67. }  
然后初始化这个区域。数独填字区域有的格子有值有的没有值,我用0表示没有值将来你可以填制,非0表示是固定区不可以改 www.2cto.com
现在你已经可以在页面上看到一个非常威武的“独”字了!
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     "500000300090500400004000700051037289302080604008052137035000900609000823080023006".split("").forEach(  
8. 
9.     function(item, index) {  
10. 
11.         $.log(item);  
12. 
13.         var li = $("<li>")  
14. 
15.         if (item != "0") {  
16. 
17.             li.addClass("fix");  
18. 
19.             li[0].innerHTML = item;  
20. 
21.         }  
22. 
23.         else {  
24. 
25.             li[0].classList.add("default");  
26. 
27.             li[0].addEventListener("dragenter",  
28. 
29.             function(e) {  
30. 
31.                 $.log(e);  
32. 
33.             }, false);  
34. 
35.   
36. 
37.             li[0].addEventListener("dragover",  
38. 
39.             function(e) {  
40. 
41.                 if (e.preventDefault) {  
42. 
43.                     e.preventDefault(); //不要执行与事件关联的默认动作  
44. 
45.                 }  
46. 
47.                 if (e.stopPropagation) {  
48. 
49.                     e.stopPropagation(); //停止事件的传播  
50. 
51.                 }  
52. 
53.                 $.log(e);  
54. 
55.                 return false;  
56. 
57.             }, false);  
58. 
59.   
60. 
61.             li[0].addEventListener("dragleave",  
62. 
63.             function(e) {  
64. 
65.             }, false);  
66. 
67.   
68. 
69.             li[0].addEventListener("drop",  
70. 
71.             function(e) {  
72. 
73.                 if (e.preventDefault) {  
74. 
75.                     e.preventDefault(); //不要执行与事件关联的默认动作  
76. 
77.                 }  
78. 
79.                 if (e.stopPropagation) {  
80. 
81.                     e.stopPropagation(); //停止事件的传播  
82. 
83.                 }  
84. 
85.   
86. 
87.             }, false);  
88. 
89.         }  
90. 
91.         $("#player").append(li);  
92. 
93.     }  
94. 
95.     );  
96. 
97. }  
98. 
99. );  

第三步:我们拖动数字之后,希望可以填数字的区域有明显的颜色变化并给出提示,同时固定区域不可以拖进去,其他区域可以拖进去,并且拖动的时候要send值。
有了前面的知识,我们马上知道去哪里改事件控制了:dragstart事件
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     [{ number: 1, bgcolor: "#C71585" }, { number: 2, bgcolor: "#800080" }, { number: 3, bgcolor: "#B8860B" },  
8. 
9.     { number: 4, bgcolor: "rgb(0,0,128)" }, { number: 5, bgcolor: "rgb(30,144,255)" },  
10. 
11.     { number: 6, bgcolor: "rgb(255,165,0)" },  
12. 
13.      { number: 7, bgcolor: "hsl(0,75%,50%)" }, { number: 8, bgcolor: "hsl(30,50%,50%)" },  
14. 
15.      { number: 9, bgcolor: "hsl(120,75%,38%)"}].forEach(  
16. 
17.      function(key, index) {  
18. 
19.          //$.log(key);  
20. 
21.          var li = $("<li>").html(key.number).css("backgroundColor", key.bgcolor).attr("draggable", "true");  
22. 
23.          //$.log(li);  
24. 
25.          li[0].addEventListener("dragstart", function(e) {  
26. 
27.              e.dataTransfer.effectAllowed = "copyMove";  
28. 
29.              e.dataTransfer.setData("text/plain", this.innerHTML);  
30. 
31.              $.log(this.innerHTML);  
32. 
33.              [ ].forEach.call(document.querySelectorAll("#player .default"),  
34. 
35.          function(item) {  
36. 
37.              //$.log(item);  
38. 
39.              item.classList.remove("default");  
40. 
41.              item.classList.add("ation");  
42. 
43.          });  
44. 
45.          }, false);  
46. 
47.   
48. 
49.          li[0].addEventListener("dragend", function() {  
50. 
51.              [ ].forEach.call(document.querySelectorAll("#player .ation"),  
52. 
53.          function(item) {  
54. 
55.              item.classList.remove("ation");  
56. 
57.              item.classList.add("default");  
58. 
59.          });  
60. 
61.          }, false);  
62. 
63.   
64. 
65.          $("#numberBox").append(li);  
66. 
67.      }  
68. 
69.      );  
70. 
71. }  
72. 
73. );  
 
 
现在你可以测试下了,当你拖动数字的时候,有明显的颜色改变,并且不同的区域你的鼠标样式也不同哦。
第四步,我们接受值,并且判断这个值是否存在行列冲突,如果冲突就提示,否则改写
1. [javascript]
2. 
3.  $(  
4. 
5. function() {  
6. 
7.     "500000300090500400004000700051037289302080604008052137035000900609000823080023006".split("").forEach(  
8. 
9.     function(item, index) {  
10. 
11.         $.log(item);  
12. 
13.         var li = $("<li>")  
14. 
15.         if (item != "0") {  
16. 
17.             li.addClass("fix");  
18. 
19.             li[0].innerHTML = item;  
20. 
21.         }  
22. 
23.         else {  
24. 
25.             li[0].classList.add("default");  
26. 
27.             li[0].addEventListener("dragenter",  
28. 
29.             function(e) {  
30. 
31.                 $.log(e);  
32. 
33.             }, false);  
34. 
35.   
36. 
37.             li[0].addEventListener("dragover",  
38. 
39.             function(e) {  
40. 
41.                 if (e.preventDefault) {  
42. 
43.                     e.preventDefault(); //不要执行与事件关联的默认动作  
44. 
45.                 }  
46. 
47.                 if (e.stopPropagation) {  
48. 
49.                     e.stopPropagation(); //停止事件的传播  
50. 
51.                 }  
52. 
53.                 $.log(e);  
54. 
55.                 return false;  
56. 
57.             }, false);  
58. 
59.   
60. 
61.             li[0].addEventListener("dragleave",  
62. 
63.             function(e) {  
64. 
65.             }, false);  
66. 
67.   
68. 
69.             li[0].addEventListener("drop",  
70. 
71.             function(e) {  
72. 
73.                 if (e.preventDefault) {  
74. 
75.                     e.preventDefault(); //不要执行与事件关联的默认动作  
76. 
77.                 }  
78. 
79.                 if (e.stopPropagation) {  
80. 
81.                     e.stopPropagation(); //停止事件的传播  
82. 
83.                 }  
84. 
85.   
86. 
87.                 var sendData = e.dataTransfer.getData("text/plain");  
88. 
89.                 //获得#player>li矩阵数组  
90. 
91.                 var matrix = Array.prototype.slice.call(document.querySelectorAll("#player>li"));   
92. 
93.                 var currIndex = matrix.indexOf(this); //获得当前元素的位置  
94. 
95.                 var rowIndex = currIndex - currIndex % 9; //行开始的位置  
96. 
97.                 var colIndex = currIndex % 9//列开始的位置  
98. 
99.                 for (var i = rowIndex; i < rowIndex + 9; i++) {  
100. 
101.                     if (i != currIndex && matrix[i].innerHTML == sendData) {  
102. 
103.                         alert("对不起行上有数据重复,请小心哦!亲");  
104. 
105.                         return;  
106. 
107.                     }  
108. 
109.                 }  
110. 
111.                 for (var i = colIndex; i < 81; ii = i + 9) {  
112. 
113.                     if (i != currIndex && matrix[i].innerHTML == sendData) {  
114. 
115.                         alert("对不起列上有数据重复,请小心哦!亲");  
116. 
117.                         return;  
118. 
119.                     }  
120. 
121.                 }  
122. 
123.                 this.innerHTML = sendData;  
124. 
125.   
126. 
127.             }, false);  
128. 
129.         }  
130. 
131.         $("#player").append(li);  
132. 
133.     }  
134. 
135.     );  
136. 
137. }  
138. 
139. );  
140. 
141.  
现在你可以开始玩啦,虽然颜色不怎么好看,但至少可以玩,对不,我们第一个html5的实用游戏。我后期的blog打算再做些类似新浪微博的“你画我猜”还有“接龙游戏”。

 

 


摘自 shyleoking的专栏

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! html5教程,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的html5教程-使用HTML5的drag&drop做一个数独游戏全部内容,希望文章能够帮你解决html5教程-使用HTML5的drag&drop做一个数独游戏所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:CSSHTML