JavaScript实现的拼图算法分析


Posted in Javascript onFebruary 13, 2019

本文实例分析了JavaScript实现的拼图算法。分享给大家供大家参考,具体如下:

学了html5的拖拽事件,相信做出一款小小的拼图游戏也不难吧。就来说一下怎么用drag事件完成拼图游戏吧,当然html5的新方法在IE下是不兼容的。这里我把这个拼图游戏封装成一个小插件,感兴趣的话可以直接copy来用,使用方法很简单。

HTML,3个div里面什么都不用写,分别是用来放拼图,参照图,拼图面吧的。

<div id="selectpanel"></div>
<div id="orginalimg"></div>
<div id="mathpanel"></div>

CSS,这里CSS基本不用写,要写的话可以把margin和padding归0,最好还是写一下。

*{margin: 0;padding: 0;}

重点javascript脚本(封装部分)

function Puzzle(imgWidth,imgHeight,cuttingoffX,cuttingoffY,img){
  var selectPanel=document.getElementById("selectpanel");//拼图面板
  var mathPanel=document.getElementById("mathpanel");//拼图匹配面板
  var orginalImg=document.getElementById("orginalimg");//参照图面板
  selectPanel.style.cssText='width: auto;height: auto;border: 2px solid black;overflow: hidden;float: left;margin: 10px;';
  mathPanel.style.cssText='width: auto;height: auto;border: 2px solid black;overflow: hidden;float: right;margin: 10px;';
  var amount=(imgWidth/cuttingoffX)*(imgHeight/cuttingoffY);//根据自定义每块拼图的宽高,计算拼图的总数量
  var jsonPosition=[];
  for(var i=0;i<amount;i++){//一个数组模拟成一个二维矩阵,用json来存这个矩阵,并且每个位置给它一个匹配值M
    jsonPosition[i]={X:i%(imgWidth/cuttingoffX),Y:parseInt(i/(imgHeight/cuttingoffY)),M:i};
  }
  for(var c=0;c<amount;c++){//随机生成拼图位置
    var divImg=document.createElement("div");
    divImg.style.width=cuttingoffX+"px";
    divImg.style.height=cuttingoffY+"px";
    divImg.style.backgroundImage="url(img/"+img+")";
    divImg.style.backgroundRepeat="no-repeat";
    divImg.style.border="1px dashed gray";
    divImg.style.float="left";
    divImg.style.cursor="pointer";
    if(c%(imgWidth/cuttingoffX)==0&&c!=0)
    divImg.style.clear="left";
    var rendomPositon=jsonPosition.splice(Math.floor(Math.random()*jsonPosition.length),1)[0];
    divImg.style.backgroundPosition=rendomPositon['X']*(-cuttingoffX)+'px'+' '+rendomPositon['Y']*(-cuttingoffY)+'px';
    divImg.draggable="true";
    divImg.maths=rendomPositon["M"];
    selectPanel.appendChild(divImg);
  }
  for(var c=0;c<amount;c++){//生成拼图匹配面板
    var divEmpty=document.createElement("div");
    divEmpty.style.width=cuttingoffX+"px";
    divEmpty.style.height=cuttingoffY+"px";
    divEmpty.style.border="1px solid gray";
    divEmpty.style.float="left";
    if(c%(imgWidth/cuttingoffX)==0&&c!=0)
    divEmpty.style.clear="left";
    divEmpty.maths=c;
    mathPanel.appendChild(divEmpty);
  }
  var orginalImgWidth=document.body.clientWidth-(selectPanel.offsetWidth+selectPanel.offsetLeft+10)*2;
  orginalImg.style.cssText="width: "+orginalImgWidth+"px;height:"+orginalImgWidth+"px;position:absolute;left:50%;margin-left:"+(-orginalImgWidth/2)+"px;top:10px;";
  orginalImg.style.background="url(img/"+img+") no-repeat 0 0";
  orginalImg.style.backgroundSize=orginalImgWidth+"px "+orginalImgWidth+"px";
  var divImgs=selectPanel.getElementsByTagName("div");
  var divEmptys=mathPanel.getElementsByTagName("div");
  for(var e=0;e<divImgs.length;e++){
    divImgs[e].ondragstart=function(event){//鼠标开始拖拽拼图,并且拿到它的匹配值maths
      var event=event||window.event;
      event.dataTransfer.setData("math",this.maths);
    }
    divImgs[e].ondrag=function(){
    }
    divImgs[e].ondragend=function(){
    }
    divEmptys[e].ondragenter=function(){
      this.style.backgroundColor="red";
    }
    divEmptys[e].ondragover=function(event){//取消在拼图匹配面板的默认事件,否则ondrop无效
      return false;
    }
    divEmptys[e].ondragleave=function(){
      this.style.backgroundColor="transparent";
    }
    divEmptys[e].ondrop=function(event){//拖拽的拼图在匹配面板放下时执行函数
      var event=event||window.event;
      this.style.backgroundColor="transparent";
      if(event.dataTransfer.getData("math")==this.maths){//判断拼图传过来的maths匹配值是否和匹配面板的maths一样,如果是则匹配成功
        for(var i=0;i<divImgs.length;i++){
          if(divImgs[i].maths==this.maths){
            this.style.backgroundImage=divImgs[i].style.backgroundImage;
            this.style.backgroundRepeat=divImgs[i].style.backgroundRepeat;
            this.style.backgroundPosition=divImgs[i].style.backgroundPosition;
            divImgs[i].setAttribute("draggable","false");
            divImgs[i].style.background="none";
          }
        }
      }
    }
  }
}
//浏览器窗口发生变化时的图片处理
window.onresize=function(){
  var selectPanel=document.getElementById("selectpanel");
  var orginalImg=document.getElementById("orginalimg");
  var orginalImgWidth=document.body.clientWidth-(selectPanel.offsetWidth+selectPanel.offsetLeft+10)*2;
  orginalImg.style.width=orginalImg.style.height=orginalImgWidth+"px";
  orginalImg.style.marginLeft=-orginalImgWidth/2+"px";
  orginalImg.style.backgroundSize=orginalImgWidth+"px "+orginalImgWidth+"px";
}

