HTML5 进阶(8)—Canvas案例:使用canvas仿手机画图解锁

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39141044/article/details/83213990

以下这种效果。
在这里插入图片描述


使用到的技术

  • canvas基本操作

  • canvas的离屏

  • js的dom2级事件注册处理函数
    addEventListenter(eventType,listener,useCapture)
    eventType:事件类型(click、focus、blur)不带on
    listener:事件处理函数,可以是匿名函数
    useCapture:默认值是false,只冒泡不捕获;true只捕获不冒泡(捕获很少用)。

  • 移动端的触摸事件:touchstart、touchmove、touchend



HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
	<title>图案解锁</title>
</head>
<body>
	<script type="text/javascript" src="./js/index.js"></script>
	<script type="text/javascript">
		new lock().init();
	</script>
</body>
</html>

JS代码

(function(){
	/*	图案解锁
		poorpenguin - v1.0.0
	*/
	window.lock = function(object){
		var obj = object || {};
		this.width = obj.width || 300;				//设置canvas的width
		this.height = obj.height || 300;			//设置canvas的height
		this.chooseType = obj.chooseType || 3;		//设置图案一排和一列的个数
	}

	//初始化
	lock.prototype.init = function(){
		this.createDom();
		this.createCanvas();
		this.createOffBg();	//绘制离屏
		this.createBg();	//生成主屏背景
		this.bindEvent();
	}

	//创建dom结构以及设置样式
	lock.prototype.createDom = function(){
		//标题
		var h4 = '<h4 id="title" style="color:#66ccff;">请解锁</h4>';
		//两个画布,canvas为主画布,offScreen为离屏
		var canvas = document.createElement('canvas');
		var offScreen = document.createElement('canvas');
		canvas.setAttribute('id','canvas');
		canvas.setAttribute('width',this.width);
		canvas.setAttribute('height',this.height);
		offScreen.setAttribute('id','offScreen');
		offScreen.setAttribute('width',this.width);
		offScreen.setAttribute('height',this.height);
		canvas.setAttribute('style','display:inline-block;');
		offScreen.setAttribute('style','display:none;');
		//div包裹canvas和title
		var wrap = document.createElement('div');
		wrap.setAttribute('style','text-align:center;');
		wrap.innerHTML = h4;
		wrap.appendChild(canvas);
		wrap.appendChild(offScreen);
		//设置body
		document.body.setAttribute('style','background-color:#305066;');
		document.body.appendChild(wrap);
	}

	//创建画布
	lock.prototype.createCanvas = function(){
		this.canvas = document.getElementById('canvas');
		this.ctx = this.canvas.getContext('2d');
		this.offScreen = document.getElementById('offScreen');
		this.offSctx = this.offScreen.getContext('2d');
	}

/*绑定事件*/
	//canvas绑定触摸事件:touchstart、touchmove、touchend
	lock.prototype.bindEvent = function(){
		var self = this;	//在给canvas绑定触摸事件的回调函数中 this代表的是canvas这个元素,而不是lock这个类
		this.touchFlag = false;
		//设置dom2级事件
		this.canvas.addEventListener('touchstart',function(e){
			self.getMousePo(e);
			self.mouseInCricle(self.restPoint);
		},false);
		this.canvas.addEventListener('touchmove',function(e){
			if(self.touchFlag){
				self.getMousePo(e);
				self.mouseInCricle(self.restPoint);
				self.update(self.lastPoint,'#CFE6FF');
			}
		},false);
		this.canvas.addEventListener('touchend',function(e){
			if(self.touchFlag){
				if(self.checkPass()){
					document.getElementById('title').innerHTML = '解锁成功';
					self.drawArc(self.lastPoint,'#7CFC00');
				}else{
					document.getElementById('title').innerHTML = '解锁失败';
					self.drawArc(self.lastPoint,'red');
				}
			}
			setTimeout(function(){
				self.reset();
			},500);
		},false);
	}


/*获取定位*/
	//获取鼠标在画布上的定位
	lock.prototype.getMousePo = function(e){
		var canvasPo = this.canvas.getBoundingClientRect();	//获取画布的位置
		this.mouseInCanvas = {	//触摸点在画布上的定位
			x: e.touches[0].clientX - canvasPo.left,
			y: e.touches[0].clientY - canvasPo.top
		}
	}
	//判读鼠标点击是否在圆内
	lock.prototype.mouseInCricle = function(arr){
		
		for(var i=0; i<arr.length; i++){
			if(Math.abs(arr[i].x-this.mouseInCanvas.x) < this.r && Math.abs(arr[i].y-this.mouseInCanvas.y) < this.r ){
				this.lastPoint.push(arr[i]);
				this.restPoint.splice(i,1);
				this.touchFlag = true;
				break;
			}
		}
	}


/*绘制*/
	//绘制离屏背景
	lock.prototype.createOffBg = function(){
		var n = this.chooseType;
		this.r = this.canvas.width/(4*n+2);
		var r = this.r;
		var count = 0;
		this.arr = [];			//所有的圆
		this.lastPoint = [];	//已经经过的圆
		this.restPoint = [];	//未经过剩余的圆

		for(var i=0 ; i < n; i++){	//行
			for(var j=0; j < n; j++){	//列
				var obj = {
					x: j*4*r + 3*r,
					y: i*4*r + 3*r,
					index: ++count
				};
				this.arr.push(obj);
				this.restPoint.push(obj);
			}
		}

		//在离屏画出圆阵列
		this.offSctx.clearRect(0,0,this.offScreen.width,this.offScreen.height);
		this.offSctx.strokeStyle = '#CFE6FF';
		for(var i=0; i < this.arr.length; i++){
			this.offSctx.beginPath();
			this.offSctx.arc( this.arr[i].x, this.arr[i].y, this.r, 0, Math.PI*2);
			this.offSctx.stroke();
			//this.offSctx.fillText(this.arr[i].index, this.arr[i].x, this.arr[i].y);
		}
	}
	//生成主屏背景
	lock.prototype.createBg = function(){
		this.ctx.drawImage( this.offScreen, 0, 0, this.offScreen.width, this.offScreen.height, 0, 0, this.canvas.width, this.canvas.height);
	}
	//更新画布
	lock.prototype.update = function(arr,color){
		this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);	//清空整个画布保证不会出现多余的线条
		this.createBg();	//重绘制背景
		this.drawPoint(arr,color);
		this.drawLine(arr,color);
	}
	//画点
	lock.prototype.drawPoint = function(arr,color){
		this.ctx.fillStyle = color;
		for(var i=0; i<arr.length; i++){
			this.ctx.beginPath();
			this.ctx.arc( arr[i].x, arr[i].y, this.r/2, 0, Math.PI*2);
			this.ctx.fill();
		}

	}
	//画线
	lock.prototype.drawLine = function(arr,color){
		this.ctx.beginPath();
		this.ctx.strokeStyle = '#CFE6FF';
		this.ctx.lineWidth = 3;
		this.ctx.moveTo(arr[0].x, arr[0].y);
		for(var i=1; i<arr.length; i++){
			this.ctx.lineTo(arr[i].x, arr[i].y);
		}
		this.ctx.lineTo(this.mouseInCanvas.x, this.mouseInCanvas.y);
		this.ctx.stroke();
	}
	//画圆弧
	lock.prototype.drawArc = function(arr,color){
		this.ctx.strokeStyle = color;
		for(var i=0; i<arr.length; i++){
			this.ctx.beginPath();
			this.ctx.arc( arr[i].x, arr[i].y, this.r, 0, Math.PI*2);
			this.ctx.stroke();
		}

	}
	//重置
	lock.prototype.reset = function(){
		this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);	//清空整个画布保证不会出现多余的线条
		this.createBg();	//重绘制背景
		document.getElementById('title').innerHTML = '请解锁';
		this.lastPoint = [];
		this.restPoint = this.arr.slice(0);
		this.touchFlag = false;
	}


/*判断密码*/
	lock.prototype.checkPass = function(){
		var password = '1234';
		var p2 = '';
		for(var i=0; i<this.lastPoint.length; i++){
			p2 += this.lastPoint[i].index;
		}
		return p2 === password;
	}

})();

猜你喜欢

转载自blog.csdn.net/weixin_39141044/article/details/83213990