Skip to content

Instantly share code, notes, and snippets.

@shuding
Created March 18, 2015 16:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shuding/661758c08313451c93ad to your computer and use it in GitHub Desktop.
Save shuding/661758c08313451c93ad to your computer and use it in GitHub Desktop.
<div style="width:100%; text-align:center" >
<div>Simple Hard Captcha</div>
<canvas id="icanvas"></canvas>
<div width="100%" id="answer">←v←</div>
<div><a href="http://farter.tk">farter</a></div>
<div><small>Text positioning broken<br />on firefox?</small></div>
</div>
<script>
var MODE=1; /* 1:Demonstration 2:Generate */
var ZOOM=2;
var width = icanvas.width = Math.floor(75*ZOOM);
var height = icanvas.height = Math.floor(14*ZOOM);
var chrlst = "ABCDEFGHJKLMNPQRSTUVXYZ"//+"23456789"
var Transformer=function()
{
var ox,oy,ct,st;
this.setTrs=function(x,y,t)
{
x=x||0; y=y||0; t=t||0;
ox=x; oy=y; ct=Math.cos(t); st=Math.sin(t);
}
this.text=function(ctx,ctxfun,str,x,y)
{
ctxfun.call(ctx,str,x*ct-y*st,x*st+y*ct);
}
return this;
}
var draw = function () {
var cntletter=4,
anglerange=0.3,
padding=-0.05,
paddedwidth=1-padding,
offxrange=0.05;
var stylebg="rgba(255,255,255,1)",
stylefg="rgba(0,0,0,1)";
var ctx=icanvas.getContext('2d');
ctx.font=(22*ZOOM).toString() + "pt Arial Black";
ctx.textBaseline="middle";
ctx.textAlign="center";
var rndpnm=function(r,m)
{
return (Math.random()-0.5)*r*m;
}
var rndpm=function(r,m)
{
return (Math.random())*r*m;
}
var trs=new Transformer();
var capstr="";
var letters=new Array(cntletter);
for(var xhl=0;xhl<cntletter;xhl++)
{
letters[xhl]={};
letters[xhl].chr=chrlst[Math.floor(Math.random()*chrlst.length)];
letters[xhl].x=
width*padding*0.5 +
(xhl+0.5)*width*paddedwidth/cntletter +
rndpnm(offxrange,width);
letters[xhl].y=height*0.45;
letters[xhl].angle=rndpnm(anglerange,Math.PI);
letters[xhl].fill=(Math.random())<0.5?0:1;
if("NWV".indexOf(letters[xhl].chr)!==-1 &&
xhl>0 &&
"NWV".indexOf(letters[xhl-1].chr)!==-1
) /* paitially avoid ambiguous combinations */
{
letters[xhl].chr="A";
}
capstr+=letters[xhl].chr;
}
ctx.fillStyle=stylebg;
ctx.fillRect(0,0,width,height);
ctx.strokeStyle=stylefg;
ctx.lineWidth=6*ZOOM;
for(var xhn=0;xhn<5;xhn++)
{
ctx.beginPath();
ctx.moveTo(rndpm(1,width),rndpm(1,height));
ctx.lineTo(rndpm(1,width),rndpm(1,height));
ctx.stroke()
}
ctx.strokeStyle=stylebg;
for(var xhl=0;xhl<cntletter;xhl++)
{
ctx.save();
trs.setTrs(0,0,-(letters[xhl].angle));
ctx.rotate(letters[xhl].angle);
ctx.lineWidth=(letters[xhl].fill?2:3)*ZOOM;
trs.text(
ctx,
ctx.strokeText,
letters[xhl].chr,letters[xhl].x,letters[xhl].y
);
ctx.restore();
}
ctx.lineWidth=1*ZOOM;
ctx.fillStyle=stylefg;
ctx.strokeStyle=stylefg;
for(var xhl=0;xhl<cntletter;xhl++)
{
ctx.save();
trs.setTrs(0,0,-(letters[xhl].angle));
ctx.rotate(letters[xhl].angle);
trs.text(
ctx,
letters[xhl].fill===0?ctx.strokeText:ctx.fillText,
letters[xhl].chr,letters[xhl].x,letters[xhl].y
);
ctx.restore();
}
ctx.strokeStyle=stylebg;
for(var xhl=0;xhl<cntletter;xhl++)
{
ctx.lineWidth=(letters[xhl].fill===0?1:2)*ZOOM;
ctx.beginPath();
ctx.moveTo(letters[xhl].x+rndpnm(1,width/cntletter),height/2+rndpnm(1,height)/2);
ctx.lineTo(letters[xhl].x+rndpnm(1,width/cntletter),height/2+rndpnm(1,height)/2);
ctx.stroke()
}
if(MODE===1)
{
answer.innerHTML=
["←","↖","↑","↗","→","↘","↓","↙"]
[Math.floor(Math.random()*8)]+
"v"+
["←","↖","↑","↗","→","↘","↓","↙"]
[Math.floor(Math.random()*8)];
setTimeout(function(){answer.innerHTML=capstr;},3000);
}
return capstr;
};
if(MODE===1)
{
draw();
setInterval(draw,5000);
}
if(MODE===2)
{
var strall="",capcur="",imgcur="";
for(var xht=0;xht<45;xht++)
{
capcur=draw();
imgcur=icanvas.toDataURL("image/png");
strall+=
"<img src=\"" + imgcur +
"\"></img>" +
capcur + " " + Math.round(imgcur.length*(3/4)) + " " +
((xht+1)%3==0?"<br>":"");
}
document.write(strall);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment