JavaScript HTML5拖拽拼图游戏实现与封装

作者:半夏时间:2026-10-22 21:01:05浏览:230

本文详解利用HTML5拖拽事件实现JavaScript拼图游戏的完整流程。通过封装Puzzle函数,支持自定义图片尺寸、切割块数及排列方式。文章提供从HTML结构、CSS样式到核心JS逻辑的代码示例,并演示如何调用插件生成不同规格的随机排列拼图,适合前端初学者参考实践。

JavaScript HTML5拖拽拼图游戏实现与封装

本文通过具体实例解析基于JavaScript开发的拼图算法逻辑,旨在为相关开发者提供可参考的实现方案。

掌握HTML5的拖拽事件后,开发简易拼图游戏并非难事。本文将介绍如何利用drag事件构建拼图游戏。需注意,HTML5的新特性在IE浏览器中存在兼容性问题。为此,本文将该拼图游戏封装为一个独立插件,用户可直接复制使用,调用方式简便。

HTML与CSS基础结构

HTML结构方面,仅需创建三个div元素,无需填充具体内容,分别用于承载拼图操作区、参考图像展示区以及拼图面板区域。


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

CSS样式部分基本无需复杂编写,建议将margin和padding重置为0以消除默认间距,这有助于布局的准确性。


*{margin: 0;padding: 0;}

核心JavaScript脚本封装

核心逻辑在于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";
}

插件调用方法与参数说明

脚本的调用方法相对简单,具体示例见下方代码块。


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

直接调用Puzzle函数即可运行。需注意,前两个参数必须指定图片的原始宽高。为了获得更好的横屏展示效果,建议图片宽度不超过屏幕横向分辨率的一半,若超出可通过Photoshop调整图片尺寸。最关键的是,自定义的每块小拼图宽高必须能整除原始图片的宽高,即第3个参数需能被第1个参数整除,第4个参数需能被第2个参数整除。最后一个参数为图片文件名,且该图片需放置在img目录下。

游戏效果与参数配置示例

初始化拼图游戏后,每次刷新页面,拼图面板中的小图都会随机排列。以一张500x500像素的狗狗图片为例,若切割宽高设为125x125,则计算方式为500/125 * 500/125 = 16,即形成4x4的四行四列布局。此参数可灵活调整,小拼图宽高越小,切割出的图片数量越多。

JavaScript HTML5拖拽拼图游戏实现与封装

为展示函数的灵活性,下面演示另一种参数配置下的调用方式。


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

此处更换为一张500x500像素的美女图片,并将切割宽高调整为100x100。

实际试玩效果如下(为展示清晰,已适当降低游戏难度)。

此外,推荐一款类似的在线工具供参考。

希望本文所述内容能对JavaScript程序设计有所帮助。

作者最新文章