拼图 canvas分割 dom拖拽 pc 移动端
参考的案例,不支持手机端。总结下实现过程中遇到的小坑。
gitHub: https://github.com/WppFrontEnd/puzzle
大概步奏分为三部分:
1. cavas 分割图片
2. 图片乱序
3. 排序图片
其中1和2都是参考了Canvas drag 实现拖拽拼图小游戏。
代码主要如下:
1. cavas 分割图片
segmentImg: function(puzzleImg){ var index =0; divisionNum =3; var imgHeight = puzzleImg.height; var imgWidth = puzzleImg.width; var sigelH = imgHeight/divisionNum; var sigelW = imgWidth/divisionNum; this.canvas.height = sigelH; this.canvas.width = sigelW; for(var i=0;i<divisionNum;i++){ for(var j=0;j<divisionNum;j++){ posX = sigelW * j+(5*j); posY = sigelH * i+(5*i); this.context.drawImage(puzzleImg, sigelW * j, sigelH * i, sigelW, sigelH, 0, 0, sigelW, sigelH); this.imgCanvasList[index].src= this.canvas.toDataURL('image/jpeg'); this.imgCanvasList[index].id=index; index++; } } }
在分割图片的时候,遇到了一个坑: 生成的图片的大小总是300*150,而我需要的图片只是在300*150的右上角,而不是一张完整我切割的图片,大概如下:
虽然我知道设置canvas的大小是要写在标签上的,然后我没有想到写在style里面,html上显示的canvas是有效果的,可是生成图片的时候却依然是默认的大小。
之前是这样写的
this.canvas.style.height = sigelH;
this.canvas.style.width = sigelW;
改成这样
this.canvas.height = sigelH;
this.canvas.width = sigelW;
2. 图片乱序
sortImg: function(){ this.imgCanvasList.sort(function(){ return Math.random() - Math.random(); }); }
这是第二个坑:
正常的逻辑即是,先分割图片,在乱序
self.segmentImg(puzzleImg);
self.sortImg();
然而这样写并没有达到乱序的效果。
整理下逻辑:
这样就通了,但是我也发现我这样写的一个不好之处: self.sortImg();不能单独拿出来用,如果想排两次序就得执行两次排序赋值。所以还需要改进~
3. 排序图片
dragEvent: function(){ var contain = document.getElementById('game'); //bind dragStart function var imgList = contain.querySelectorAll('img'); var that = this; var listLen = that.imgDomList.length; var originImgIndex; var dragImgIndex; for(var i=0, len = that.imgDomList.length; i < len; i++ ){ var draggie = new Draggabilly(that.imgDomList[i]); draggie.on( 'dragStart', function( event, pointer) { dragImg = event.srcElement; }); draggie.on( 'dragEnd', function( event, pointer) { console.log(pointer); var clickX = pointer.pageX; var clickY = pointer.pageY; console.log(clickX+ ' '+clickY); var index =0; for(var i=0;i<listLen;i++){ var posX1 = that.imgDomList[i].offsetTop; var posX2 = posX1+that.imgDomList[i].height; var posY1 = that.imgDomList[i].offsetLeft; var posY2 = posY1+that.imgDomList[i].width; if(clickX>=posY1&&clickX<=posY2&&clickY>=posX1&&clickY<=posX2){ index++; if(index==1){ originImgIndex = i; }else if(index==2){ dragImgIndex = i; index=0; } } } var originImgId = that.imgDomList[originImgIndex].id; var originObj = document.getElementById(originImgId); var cache = { 'src': originObj.src, 'id': originObj.id }; if(!dragImgIndex){ originObj.style.left=0; originObj.style.top=0; originImgIndex=""; dragImgIndex=""; }else{ var endObjId = that.imgDomList[dragImgIndex].id; var endObj = document.getElementById(endObjId); originObj.src=endObj.src; originObj.id=endObj.id; endObj.src = cache.src; endObj.id = cache.id; originObj.style.left=0; originObj.style.top=0; endObj.style.left=0; endObj.style.top=0; originImgIndex=""; dragImgIndex=""; } that.isSuccess(); }) } }
排序的过程中,主要遇到两个问题:
(1) offsetTop,height,offsetLef,width 取到的值都是四舍五入的整数
解决办法: 用style.top,style.left 但是结果都带px
(2) 值引用,引用类型
例如:
好好研究一下。