一开始写的拼图是用div一个一个列出来的,里面放的是切好的图片。拼图小游戏(前端)
canvas.drawImage()使用可以参照drawImage()方法
这里生成拼图对象传入了两个数组。
一个是canvas的九格位置数组(不可改动)canvas九格的每一格都可以放图片的任意一个图片碎片或者“白块”,以此实现“拼图”的效果;
一个是图片的九格位置数组(可打乱);
样式没有过多调整,能用就成
<!-- 流程1,选择想拼的图片 -->
流程1,选择想拼的图片
<div class="process1">
<div>选择图片</div>
<input class="file" type="file" id="ipt">
</div>
<!-- 流程2:切图 -->
流程2:切图
<div class="process2">
<div class="img">
<div class="mask">
</div>
</div>
<button>确定</button>
</div>
<div class="process3">
<canvas id ="canvas" width="500" height="500"></canvas>
</div>
<style>
.process1{
width: 150px;
height: 80px;
position: relative;
background: #000;
color: #fff;
text-align: center;
line-height: 80px;
}
.file{
/* visibility: hidden; */
opacity: 0;
width: 150px;
height: 80px;
position: absolute;
left: 0;
top: 0;
}
.img{
margin: 0 auto;
position: relative;
overflow: hidden;
width: 800px;
}
.mask{
position: absolute;
width: 30%;
background-color:rgba(0, 0, 0, 0);
box-shadow: 0 0 0 10000px rgba(0,0,0,.5);
left: 30%;
top: 30%;
}
canvas{
border: 1px solid #000;
}
</style>
var ipt = document.getElementById('ipt')
var canvas = document.getElementById('canvas')
var contDv = document.getElementsByClassName('img')[0];
var c_msg
var sqrt = document.getElementsByClassName('mask')[0];
sqrt.style.height = sqrt.offsetWidth + 'px'
var ctx = canvas.getContext('2d');
var image = new Image();
var sx=0,sy=0;
var step = 500/3
var imagestep;
var rate ;
//选择一张图片,生成img对象,流程一
ipt.onchange = function(e){
var windowurl = window.URL || window.webkitURL;
var url = windowurl.createObjectURL(e.target.files[0]);
// img.src = url
contDv.style.background = `url(${url}) no-repeat center center/100% 100%`;
image.src = url;
image.onload = function(){
var ix = this.width;
var iy = this.height;
contDv.style.height = contDv.offsetWidth *iy/ix + 'px'
rate = iy/contDv.offsetHeight;
c_msg = contDv.getClientRects()[0];
}
}
// 确定裁剪区域,流程二,思路可以参照放大镜的思路,这部分有问题,但是因为目的不是它就没管
var bdy = document.documentElement
sqrt.onmousedown = function(e){
var msg = this.getClientRects()[0];
// 计算鼠标与白块的距离
var space_x = e.pageX - msg.left;
var space_y = e.pageY - msg.top;
var _this = this;
var max_x = c_msg.width-this.offsetWidth;
var max_y = c_msg.height-this.offsetHeight;
var scrolltop = bdy.scrollTop;
var scrollleft = bdy.scrollLeft;
document.onmousemove = function(eve){
sx = eve.pageX+ scrollleft - space_x - c_msg.left;
sy = eve.pageY + scrolltop- space_y - c_msg.top;
sx = sx>max_x?max_x:sx
sy = sy>max_y?max_y:sy
_this.style.left = sx<0?0:sx + 'px';
_this.style.top = sy<0?0:sy + 'px';
}
}
sqrt.onmouseup = function(){
document.onmousemove = ''
}
// 开始裁剪
var btn = document.getElementsByTagName('button')[0];
var jigsaw
btn.onclick = function(){
imagestep = sqrt.offsetWidth*rate/3;//获得每块拼图的宽高
var pointlist = [];
var canvaslist =[]
var pointy=sy*rate,
cy=0,
pointx,
cx;
for(var i = 0 ; i <3 ;i ++){
if(i!==0){pointy+=imagestep;cy+=step}
pointx=sx*rate,cx=0
for(var j = 0 ;j<3;j++){
if(j!==0){pointx+=imagestep;cx+=step}
console.log(pointx,pointy)
pointlist.push({x:pointx,y:pointy,id:i*3+j})//id当做判断游戏结束的依据
canvaslist.push({x:j,y:i})
}
}
console.log(canvaslist,pointlist)
jigsaw = new Jigsaw('canvas',pointlist,canvaslist,9,image,imagestep);
jigsaw.init()
}
function random (n){
return Math.ceil(Math.random()*n)
}
//这里传入两个数组,一是游戏的九各位置,一个是图片碎片的位置
function Jigsaw(dom,imgdata,canvasdata,size,image,imagestep){
this.$data = imgdata;//原始数据
this.$canvaslist = canvasdata;//canvas九宫数据
this.$size =size;//九宫格或者十六宫格
this.$jigsaw_data = null //处理后的拼图数组
this.$dom = document.getElementById(dom)//承载游戏的元素
this.$ctx = this.$dom.getContext('2d');//画布
this.$finish = false;//游戏结束标志
this.$change;//白块所在元素的索引值
this.$image = image;//图片
this.$step = 0;//移动步数
this.$imagestep = imagestep
}
Jigsaw.prototype.init = function(){
if(!this.$dom){
console.log('要承载的对象不存在')
return
}
if(this.data_handle()){//处理传入的数组
console.log('错误的数据格式')
return
}
this.game()
this.interactive()
}
Jigsaw.prototype.data_handle = function(){
if(this.$data.length!=this.$size){
return true //传入的数据长度不对
}
var newarr=[];
var arr = this.$data;
var last = arr.pop()
for( var i =7 ; i>=0;i--){
var tmp = arr.splice(random(i),1)
newarr = newarr.concat(tmp)
}//将传入的原始数据打乱
newarr.push(last);//把空白拼图放在数组最后一位
this.$change = newarr.length -1;//记录空白拼图的位置
newarr[this.$change].white = true
this.$jigsaw_data = newarr
}
Jigsaw.prototype.createLine = function(){
this.$ctx.clearRect(0,0,this.$dom.offsetWidth,this.$dom.offsetHeight)//将画布清空
this.$jigsaw_data.forEach((item,y)=>{
var p = this.$canvaslist[y]
if(!item.white){
this.$ctx.drawImage(this.$image,item.x,item.y,this.$imagestep,this.$imagestep,p.x*step,p.y*step,step,step)//如果当前对象不是空白拼图
}
this.$ctx.rect(p.canvasx,p.canvasy,step,step);
this.$ctx.stroke()
})
}
Jigsaw.prototype.exchange = function(obj){
var _this = this;
var x = Math.floor(obj.x/step);
var y = Math.floor(obj.y/step);//计算鼠标落在哪块拼图上
var index = y*3+x//计算出被点的区域对应索引值
console.log(obj,index)
var $x = this.$canvaslist[index].x - this.$canvaslist[this.$change].x;
var $y = this.$canvaslist[index].y - this.$canvaslist[this.$change].y;
if(Math.abs($x+$y)==1){//计算鼠标所落的拼图是否与白色拼图相邻,是则交换
var tmp = _this.$jigsaw_data[index];
_this.$jigsaw_data[index] = _this.$jigsaw_data[this.$change];
_this.$jigsaw_data[this.$change]=tmp;
this.$change = index
_this.game()
_this.$step ++
}
}
Jigsaw.prototype.resetwhite=function(){
this.$change = ''
}
Jigsaw.prototype.interactive = function(){
var _this = this
this.$dom.onclick = function(e){
var x = e.pageX - this.offsetLeft
var y = e.pageY - this.offsetTop
if(_this.$finish){
console.log('游戏结束,你一共走了' + _this.$step + '步')
return
}else{
_this.exchange({x:x,y:y})
}
}
}
Jigsaw.prototype.game = function(){
this.createLine();
this.endjudge();
if(this.$finish){
console.log('游戏结束,你一共走了' + this.$step + '步')
}
}
Jigsaw.prototype.endjudge=function(){
for(var i = 0 ; i <this.$jigsaw_data.length ;i ++){
var obj = this.$jigsaw_data[i]
if(obj&&obj.id !==i){
this.$finish = false;
break;
}else{
this.$finish = true;
}
}
}