Rompecabezas hecho por javascript (lienzo html5), fácil de entender

Aprovechando el tiempo de pesca, escribí un juego de rompecabezas, que es fácil de operar y refrescante.

Imagen de efecto (el acabado final parece estar cubierto, jaja)

Ideas de realización

  1. Utilice el método de lienzo drawImage, utilice 8 parámetros para cortar la imagen grande en imágenes pequeñas y almacene cada imagen pequeña en la matriz correspondiente.
  2. Al cortar la imagen, use dos claves de matriz y orig_keys para acceder al subíndice de la imagen pequeña. Si hay 9 imágenes pequeñas (claves, ingrese la matriz de números 0-8).
  3. Cuando se hace clic en el botón de inicio, las claves se ordenan aleatoriamente, y luego se obtiene el objeto de imagen correspondiente de la pequeña matriz de imágenes y se actualiza su posición de visualización, de modo que la imagen se puede interrumpir.
  4. Elija una imagen pequeña (haga clic en esta imagen nuevamente para cancelar el estado de selección actual), y luego elija otra imagen para intercambiar posiciones.
  5. Después de cada intercambio de posiciones, se comparan las claves de matriz y orig_keys. Si las dos matrices tienen la misma estructura, significa que el rompecabezas está completo.

uso de drawImage

Puede leer este artículo

 

Escribir constructor ImageDraw

//图片对象ImageDraw构造函数
	function ImageDraw(o,obj){
		this.id='',
		this.image=0,//图片对象(必填)
		this.sx=0,//图片切片开始x位置(显示整个图片的时候不需要填)
		this.sy=0,//图片切片开始y位置(显示整个图片的时候不需要填)
		this.sWidth=0, //图片切片开始宽度(显示整个图片的时候不需要填)
		this.sHeight=0,//图片切片开始高度(显示整个图片的时候不需要填)
		this.dx=0, //图片目标x位置(必填)
		this.dy=0, //图片目标y位置(必填)
		this.dWidth=0,//图片目标显示宽度(宽度不缩放时不必填)
		this.dHeight=0//图片目标高度高度(高度不缩放时不必填)
		
		this.init(o,obj);
	}
	ImageDraw.prototype.init=function(o,obj){
		this.lol=obj;
		for(var key in o){
			this[key]=o[key];
		}
		return this;
	}
	ImageDraw.prototype.render=function(context){
		draw(context,this);
		function draw(context,obj) {
			var ctx=context;
			ctx.save();
			
			if(!obj.image || getType(obj.dx)=='undefined' || getType(obj.dy)=='undefined'){
				throw new Error("绘制图片缺失参数");	
				return;
			} 
			ctx.translate(obj.dx,obj.dy);
			if(getType(obj.sx)!='undefined' && getType(obj.sy)!='undefined' && obj.sWidth && obj.sHeight && obj.dWidth && obj.dHeight){
				//裁剪图片,显示时候有缩放
				ctx.drawImage(obj.image, obj.sx, obj.sy, obj.sWidth, obj.sHeight, 0, 0, obj.dWidth, obj.dHeight);
			}else if(obj.dWidth && obj.dHeight){
				ctx.drawImage(obj.image, 0, 0, obj.dWidth, obj.dHeight);//原始图片,显示时候有缩放
			}else{
				ctx.drawImage(obj.image,0, 0);//原始图片,显示时候无缩放
			}
			ctx.restore();
		}
	}
	ImageDraw.prototype.isPoint=function(pos){
		//鼠标位置的x、y要分别大于dx、dy 且x、y要分别小于 dx+dWidth、dy+dHeight
		if(pos.x>this.dx && pos.y>this.dy && pos.x<this.dx+this.dWidth && pos.y<this.dy+this.dHeight ){//表示处于当前图片对象范围内
			return true;
		}
		return false;
	}
	

Corta la imagen

  1. Divida la longitud de la imagen grande por el número de columnas y divida el ancho de la imagen grande por el número de filas para obtener la longitud y el ancho de la imagen pequeña respectivamente;
  2. Inicialice la imagen pequeña con un bucle doble
  3. Las claves almacenan la clave y la matriz posArr para acceder a dx y dy (se usa cuando se codifica)
//对图片进行切片
	Jigsaw.prototype.sliceImage=function(){
		var imgObj = this.imgObj;
		var img,image,key=this.imageIndex,renderArr=this.renderArr;
		var countX=this.countX,countY=this.countY;
		
		image=imgObj[key];
		
		var disX = this.w/countX,//小图片的宽
			disY = this.h/countY;//小图片的高
			
		//相关数组清空处理	
		renderArr.length=0;
		this.orig_keys.length=0;
        this.keys.length=0;
        this.posArr.length=0;
		    
		//初始化小图片对象        			
		var x=y=n=0;	
		for(var i=0;i<countX;i++){
			x = i*disX;
			for(var j=0;j<countY;j++){
				y = j*disY;
				img = new ImageDraw({image:image,sx:x,sy:y,sWidth:disX,sHeight:disY, dx:x, dy:y ,dWidth:disX,dHeight:disY},this);
				renderArr.push(img);
				
				img.key=n;//设置key值
				img.keyPos=n;//设置所处于的位置
				
				this.orig_keys.push(n);
		        this.keys.push(n);
		        this.posArr.push({x:x,y:y})
		        n++;
			}
		}
	}

