浅谈移动设备手势密码组件的canvas实现

function Gesture(width, height) {
    this.width = width; 
    this.height = height;
	this.r = width * 0.8 / 14;
}

Gesture.prototype.init = function() {
	var container = document.createElement('div');
	container.innerHTML = '<header><div class="circle"></div><div class="circle"></div><div class="circle"></div><div class="circle"></div><div class="circle"></div><div id="chinaMobile">中国移动</div><div id="time">1</div></header><nav>手势密码</nav><article><canvas id="canvas" width="' + this.width * 0.8 + '" height="' + this.width * 0.8 + '">浏览器不支持canvas元素</canvas></article><section>请输入手势密码</section><aside><input type="radio" name="password" value="setPassword" checked><span>设置密码</span><br><input type="radio" name="password" value="validatePassword"><span>验证密码</span></aside>';
	document.getElementsByTagName("body")[0].appendChild(container);
	var date = new Date();
	var hour = date.getHours();
	var minute = date.getMinutes();
	if (hour == 12 && minute == 0) 
		document.getElementById("time").innerText = "12:00 AM";	
	else if (hour < 12) 
		minute >= 10 ? document.getElementById("time").innerText = hour + ":" + minute + " AM" : document.getElementById("time").innerText = hour + ":0" + minute + " AM";
	else if (hour == 12)
		minute >= 10 ? document.getElementById("time").innerText = "12:" + minute + " PM" : document.getElementById("time").innerText = "12:0" + minute + " PM";
	else
		minute >= 10 ? document.getElementById("time").innerText = hour % 12 + ":" + minute + " PM" : document.getElementById("time").innerText = hour % 12 + ":0" + minute + " PM";
	this.canvas = document.getElementById('canvas');
    this.context = this.canvas.getContext('2d');
	this.state = 0;
	this.radio = 0;
	this.selectPoints = [];
	this.ninePoints = [];
	this.marginX = this.canvas.offsetLeft;
	this.marginY = this.canvas.offsetTop;
	this.caculateLocation();
	for (var i = 0; i < this.ninePoints.length; i++) {
		this.strokeCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#cccccc", 10);
		this.fillCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#ffffff");
	}
	this.eventHandler();
}

Gesture.prototype.caculateLocation = function() {
	for (var i = 0; i < 3; i++) {
		for (var j = 0; j < 3; j++) {
			var point = {
				x: 4 * this.r * j + 3 * this.r,
				y: 4 * this.r * i + 3 * this.r
			};
			this.ninePoints.push(point);
		}
	}
};

Gesture.prototype.strokeCircle = function(x, y, r, color, lineWidth) {
	this.context.lineWidth = lineWidth;
	this.context.strokeStyle = color;
	this.context.beginPath();
	this.context.arc(x, y, r, 0, Math.PI * 2, true);
	this.context.stroke();
	this.context.closePath();
}

Gesture.prototype.fillCircle = function(x, y, r, color) {
	this.context.fillStyle = color;
	this.context.beginPath();
	this.context.arc(x, y, r, 0, Math.PI * 2, true);
	this.context.fill();
	this.context.closePath();
}

Gesture.prototype.drawLine = function(touchPoint, color, lineWidth) {
	this.context.beginPath();
    this.context.strokeStyle = color;
    this.context.lineWidth = lineWidth;
    this.context.moveTo(this.ninePoints[this.selectPoints[0]].x, this.ninePoints[this.selectPoints[0]].y);
    for (var i = 1; i < this.selectPoints.length; i++) 
        this.context.lineTo(this.ninePoints[this.selectPoints[i]].x, this.ninePoints[this.selectPoints[i]].y);
	this.context.lineTo(touchPoint.x, touchPoint.y);
    this.context.stroke();
    this.context.closePath();
}

