目录
先看效果图:
单飞:
双飞:
完成后的页面:
实现思路:
1.切图:用 background:url('+url+') no-repeat -60px -60px 这种语法,将图片切成一张张小图,添加到一个数组item里面。
2.在上一步中同步用数组keys存取小图的下标,9张小图的话(keys就输数字0-8的数组),同时用另外一个数组存下每个小图的坐标。
3.点击开始 用Math.random()>0.5?1:-1 对keys进行随机排序。
4.然后遍历keys,拿到下标对应找到存取小图片的数组item取到小图片,然后执行飞入动画即可。
5.双飞的话,就是将keys分成两个,第一个方式不变,第2个设置好每个元素的left,然后从右边飞入。
代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<style>
*{
margin:0;
padding:0;
}
.small{
top: 10px;
position: absolute;
}
.small_img{
display: block;
width: 200px;
margin-left: 10px;
}
.button{
margin-left: 10px;
font-size: 18px;
width: 60px;
letter-spacing: 5px;
}
div.box{
float:left;
width: 600px;
height: 600px;
position: absolute;
left: 50%;
top:10px;
margin-left: -300px;
border: 1px solid darkseagreen;
}
.active{
border:2px dashed palevioletred;
z-index:9;
}
.not_active{
z-index:1;
}
.input{
width:30px;
}
.modelActive{
background:lightblue;
}
</style>
</head>
<body>
<div class="small">
<img class="small_img" src='../images/j/1.jpg' />
<br>
<div style='margin-left:10px;'>
难度系数:<input type='text' id='difficulty_col' value='10' class='input'>
<input type='text' id='difficulty_row' value='10' class='input'>
<span id='msg' style='color:red;'></span>
</div>
<br>
<input type='button' value='开始' id='start' class="button"/>
<input type='button' value='换换' id='next' class="button"/>
<input type='button' value='单飞' onclick='changeModel(1)' id='modelOne' class="button modelActive"/>
<input type='button' value='双飞' onclick='changeModel(2)' id='modelTwo' class="button"/>
</div>
<div class="box" id='box'></div>
</body>
<script>
var model=1;//飞入模式
var speed=60;//初步设定30毫秒,可以改小加快速度、改大减缓速度
function Jigsaw(col,row){
this.box=document.getElementById("box");
this.row=row;
this.col=col;
this.row=row||3;
this.col=col||3;
this.boxWidth=600;
this.boxHeight=600;
this.itemWidth = this.boxWidth/this.col;
this.itemHeight= this.boxHeight/this.row;
//存放每个小图片的数组
this.item=[];
//存放key
this.keys=[];
//存放坐标的数组
this.posArr=[];
this.len=this.row*this.col;
this.init();
}
//初始化
Jigsaw.prototype.init=function(){
var fragment=document.createDocumentFragment();
var url = small_img.src;
var rowNum=0,colNum=0;
for(var i=0;i<this.len;i++){
var div=document.createElement('div');
div.style.cssText='cursor:move;background:url('+url+') no-repeat -'+(i%this.col)*this.itemWidth+'px -'+Math.floor((i)/this.col)*this.itemHeight+'px;'
+'float:left;height:'+this.itemHeight+'px;width:'+this.itemWidth+'px;position:absolute;FILTER: alpha(opacity=0);opacity: 0;';
this.item.push(div);
this.keys.push(i);
if(i>0){
if(i%this.col===0){
rowNum++;
}
if(i%this.col===0){
colNum=0;
}
}
//存放好小图片最终的位置 left top
this.posArr.push({
left:colNum++*this.itemWidth,
top:rowNum*this.itemHeight
})
fragment.appendChild(div);
}
this.box.innerHTML="";
this.box.appendChild(fragment);
}
//开始
Jigsaw.prototype.start=function(){
//随机位置
this.keys.sort(function(a,b){
return Math.random()>0.5?1:-1;
})
//根据模式来确定执行
if(model==2){
this.modelTwo();
}else{
this.modelOne();
}
}
//单飞
Jigsaw.prototype.modelOne=function(){
this.doInto(this.keys);
}
//双飞
Jigsaw.prototype.modelTwo=function(){
var keys = this.keys;
var keys1=[],keys2=[];
var middle = Math.ceil(keys.length/2);
//将keys分成2半
for(var i=0;i<keys.length;i++){
if(i<middle){
keys1.push(keys[i]);
}else{
keys2.push(keys[i]);
}
}
this.doInto(keys1);//左上角飞入
this.doInto(keys2,2);//右上角飞入
}
//执行飞入的函数
Jigsaw.prototype.doInto=function(arr,type){
for(var i=0;i<arr.length;i++){
var item = this.item[arr[i]];
var pos = this.posArr[arr[i]];
if(type==2){//先定位到右上角
item.style.left=(600-this.itemWidth)+'px';
item.style.top='0px';
}
(function(o,j){//采用闭包的模式调用
var o_left=pos.left+'px',o_top=pos.top+'px';
var param = {'left': o_left,'top': o_top,'opacity':1};
setTimeout(function(){//用setTimeout来将多个小图片依次飞入
animate(o,param,'fast');//使用自己封装的动画函数
},j*speed);
})(item,i);
}
}
//获取属性值
function getStyle(obj, prop) {
var prevComputedStyle = document.defaultView ? document.defaultView.getComputedStyle( obj, null ) : obj.currentStyle;
return prevComputedStyle[prop];
}
/*
obj:dom对象
prop:动画参数
speed:执行速度 fast slow 3000等
func:回调函数
*/
function animate(obj,prop,speed,func){
//防止重复动画事件
if(obj.timer) return ;
//定义定时器执行次数和总执行时间
var limit=20,totalTime;
if(typeof speed==='number'){//如果传入的是
totalTime = speed;
}else if(speed==='slow'){
totalTime = 600;
}else if(speed==='fast'){
totalTime = 200;
}else{
totalTime = 400;
}
var time = totalTime/limit;
var n=0,cache={},display,primary_cur;//cache用来缓存,省的每次都去dom获取
obj.timer = setInterval(function(){
n++;//执行次数每次递增
for(var p in prop){
if("display"===p) {
display = prop["display"];
if(display!=='none'){
obj.style['display'] = display;
}
delete prop["display"];
continue;
}
//判断是否是可以递增的属性,如果不是则直接让它生效,并从prop中删除,删除后就不用每次任务都执行它
var reg = /^(\d)+(px$)?/;//数字和像素这样的判定为可以递增的属性
if(!reg.test(prop[p])){
obj.style[p] = prop[p];
delete prop[p];
continue;
}
var value,opacityFlag=(p == "opacity")?true:false;
var cur = 0;
if(cache[p+"_cur"]){//从缓存中取
cur = cache[p+"_cur"];
value = cache[p+"_value"];
}else{
value = prop[p];
if(opacityFlag) {
//如果本来是隐藏的则cur默认就是0
if(getStyle(obj, 'display')!=='none'){
cur = Math.round(parseFloat(getStyle(obj, p)) * 100);
}
} else {
cur = parseInt(getStyle(obj, p));
//处理100px的格式
(typeof value==='string') && (value=value.replace(/px$/,""));
}
primary_cur=cur;
cache[p+"_value"] = value;
}
var incre ;
if(cache[p+'_increment']){//如果缓存中有则从中取
incre = cache[p+'_increment'];
}else{
if(opacityFlag){
incre = (value*100-cur)/limit;//计算每次变化值
}else{
incre = (value-cur)/limit;//计算每次变化值
}
cache[p+'_increment']= incre;
}
//缓存起来,这样就不用每次都去dom中获取了。
cache[p+"_cur"] = cur + incre;
if (opacityFlag) {
obj.style.filter = "alpha(opacity:"+(cur + incre)+" )";
obj.style.opacity = (cur + incre)/100 ;
}else {
obj.style[p] = cur + incre + "px";
}
}
//如果达到了最大执行次数,要清除定时器,并执行回调函数
if(n==limit){
if(display==='none'){
obj.style['display'] = 'none';
}
//清除定时器
clearInterval(obj.timer);
obj.timer=undefined;
func && func();
}
},time)
}
var _ = {
isFunction : function(o){
return o!== null &&typeof o ==='function';
}
}
var msg = document.getElementById("msg");
var difficulty_col=document.getElementById("difficulty_col");
difficulty_col.onblur=function(){
var temp = parseInt(this.value);
if(isNaN(temp)){
temp=3;
}
this.value = temp;
if(this.value>10){
this.value = 10;
msg.innerText="太难了,不能超过10";
}else if(this.value<2){
this.value = 2;
msg.innerText="太容易了,不能小于2";
}else
msg.innerText="";
}
var difficulty_row=document.getElementById("difficulty_row");
difficulty_row.onblur=function(){
var temp = parseInt(this.value);
if(isNaN(temp)){
temp=3;
}
this.value = temp;
if(this.value>20){
this.value = 20;
msg.innerText="太难了,不能超过20"
}else if(this.value<2){
this.value = 2;
msg.innerText="太容易了,不能小于2";
}else{
msg.innerText="";
}
}
var small_img =document.getElementsByClassName("small_img")[0];
document.getElementById("next").onclick=function(){
var src = small_img.src;
var reg = /(\d+)\.jpg$/;
var arr = reg.exec(src);
var index=1;
if(arr.length>1){
index = ++arr[1];
if(index>=6){
index=1;
}
}
small_img.src='../images/j/'+index+'.jpg';
jigsaw = new Jigsaw(difficulty_col.value,difficulty_row.value);
}
function changeModel(type){
var modelOne = document.getElementById("modelOne");
var modelTwo = document.getElementById("modelTwo");
if(type==1){
model=1;
modelOne.className='button modelActive';
modelTwo.className='button';
}else{
model=2;
modelTwo.className='button modelActive';
modelOne.className='button';
}
}
var jigsaw = new Jigsaw(difficulty_col.value,difficulty_row.value);
document.getElementById("start").onclick=function(){
//开始
jigsaw = new Jigsaw(difficulty_col.value,difficulty_row.value);
jigsaw.start();
}
</script>
</html>