最近在搞一个很复杂的页面,搞得脑子有点疲劳。。。抽空把前段时间用jQuery UI写的一个非常简单的九宫格拼图重新分析一下,转换一下心情。

jQuery UI提供了许多非常有用的工具,如draggable、droppable等。这可以让我们用很少的代码实现复杂的功能,并且做到多浏览器兼容。

这个九宫格拼图根据需求的不同,我做了两个版本。由于两个版本的JS代码变化还是比较大的,所以我准备分开来讲。先讲最初也是最简单的版本。一步步来。

  1. 首先建好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>
  1. 注意:图片插入顺序需要为正确顺序。稍后会用JS来打乱图片的顺序。
  2. 加上CSS使图片呈九宫格分布:
#jigsaw{float:left;width:450px;}
#jigsaw IMG{float:left;width:150px;height:100px;}

  1. 开始编写我的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();
  1. 接着,做一些准备工作。在这里,我为了便于判断图片的顺序,将正确的顺序写入图片的ID中。
imgs.each(function(i){
	$(this).attr('id','jigsaw' + i);
	$(this).addClass("ready");
});
  1. 然后,打乱图片的顺序。
    这里用到了上面一段代码中,给图片加的"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,"");
}
  1. 如上,我用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;}
  1. 接下来就要用神奇的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!");}
				}
			}
		});
	}
});
  1. 如上,首先按排列顺序检查每张图片,是否正好分布在对应的位置。如果已经在对应的位置,则将它挪入对应的DIV中,给它一个class为"dropped",match数加1。
    dropped的CSS:
#jigsaw IMG.dropped{ position:static !important;}
  1. 将图片插入对应的div中后,需要将position属性更改为static,则图片会自动与DIV对齐。如果图片没有在对应位置,使用jQuery UI的Draggable方法使图片可以被拖动,并且使用Droppable方法使对应的DIV可以吸附图片。
    在DIV吸附图片的时候判断这张图片是不是被吸附在对应的DIV上,是的话给它加上"dropped"类,match数加1,并且禁掉这个DIV的可吸附性。
    当match为9的时候,即为9张图片都已经拖到对应位置,给出已经拼图完成的提示就大功告成啦!

另外一个版本比这个稍微高级一点。图片拖对位置之后,还可以重新被拖出去。虽说是在这个版本的基础上改的,但是基本上面目全非了T-T。下次放上来。