Gesture.prototype.draw = function(touchPoint) {
	this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
	for (var i = 0; i < this.ninePoints.length; i++) {
		if (this.selectPoints.indexOf(i) == -1) { 
			this.strokeCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#cccccc", 10);
			this.fillCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#ffffff");
		}
		else {
			this.strokeCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#ff5511", 10);
			this.fillCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#ff8800");
		}
	}
	this.drawLine(touchPoint, "red", 8); 
};

Gesture.prototype.selectPoint = function(touchPoint) {
	var touchX = touchPoint.pageX - this.marginX;
	var touchY = touchPoint.pageY - this.marginY;
	for (var i = 0; i < this.ninePoints.length; i++) {
		if (this.selectPoints.indexOf(i) == -1) { 
			var point = this.ninePoints[i];
			var diffX = Math.abs(point.x - touchX);
			var diffY = Math.abs(point.y - touchY);
			var distance = Math.sqrt(diffX * diffX + diffY * diffY);
			if (distance < this.r) {
				this.selectPoints.push(i);
				this.strokeCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#ff5511", 10);
				this.fillCircle(this.ninePoints[i].x, this.ninePoints[i].y, this.r, "#ff8800");
				break;				
			}
		}
	}
};

Gesture.prototype.eventHandler = function() {
	var that = this;
	this.canvas.addEventListener("touchstart", function(event) {
		that.selectPoint(event.touches[0]);
	}, false);
	this.canvas.addEventListener("touchmove", function(event) {
		event.preventDefault();
		that.selectPoint(event.touches[0]);
		that.draw({x: event.touches[0].pageX - that.marginX, y: event.touches[0].pageY - that.marginY});
	}, false);
	this.canvas.addEventListener("touchend", function() {
		that.storage();
		that.selectPoints = [];
		setTimeout(function() {
			that.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
			for (var i = 0; i < that.ninePoints.length; i++) {
				that.strokeCircle(that.ninePoints[i].x, that.ninePoints[i].y, that.r, "#cccccc", 10);
				that.fillCircle(that.ninePoints[i].x, that.ninePoints[i].y, that.r, "#ffffff");
			}
		}, 500);
	}, false);
	var radios = document.getElementsByName("password");
	for (var i = 0; i < radios.length; i++) {
		radios[i].addEventListener("change", function() {
			if (this.value == "setPassword") { 
				that.radio = 0; 
				that.state = 0;
			}
			else { 
				if (JSON.parse(window.localStorage.getItem('password')) != null) { 
					that.radio = 1;
					that.state = 2;
				}
				else { 
					alert("请先设置密码");
					radios[0].checked = "checked";
					that.state = 0;
				}
			}
			document.getElementsByTagName('section')[0].innerHTML = '请输入手势密码';
		}, false);
	}
};

Gesture.prototype.storage = function() {
	var section = document.getElementsByTagName('section')[0];
	var radios = document.getElementsByName("password");
	switch(this.state) {
		case 0: 
			if (this.radio == 0 && this.selectPoints.length < 5) 
				section.innerHTML = '密码太短,至少需要5个点';
			else {
				section.innerHTML = '请再次输入手势密码';
				this.password = this.selectPoints.slice(0);
				this.state = 1;
			}
			break;
		case 1:
			if (!this.check(this.password, this.selectPoints)) {
				section.innerHTML = '两次输入的不一致';
				delete this.password;
				this.state = 0;
			}
			else {
				section.innerHTML = '密码设置成功';
				window.localStorage.setItem('password', JSON.stringify(this.password));
				radios[1].checked = "checked";
				this.state = 2;
			}
			break;
		case 2: 
			if (!this.check(JSON.parse(window.localStorage.getItem('password')), this.selectPoints)) 
				section.innerHTML = '输入的密码不正确';
			else 
				section.innerHTML = '密码正确!';
			break;
	}
}

Gesture.prototype.check = function(prePassword, curPassword) {
	var preLen = prePassword.length;
	var curLen =curPassword.length;
	if (preLen != curLen) 
		return false;
	for (var i = 0; i < preLen; i++) {
		if (prePassword[i] != curPassword[i])
			return false;
	}
	return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值