Orden aleatorio

	this.keys.sort(function(a,b){//随机排序
			return Math.random()>0.5?1:-1;
		})
  1. Las claves antes codificadas son así: [0, 1, 2, 3, 4, 5, 6, 7, 8]
  2. Después de codificar, las claves se ven así: [5, 0, 7, 1, 4, 8, 6, 2, 3]
  3. Cuando el objeto de imagen pequeña está en bucle, el subíndice comienza desde 0, 1, 2, y la clave recuperada por primera vez es el primer elemento 5 de la matriz de claves.
  4. Utilice 5 para ir a posArr y obtener el sexto elemento posArr [5], y establezca dx y dy de este elemento en la imagen pequeña con el subíndice actual de 0. Los otros principios son los mismos, lo que interrumpe la imagen.
		var key,pos;   
		//排序后重新更改位置,达到打乱图片的效果     
		_.each(this.renderArr,function(item,index){
			if(item){
				key = that.keys[index];
				pos = that.posArr[key];
				//改变dx,dy既可
				item.dx=pos.x;
				item.dy=pos.y;
				item.image=that.imgObj[that.imageIndex];
				item.key=key;
				item.keyPos=index; 
			}
		});

Veamos el efecto

Agregue un evento de clic al lienzo y agregue un juicio a cada imagen pequeña. Si se hace clic en la imagen pequeña actual, se agrega un marco para indicar la selección

Constructor rect

function Rect(o){
		this.x=0,//x坐标
		this.y=0,//y坐标
		this.width=100,//宽
		this.height=40,//高
		this.thin=true,//线段薄一点
		
		this.init(o);
	}
	
	Rect.prototype.init=function(o){
		for(var key in o){
			this[key]=o[key];
		}
	}
	Rect.prototype.render=function(context){
		this.ctx=context;
		innerRender(this);
			
		function innerRender(obj){
			var ctx=obj.ctx;
			ctx.save()
			ctx.beginPath();
			ctx.translate(obj.x,obj.y);
			
			if(obj.lineWidth){
				ctx.lineWidth=obj.lineWidth;
			}
			if(obj.thin){
				ctx.translate(0.5,0.5);
			}
			ctx.rect(0,0,obj.width,obj.height);
			if(obj.fill){//是否填充
				obj.fillStyle?(ctx.fillStyle=obj.fillStyle):null;
				ctx.fill();
			}
			if(obj.stroke){//是否描边
				obj.strokeStyle?(ctx.strokeStyle=obj.strokeStyle):null;
				ctx.stroke();
			}	
		  	ctx.restore();
		}
	  	return this;
	}

Código post-clic

//表示第一次选中
						item.selected=true;
						//添加一个边框用来指示被选择
						var rect = new Rect({
								x:item.dx,
								y:item.dy,
								width:item.dWidth,
								height:item.dHeight,
								stroke:true,
								strokeStyle:'skyblue'
						})
						rect.img=item;
						this.renderRectArr.push(rect);

Efecto en este momento

Cambiar posiciones después de seleccionar otra imagen

  1. Borrar el estado de selección y el cuadro de indicación
  2. Intercambie los valores pos y clave de dos pequeños objetos de imagen
  3. Intercambia sus valores en la matriz de claves
  4. Determine si las claves y orig_keys son consistentes en este momento, si son consistentes, significa finalización
						var itemSelected = this.renderRectArr[0].img;
						//将已选择的dx、dy拷贝给x、y
						var x = itemSelected.dx,y=itemSelected.dy;
						//进行位置交换
						itemSelected.dx=item.dx,itemSelected.dy=item.dy,
						item.dx=x,item.dy=y;
						//清空选择状态及指示框
						itemSelected.selected=false;
						this.renderRectArr.length=0;
						
						//位置的交换
						var from_pos = itemSelected.keyPos;
						var from_key = itemSelected.key;
						var target_pos = item.keyPos;
						var target_key = item.key;
						
						itemSelected.pos=target_pos;
						itemSelected.key=target_key;
						item.pos=from_pos;
						item.key=from_key;
						//交换他们在this.keys中的位置
						this.keys.splice(from_pos,1,target_key);
						this.keys.splice(target_pos,1,from_key);
						
						//如果相等表示已经找好了
						if(this.diff(this.orig_keys,this.keys)){//每次交换完成以后都要进行一次判断,看是否完成拼图
							setTimeout(function(){
								alert("恭喜你已完成!");
								console.log('完成了');
							},0)
						}

Finalmente, agregue el código para el reemplazo de la imagen y el coeficiente de dificultad para completar

var box = document.getElementById('box');
	var start = document.getElementById('start');
	jigsaw.init(box,start);
	
	function up(type){
		var el = document.getElementById("difficulty_"+type);
		
		if(el){
			var val=el.value;
			if(val<10){
				val++;
				el.value=val;
				if(type='col'){
					jigsaw.countY=val;
				}else{
					jigsaw.countX=val;
				}
			}
		}
	}
		
	function down(type){
		var el = document.getElementById("difficulty_"+type);
		
		if(el){
			var val=el.value;
			if(val>3){
				val--;
				el.value=val;
				if(type='col'){
					jigsaw.countY=val;
				}else{
					jigsaw.countX=val;
				}
			}
		}
	}
	
	var index=1;
	var small_img =document.getElementsByClassName("small_img")[0]; 
	document.getElementById("next").onclick=function(){
		var src = small_img.src;
		var reg = /(\d+)\.jpeg$/;
		var arr = reg.exec(src);
		
		if(arr.length>1){
			index = ++arr[1];
			if(index>16){
				index=1;
			}
			
			jigsaw.imageIndex=index;
			jigsaw.draw();
		}
		small_img.src='./images/'+index+'.jpeg';
	}

 

Descarga todos los códigos, no se requieren puntos

Hermanos, déselo a tres empresas, ¡gracias por tirar! !

Supongo que te gusta

Origin blog.csdn.net/dkm123456/article/details/114695468
Recomendado
Clasificación