利用HTML5的drop、drag及拖动属性做元素位置交换《我是学霸》 - 图1

    很久没来这里,我也安静了很久。经过半年的技术转型,我现在是一名彻底前端开发人员,并也已前端开发人员的身份找到了工作。从后端的种种在到前端的种种,我技术转型成功了。

    空闲时间总结前段时间看过的html5的拖动写了一个小东东《我是学霸》,个人能力有限就没有做比较严谨的关卡设计,望大家理解。

    设计思路:使用九宫格作为画布背景;每个九宫格中的元素为数字、数学公式、物理公式(注:一切能在数学条件下代表大小的元素);拖动九宫格选中元素到目标元素,元素进行两两交换位置;在每一次元素位置发生变化时进行比较当前九宫格中所有元素是否由小到大顺序排列,如顺序排列就进入下一关;
    技术要点:jquery、drop、drag、cookie
    实现步骤:
    1.解决九宫格展现内容问题:将九宫格中的元素内容做成80*80的图片并按照图片内容按照大小顺序数字编号排列好,为什么要将图片按照数字大小编号呢?容我在这里买个小关子(在代码中有答案,前提是你能看懂)。

    利用HTML5的drop、drag及拖动属性做元素位置交换《我是学霸》 - 图2

    2.绘制九宫格:使用css+html+js实现。
    3.记录游戏当前信息:关卡、移动步数、原始序列、当前移动序列、历史移动序列。使用cookie来记录这些信息。
    4.实现九宫格元素两两交换:使用html5的特性drop与drag来实现。

    css

    1. h1{
    2. text-align: center;
    3. }
    4. #toast{
    5. min-width:10px;
    6. position: absolute;
    7. top:-50px;
    8. left:45%;
    9. border:1px #ccc solid;
    10. padding:10px 20px;
    11. background-color: #000;
    12. color: #fff;
    13. border-radius: 10px;
    14. display: none;
    15. }
    16. #heading{
    17. width: 320px;
    18. border: 0px #ccc solid;
    19. margin: 0 auto;
    20. padding: 10px 0px;
    21. }
    22. #tf_box {
    23. width: 300px;
    24. height: 300px;
    25. border: 1px #ccc solid;
    26. margin: 0 auto;
    27. padding: 10px;
    28. }
    29. .div_box {
    30. float: left;
    31. width: 80px;
    32. height: 80px;
    33. margin: 2px;
    34. padding: 7px;
    35. border: 1px solid #aaaaaa;
    36. }
    37. *[draggable=true] {
    38. -moz-user-select:none;
    39. -khtml-user-drag: element;
    40. cursor: move;
    41. }
    42. img {
    43. display:inline-block;
    44. transition: all 100ms;
    45. position: absolute;
    46. }
    47. img.move {
    48. -webkit-transform:scale3d( 1.1, 1.1, 1.1 );
    49. }

    html

    1. <h1>我是学渣</h1>
    2. <div id="toast">这里输出鼓励消息</div>
    3. <div id="tf_box"></div>
    4. <div id="heading">
    5. <input id="instruct" type="button" value="玩法说明">
    6. <input id="btn" type="button" value="复位">
    7. <div id="gameMsg" style="padding-top:10px;">
    8. 当前级别: <b>1</b><br>
    9. 当前移动次数: <b>0</b><br>
    10. 总计移动次数: <b>0</b><br>
    11. </div>
    12. </div>

    js
    向cookie记录并输出当前每一步的信息

    1. function cookieHelpers() {
    2. //记录并输出每一步的信息
    3. this.writeCookies = function(game) {
    4. var toWrite = "px=" +
    5. game.level + " " +
    6. game.totalClicks + " " +
    7. game.currentClicks + " " +
    8. game.dataY + " " +
    9. game.pa + " " +
    10. game.pb + " " +
    11. game.dataP + " " +
    12. ";";
    13. document.cookie = toWrite;
    14. console.log(document.cookie);
    15. }
    16. }

    定义过关提示与周边其它信息

    1. function cheesyWordGetter() {
    2. this.words = ['非常好', '干得漂亮', '帅呆了', '哇塞', 'I服U', '天才诞生了'];
    3. /**
    4. * 页面过关鼓励提示
    5. * @return {[type]} [description]
    6. */
    7. this.getWord = function() {
    8. var _this = this;
    9. $('#toast').html(_this.words[Math.floor(Math.random()*_this.words.length)]);
    10. $('#toast').fadeIn().animate({top:"50px"}, "slow", function() {
    11. $(this).animate({top: "-50px"}, 500).fadeOut();
    12. });
    13. }
    14. /**
    15. * 玩法说明
    16. * @return {[type]} [description]
    17. */
    18. this.instruct = function() {
    19. $('#gameMsg').html("如何才算赢:使拼板全部元素从小到大排列。拖动一个元素都另一个元素上,这两个元素就会交换位置。");
    20. }
    21. /**
    22. * 更新页面统计信息
    23. * @param {[type]} game [description]
    24. * @return {[type]} [description]
    25. */
    26. this.updateCounts = function(game) {
    27. var htmlMsg = "当前级别: <b>" + game.level + "</b><br>"+
    28. "当前移动次数: <b>" + game.currentClicks +"</b><br>"+
    29. "总计移动次数: <b>" + game.totalClicks + "</b><br>"+
    30. "";//this.dataY+"<br>"+this.dataP
    31. $('#gameMsg').html(htmlMsg);
    32. }
    33. }

    定义游戏相关方法

    1. function GameBoard(){
    2. var self = this;
    3. this.cwg = new cheesyWordGetter();
    4. this.cook = new cookieHelpers();
    5. this.pa = '0';
    6. this.pb = '0';
    7. this.dataY = [];//原始序列
    8. this.dataP = [];//排序序列
    9. this.level = 1;//等级
    10. this.currentClicks = 0; //当前移动次数
    11. this.totalClicks = 0; //总计移动次数
    12. /**
    13. * 开始游戏
    14. * @return {[type]} [description]
    15. */
    16. this.beginGame = function() {
    17. var vv = self.createRandom(9,1,9);
    18. this.dataY = vv.toString();
    19. this.dataP = vv;
    20. this.cook.writeCookies(this);
    21. self.renderBoard();
    22. }
    23. /**
    24. * 进入下一关
    25. * @return {[type]} [description]
    26. */
    27. this.resetGame = function() {
    28. this.level++;
    29. var vv = self.createRandom(9,1,9+this.level);
    30. this.dataY = vv.toString();
    31. this.dataP = vv;
    32. this.cook.writeCookies(this);
    33. self.setupLevel();
    34. }
    35. /**
    36. * 复位
    37. * @return {[type]} [description]
    38. */
    39. this.setupLevel = function(){
    40. this.currentClicks = 0;//复位当前移动次数
    41. self.renderBoard();
    42. self.updateCounts();
    43. }
    44. /**
    45. * 产生不重复的随机数
    46. * @param {[type]} num [要产生多少个随机数]
    47. * @param {[type]} from [产生随机数的最小值]
    48. * @param {[type]} to [产生随机数的最大值]
    49. * @return {[type]} [description]
    50. */
    51. this.createRandom = function(num ,from ,to){
    52. var arr=[];
    53. for(var i=from;i<=to;i++)
    54. arr.push(i);
    55. arr.sort(function(){
    56. return 0.5-Math.random();
    57. });
    58. arr.length=num;
    59. return arr;
    60. }
    61. /**
    62. * 初始画布
    63. * @return {[type]} [description]
    64. */
    65. this.renderBoard = function(){
    66. var html = '';
    67. $.each(this.dataY.split(","),function(i,itme){
    68. html+='<div class="div_box" >';
    69. html+='<img draggable="true" src="image/tf/'+itme+'.png" id="drag'+itme+'" data-num="'+itme+'" />';
    70. html+='</div>';
    71. });
    72. $('#tf_box').html("").append(html);
    73. var fl = $('.div_box').find("img");
    74. fl.each(function(index, el) {
    75. var _this=$(this);
    76. // console.log(_this.attr("data-num"));
    77. var t = _this.position().top;
    78. var l = _this.position().left;
    79. _this.css({
    80. "top": t+'px',
    81. "left": l+'px'
    82. });
    83. });
    84. self.isDrop();
    85. }
    86. /**
    87. * 绑定拖动事件
    88. * @return {Boolean} [description]
    89. */
    90. this.isDrop=function(){
    91. var _this = this;
    92. var origin, is_moving = false;
    93. $("#tf_box").find("img").on("drop",
    94. function(e) {
    95. _this.pa=$(origin).attr('data-num');
    96. _this.pb=$(e.target).attr('data-num');
    97. var origin_pos = $(origin).position();
    98. var target_pos = $(e.target).position();
    99. $(origin).addClass("move").animate(target_pos, "fast",
    100. function() {
    101. $(this).removeClass("move");
    102. });
    103. $(e.target).addClass("move").animate(origin_pos, "fast",
    104. function() {
    105. $(this).removeClass("move");
    106. });
    107. self.updateCount();
    108. }).on("dragstart",
    109. function(e) {
    110. if (is_moving) {
    111. return false;
    112. }
    113. is_moving = true;
    114. e.originalEvent.dataTransfer.effectAllowed = 'move';
    115. origin = this;
    116. }).on("dragover",
    117. function(e) {
    118. if (e.stopPropagation()) e.stopPropagation();
    119. if (e.preventDefault) e.preventDefault(); // allows us to drop
    120. is_moving = false;
    121. e.originalEvent.dataTransfer.dropEffect = 'move'; // only dropEffect='copy' will be dropable
    122. });
    123. }
    124. /**
    125. * 更新统计数
    126. * @return {[type]} [description]
    127. */
    128. this.updateCount = function() {
    129. this.currentClicks++; //当前移动次数
    130. this.totalClicks++; //总计移动次数
    131. self.isSort();
    132. self.updateCounts();
    133. }
    134. this.updateCounts = function() {
    135. this.cwg.updateCounts(this);
    136. this.cook.writeCookies(this);
    137. }
    138. /**
    139. * 移动元素位置
    140. * @return {Boolean} [description]
    141. */
    142. this.isSort = function(){
    143. var _this=this;
    144. var a = this.pa;
    145. var b = this.pb;
    146. var arr = this.dataP;
    147. var i=0,len=arr.length,j,k;
    148. for(;i<len;i++){
    149. if(arr[i] == a)
    150. {
    151. j=i;
    152. }
    153. if(arr[i] == b)
    154. {
    155. k=i;
    156. }
    157. }
    158. i=arr[j];
    159. arr[j]=arr[k];
    160. arr[k]=i;
    161. self.ifSort();
    162. }
    163. /**
    164. * 判断元素是否序列排序
    165. * @return {[type]} [description]
    166. */
    167. this.ifSort = function(){
    168. var bo = false;
    169. var arr = this.dataP;
    170. for(var i=0;i<arr.length-1;i++){
    171. if(arr[i]>arr[i+1]){
    172. bo = false;
    173. return;
    174. }else{
    175. bo = true;
    176. }
    177. }
    178. if(bo){
    179. this.cwg.getWord();
    180. self.resetGame();
    181. }
    182. }
    183. }

    利用HTML5的drop、drag及拖动属性做元素位置交换《我是学霸》 - 图3

    源码包 http://download.csdn.net/detail/u012793146/8857407