将原本在服务器端生成的验证码图形移动到浏览器端
demo地址:http://www.free361.com/demo.php?id=5
captcha.js
function canvasApp(_msg_str,callback_fun){
function canvasSupport(){
return Modernizr.canvas; //检查是否支持canvas
}
function checkMobile(){
return Modernizr.touchevents; //检查是否手机浏览器
}
if(!canvasSupport()){
return;
}
var msg_str = _msg_str; //"所对角的正弦之比相等",用于验证的文字
var msg_arr = msg_str.split("");
var cas_box_obj = document.getElementById("cas_box");
var canvas_offset_x = cas_box_obj.offsetLeft; //画布偏移量50
var canvas_offset_y = cas_box_obj.offsetTop;
var font_size = 18;
var background_color_range = 50; //杂色概率,1/50
var save_distance = Math.ceil(font_size*2*Math.sqrt(2))-font_size/2; //安全距离:两个字体左下角坐标点的距离>2*根号2*fontsize
var is_mobile = checkMobile(); //判断是否手机
var result_code = ""; //最终结果
var positions = []; //位置缓存
var canvas_obj = document.getElementById("cas");
var context = canvas_obj.getContext("2d"); //2d上下文对象
console.log(canvas_offset_x,canvas_offset_y);
canvas_obj.addEventListener("click",checkWord,false);
function checkWord(e){
if(is_mobile){
//手机触屏
if (e.targetTouches.length == 1) {
event.preventDefault();// 阻止浏览器默认事件,重要
var touch = e.targetTouches[0];
//目标坐标
var mx = touch.pageX-canvas_offset_x;
var my = touch.pageY-canvas_offset_y;
}else{
alert("不支持多点触摸");
return;
}
}else{
var mx = e.x-canvas_offset_x;
var my = e.y-canvas_offset_y;
}
console.log(e.x,e.y,mx,my);
for(var i=0;i<msg_arr.length;i++){
//context,"arc","150,250,120,0,"+2*Math.PI
var x = positions[i*3];
var y = positions[i*3+1];
var arg_org = positions[i*3+2];
var angle = positions[i*3+2]*Math.PI/180;
var f_x = Math.ceil(Math.cos(angle)*font_size);
var f_y = Math.ceil(Math.sin(angle)*font_size);
var m = 0;
var n = 0;
var point = [x+m,y+n,x+f_x+m,y+f_y+n,x+f_y+f_x+m,y+f_y-f_x+n,x+f_y+m,y-f_x+n];
var event1=new addEvent(context,"egg",point,mx,my,i,function(n) {
//因为beginPath清掉了前面路径的所有绑定,所以这里重新绑定区域的路径
result_code += n;
// alert(this.code);
// console.log(result_code);
saveCode(result_code);
var arr = point;
context.beginPath();
context.strokeStyle = "rgba(255,0,0,1)";
context.lineWidth = 2;
var arr=this.data;
context.moveTo(arr[0],arr[1]);
context.lineTo(arr[2],arr[3]);
context.lineTo(arr[4],arr[5]);
context.lineTo(arr[6],arr[7]);
context.lineTo(arr[0],arr[1]);
context.stroke();
context.closePath();
});
event1.add(mx,my);
}
}
function saveCode(code){
callback_fun(code);
}
function addEvent (cobj,type,data,mx,my,id,callback) {
this.cobj=cobj; //给addEvent增加属性和方法
this.type=type;
this.data=data;
this.callback=callback;
this.x = mx;
this.y = my;
this.id= id;
this.redraw();
}
addEvent.prototype={ //给addEvent原型增加方法
redraw:function () { //重绘
if(this.type=="egg"){
this.cobj.beginPath();
this.cobj.strokeStyle = "rgba(255,0,0,0)";
this.cobj.lineWidth = 2;
var arr=this.data;
context.moveTo(arr[0],arr[1]);
context.lineTo(arr[2],arr[3]);
context.lineTo(arr[4],arr[5]);
context.lineTo(arr[6],arr[7]);
context.lineTo(arr[0],arr[1]);
this.cobj.stroke();
}
},
add:function (mx,my) {
if(this.cobj.isPointInPath(mx,my)){
this.callback(this.id);
}
}
}
function drawScreen(){
function getRandColor(){
//随机颜色
var r = Math.ceil(Math.random()*255);
var g = Math.ceil(Math.random()*255);
var b = Math.ceil(Math.random()*255);
while(r>100 && g>100 && b>100){
//不允许有白色
// r = Math.ceil(Math.random()*255);
// g = Math.ceil(Math.random()*255);
// b = Math.ceil(Math.random()*255);
// console.log(r,g,b);
r = 0;
g = 0;
b = 0;
}
//透明度要在75%以上
var a = Math.ceil(Math.random()*40)/10;
if(a>1 || a<0.75){
a = 1;
}
var rgb = "rgba("+r+","+g+","+b+","+a+")";
return rgb;
}
//边界检测
function checkBorder(x,y){
//边框检查
if(x > canvas_obj.width-2*font_size){
return true;
}
if(y > canvas_obj.height-2*font_size){
return true;
}
if(x < 2*font_size){
return true;
}
if(y < 2*font_size){
return true;
}
//字字直接检查
if(positions.length>0){
for(var i=0;i<positions.length;i+=3){
// Debugger.log(positions[i],Math.abs(x-positions[i]),save_distance);
if(Math.abs(x-positions[i])<save_distance && Math.abs(y-positions[i+1])<save_distance){
// console.log(1);
return true;
}
}
}
}
function getRandPosition(){
var x = Math.ceil(Math.random()*canvas_obj.width);
var y = Math.ceil(Math.random()*canvas_obj.height);
while(checkBorder(x,y)){
x = Math.ceil(Math.random()*canvas_obj.width);
y = Math.ceil(Math.random()*canvas_obj.height);
}
var _poi = [];
_poi.push(x);
_poi.push(y);
return _poi;
}
function getRandAngle(){
return Math.ceil(Math.random()*360);
}
function getRandStyle(){
var font_style = ["normal","italic","oblique"];
var i = Math.ceil(Math.random()*3);
return font_style[i-1];
}
function getRandFace(){
var font_face = ["微软雅黑","仿宋","宋体","楷体","黑体"];
var i = Math.ceil(Math.random()*5);
return font_face[i-1];
}
function createBackground(ctx){
var image_obj = ctx.getImageData(canvas_obj.width,canvas_obj.height,canvas_obj.width,canvas_obj.height);
// Debugger.log(image_obj);
for (var y = 0; y < image_obj.height; y++) {
for (var x = 0;x < image_obj.width; x++) {
var r = Math.ceil(Math.random()* background_color_range);
if(r == 1){
var index = y * image_obj.width + x; //index 为当前要处理的像素编号
var p = index * 4;
image_obj.data[p] = Math.ceil(Math.random()*255);
image_obj.data[p+1] = Math.ceil(Math.random()*255);
image_obj.data[p+2] = Math.ceil(Math.random()*255);
image_obj.data[p+3] = Math.ceil(Math.random()*255);
}
}
}
// console.log(image_obj);
ctx.putImageData(image_obj,0,0);
}
//背景色
createBackground(context);
//边框
context.strokeStyle = "#000000";
context.strokeRect(1,1,canvas_obj.width-2,canvas_obj.height-2);
for(var i=0;i<msg_arr.length;i++){
//随机颜色
var rgb = getRandColor();
//随机位置
var temp = getRandPosition();
var x = temp[0];
var y = temp[1];
//随机角度
var angle = getRandAngle();
var radian = angle*Math.PI/180; //弧度
//随机样式
var font_style = getRandStyle();
var font_face = getRandFace();
//记录各文字位置
positions.push(x);
positions.push(y);
positions.push(angle);
context.fillStyle = rgb;
context.font = font_style+" "+font_size+"px "+font_face;
context.save();
context.setTransform(1,0,0,1,0,0);
context.translate(x,y);
context.rotate(radian);
context.fillText(msg_arr[i],0,0);
context.restore();
}
}
drawScreen();
}
//调用
window.addEventListener("load",eventWindowLoaded,false);
function eventWindowLoaded(){
event_can = new canvasApp("所对角的正弦之比相等",function(code){
console.log(code);
});
}