最近在搞一个很复杂的页面,搞得脑子有点疲劳。。。抽空把前段时间用jQuery UI写的一个非常简单的九宫格拼图重新分析一下,转换一下心情。
jQuery UI提供了许多非常有用的工具,如draggable、droppable等。这可以让我们用很少的代码实现复杂的功能,并且做到多浏览器兼容。
这个九宫格拼图根据需求的不同,我做了两个版本。由于两个版本的JS代码变化还是比较大的,所以我准备分开来讲。先讲最初也是最简单的版本。一步步来。
- 首先建好HTML文件,把你的9张切割好的图片都扔进去:
<!doctype> <html> <head> </head> <body> <div id="jigsaw"> <img src="images/puzzle_r1_c1.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r1_c2.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r1_c3.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r2_c1.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r2_c2.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r2_c3.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r3_c1.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r3_c2.gif" width="150" height="100" alt="Puzzle Piece"/> <img src="images/puzzle_r3_c3.gif" width="150" height="100" alt="Puzzle Piece"/> </div> <script type="text/javascript" src="scripts/jquery-1.7.2.min.js"></script> <script type="text/javascript" src="scripts/jquery-ui-1.8.21.custom.min.js"></script> <script type="text/javascript" src="scripts/jigsaw.js"></script> </body> </html>
注意:图片插入顺序需要为正确顺序。稍后会用JS来打乱图片的顺序。 - 加上CSS使图片呈九宫格分布:
#jigsaw{float:left;width:450px;} #jigsaw IMG{float:left;width:150px;height:100px;}
- 开始编写我的jigsaw.js。首先记录一下我们经常需要用到的量:
var jigsaw = $('#jigsaw'), imgs = jigsaw.find("IMG"); var col = 3, row = 3, match = col * row, width = imgs.width(), height = imgs.height(), order = new Array();
- 接着,做一些准备工作。在这里,我为了便于判断图片的顺序,将正确的顺序写入图片的ID中。
imgs.each(function(i){ $(this).attr('id','jigsaw' + i); $(this).addClass("ready"); });
然后,打乱图片的顺序。
这里用到了上面一段代码中,给图片加的"ready"类。
思路是:在有"ready"这个class的图片中,随机选择一张图片,按从左到右、从上到下的顺序依次插入九宫格的相应位置,然后去掉它的"ready"类,直至9张图片位置都调整完成,match这个变量减为0。同时,在图片下面插入9个用于吸附图片的DIV。for( match; match>0; match-- ){ $("<div/>").appendTo(jigsaw); var now = col * row - match, nowCol = now % col, nowRow = parseInt( now / col ); var selectImg = imgs.filter(".ready").eq( parseInt( Math.random() * 10 ) % match ); selectImg.css({ 'left': nowCol * width, 'top': nowRow * height }); selectImg.removeClass("ready"); order[now] = selectImg.attr('id').replace(/jigsaw/i,""); }
如上,我用imgs.filter(".ready")先选出带有"ready"这个类的图片,然后用随机数选出第parseInt(Math.random()*10)%match张图片,将图片放到相应位置。
改变位置后,我将目前的位置顺序记录到数组order中。
做这步之后,还要将CSS做一些改动。如下:#jigsaw{float:left; width:450px; margin:103px 0 0 150px; position:relative; z-index:1;} #jigsaw DIV{float:left; width:150px; height:100px; padding:0;} #jigsaw IMG{float:left; width:150px; height:100px; font-size:3em; color:#fff; background:#ccc; position:absolute; z-index:2;}
- 接下来就要用神奇的jQuery UI来实现图片的拖放功能了。
思路:图片拖到对应位置附近,就会被“吸附”进对应的DIV中,并且不能再被拖动。$('DIV', jigsaw).each( function(i){ var obj = $( "#jigsaw" + order[i] ); if( obj.attr('id') == 'jigsaw' + i ){ match++; obj.appendTo( $(this) ).addClass("dropped"); } else{ obj.draggable(); $(this).droppable({ drop:function( event, ui ){ if( ui.draggable.attr('id')== 'jigsaw' + i ){ ui.draggable.appendTo($(this)).addClass("dropped"); match++; ui.draggable.draggable("disable"); $(this).droppable("disable"); if( match == 9 ){alert("Match!");} } } }); } });
如上,首先按排列顺序检查每张图片,是否正好分布在对应的位置。如果已经在对应的位置,则将它挪入对应的DIV中,给它一个class为"dropped",match数加1。
dropped的CSS:#jigsaw IMG.dropped{ position:static !important;}
将图片插入对应的div中后,需要将position属性更改为static,则图片会自动与DIV对齐。如果图片没有在对应位置,使用jQuery UI的Draggable方法使图片可以被拖动,并且使用Droppable方法使对应的DIV可以吸附图片。
在DIV吸附图片的时候判断这张图片是不是被吸附在对应的DIV上,是的话给它加上"dropped"类,match数加1,并且禁掉这个DIV的可吸附性。
当match为9的时候,即为9张图片都已经拖到对应位置,给出已经拼图完成的提示就大功告成啦!
另外一个版本比这个稍微高级一点。图片拖对位置之后,还可以重新被拖出去。虽说是在这个版本的基础上改的,但是基本上面目全非了T-T。下次放上来。