javascript脚本(调用方法)

window.onload=function(){
  //图的原始宽度(原图宽),图的原始高度(原图高),自定每块拼图的宽度(能被原图宽整除),自定每块拼图的高度(能被原图高整除),图片名(需放在img下)
  Puzzle(500,500,125,125,"haqi.jpg");
}

这里直接调用Puzzle这个函数哦,要注意的是,前面两个参数一定要为图片原始的宽高,而且为了效果更好的横屏拼图展示,这个图片的宽度啊最好小于屏幕横分辨率的1/2,多出来的话用photoshop调一下图片尺寸也是可以的。还有一个最重要的是,自定义每块小拼图的宽高一定是能被原始图片宽高整除的。说白了就是,第3个参数能被第1个参数整除,第4个参数能被第2个参数整除。最后一个参数就是图片名了,而且这个图片是放在img下的。

下面就来看看初始化拼图游戏的效果,而且每次刷新页面,拼图面板的小图都是随机排列的。这个狗狗的图大小是500x500,每个小图切割宽高为125x125,所以拼图排列是500/125*500/125=16,就是四行四列吧=>4x4,当然这个参数是可以改的,每个小拼图的宽高越小,它切出来的图就越多。

JavaScript实现的拼图算法分析

为了凸显这个函数的灵活性,下面再换种参数进行调用。

window.onload=function(){
  //图的原始宽度(原图宽),图的原始高度(原图高),自定每块拼图的宽度(能被原图宽整除),自定每块拼图的高度(能被原图高整除),图片名(需放在img下)
  Puzzle(500,500,100,100,"beauty.jpg");
}

换成了一张500x500的美女图,切割宽高为100x100

JavaScript实现的拼图算法分析

试玩一波游戏先:(为了展示效果降低游戏难度)

JavaScript实现的拼图算法分析

Javascript 相关文章推荐
javascript笔试题目附答案@20081025_jb51.net
Oct 26 Javascript
Mootools 1.2教程 滚动条(Slider)
Sep 15 Javascript
JavaScript 基础篇之对象、数组使用介绍(三)
Apr 07 Javascript
让人印象深刻的10个jQuery手风琴效果应用
May 08 Javascript
jQuery实现带滚动导航效果的全屏滚动相册实例
Jun 19 Javascript
JS实现简单的右下角弹出提示窗口完整实例
Jun 21 Javascript
ES6新特性之字符串的扩展实例分析
Apr 01 Javascript
AngularJS中的拦截器实例详解
Apr 07 Javascript
深入研究React中setState源码
Nov 17 Javascript
基于vue-router 多级路由redirect 重定向的问题
Sep 03 Javascript
JavaScript数组及常见操作方法小结
Nov 13 Javascript
vue data对象重新赋值无效(未更改)的解决方式
Jul 24 Javascript
推荐15个最好用的JavaScript代码压缩工具
Feb 13 #Javascript
Vue中CSS动画原理的实现
Feb 13 #Javascript
Vue中JS动画与Velocity.js的结合使用
Feb 13 #Javascript
JavaScript中.min.js和.js文件的区别讲解
Feb 13 #Javascript
node.js微信小程序配置消息推送的实现
Feb 13 #Javascript
vue实现购物车抛物线小球动画效果的方法详解
Feb 13 #Javascript
Jquery实现无缝向上循环滚动列表的特效
Feb 13 #jQuery
You might like
linux下删除7天前日志的代码(php+shell)
2011/01/02 PHP
php页面缓存ob系列函数介绍
2012/10/18 PHP
关于zend studio 出现乱码问题的总结
2013/06/23 PHP
如何在php中正确的使用json
2013/08/06 PHP
smarty内置函数foreach用法实例
2015/01/22 PHP
PHP 文件锁与进程锁的使用示例
2017/08/07 PHP
PHP实现的服务器一致性hash分布算法示例
2018/08/09 PHP
PHP APP微信提现接口代码
2018/09/30 PHP
tp5框架基于Ajax实现列表无刷新排序功能示例
2020/02/10 PHP
几个比较实用的JavaScript 测试及效验工具
2010/04/18 Javascript
js 优化次数过多的循环 考虑到性能问题
2011/03/05 Javascript
jquery easyui combobox模糊过滤(示例代码)
2013/11/30 Javascript
js鼠标滑轮滚动事件绑定的简单实例(兼容主流浏览器)
2014/01/14 Javascript
JavaScript开发人员的10个关键习惯小结
2014/12/05 Javascript
分享我的jquery实现下拉菜单心的
2015/11/29 Javascript
jQuery拖拽排序插件制作拖拽排序效果(附源码下载)
2016/02/23 Javascript
Node.js如何自动审核团队的代码
2016/07/20 Javascript
jQuery如何跳转到另一个网页 就这么简单
2016/12/28 Javascript
Vue 2.0入门基础知识之内部指令详解
2017/10/15 Javascript
Vue手把手教你撸一个 beforeEnter 钩子函数
2018/04/24 Javascript
electron + vue项目实现打印小票功能及实现代码
2018/11/25 Javascript
JavaScript中的回调函数实例讲解
2019/01/27 Javascript
详解JavaScript 的执行机制
2020/09/18 Javascript
[01:46]2020完美世界全国高校联赛秋季赛报名开启
2020/10/15 DOTA
在Django的视图中使用form对象的方法
2015/07/18 Python
Python实现的简单读写csv文件操作示例
2018/07/12 Python
Django 实现前端图片压缩功能的方法
2019/08/07 Python
python中单下划线(_)和双下划线(__)的特殊用法
2019/08/29 Python
Python ini文件常用操作方法解析
2020/04/26 Python
Invicta手表官方商店:百年制表历史的瑞士腕表品牌
2019/09/26 全球购物
Parfumdreams芬兰:购买香水和化妆品
2021/02/13 全球购物
Monki官网:斯堪的纳维亚的独立时尚品牌
2020/11/09 全球购物
2014新年寄语
2014/01/20 职场文书
护士节慰问信
2015/02/15 职场文书
工作年限证明范本
2015/06/15 职场文书
大学生读书笔记范文
2015/07/01 职场文书