verify.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. /*! Verify-v0.1.0 MIT License by 大熊*/
  2. ;(function($, window, document,undefined) {
  3. //定义Code的构造函数
  4. var Code = function(ele, opt) {
  5. this.$element = ele,
  6. this.defaults = {
  7. type : 1,
  8. figure : 100, //位数,仅在type=2时生效
  9. arith : 0, //算法,支持加减乘,0为随机,仅在type=2时生效
  10. width : '200px',
  11. height : '60px',
  12. fontSize : '30px',
  13. codeLength : 6,
  14. btnId : 'check-btn',
  15. ready : function(){},
  16. success : function(){},
  17. error : function(){}
  18. },
  19. this.options = $.extend({}, this.defaults, opt)
  20. };
  21. var _code_chars = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
  22. var _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0'];
  23. var _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC'];
  24. //定义Code的方法
  25. Code.prototype = {
  26. init : function() {
  27. var _this = this;
  28. this.loadDom();
  29. this.setCode();
  30. this.options.ready();
  31. this.$element[0].onselectstart = document.body.ondrag = function(){
  32. return false;
  33. };
  34. //点击验证码
  35. this.$element.find('.verify-code, .verify-change-code').on('click', function() {
  36. _this.setCode();
  37. });
  38. //确定的点击事件
  39. this.htmlDoms.code_btn.on('click', function() {
  40. _this.checkCode();
  41. })
  42. },
  43. //加载页面
  44. loadDom : function() {
  45. var panelHtml = '<div class="cerify-code-panel"><div class="verify-code"></div><div class="verify-code-area"><div class="verify-input-area"><input type="text" class="varify-input-code" /></div><div class="verify-change-area"><a class="verify-change-code">换一张</a></div></div></div>';
  46. this.$element.append(panelHtml);
  47. this.isEnd = false;
  48. this.htmlDoms = {
  49. code_btn : $('#'+this.options.btnId),
  50. code : this.$element.find('.verify-code'),
  51. code_area : this.$element.find('.verify-code-area'),
  52. code_input : this.$element.find('.varify-input-code'),
  53. };
  54. this.htmlDoms.code.css({'width':this.options.width, 'height':this.options.height,'line-height':this.options.height, 'font-size':this.options.fontSize});
  55. this.htmlDoms.code_area.css({'width':this.options.width});
  56. },
  57. //设置验证码
  58. setCode : function() {
  59. if(this.isEnd == false) {
  60. var color1Num = Math.floor(Math.random() * 3);
  61. var color2Num = Math.floor(Math.random() * 5);
  62. this.htmlDoms.code.css({'background-color': _code_color1[color1Num], 'color': _code_color2[color2Num]});
  63. this.htmlDoms.code_input.val('');
  64. var code = '';
  65. this.code_chose = '';
  66. if(this.options.type == 1) { //普通验证码
  67. for(var i = 0; i < this.options.codeLength; i++) {
  68. var charNum = Math.floor(Math.random() * 52);
  69. var tmpStyle = (charNum%2 ==0)? "font-style:italic;margin-right: 10px;":"font-weight:bolder;";
  70. tmpStyle += (Math.floor(Math.random() * 2) == 1)? "font-weight:bolder;":"";
  71. this.code_chose += _code_chars[charNum];
  72. code += '<font style="'+tmpStyle+'">'+_code_chars[charNum]+'</font>';
  73. }
  74. }else { //算法验证码
  75. var num1 = Math.floor(Math.random() * this.options.figure);
  76. var num2 = Math.floor(Math.random() * this.options.figure);
  77. if(this.options.arith == 0) {
  78. var tmparith = Math.floor(Math.random() * 3);
  79. }
  80. switch(tmparith) {
  81. case 1 :
  82. this.code_chose = parseInt(num1) + parseInt(num2);
  83. code = num1 + ' + ' + num2 + ' = ?';
  84. break;
  85. case 2 :
  86. if(parseInt(num1) < parseInt(num2)) {
  87. var tmpnum = num1;
  88. num1 = num2;
  89. num2 = tmpnum;
  90. }
  91. this.code_chose = parseInt(num1) - parseInt(num2);
  92. code = num1 + ' - ' + num2 + ' = ?';
  93. break;
  94. default :
  95. this.code_chose = parseInt(num1) * parseInt(num2);
  96. code = num1 + ' × ' + num2 + ' = ?';
  97. break;
  98. }
  99. }
  100. this.htmlDoms.code.html(code);
  101. }
  102. },
  103. //比对验证码
  104. checkCode : function() {
  105. if(this.options.type == 1) { //普通验证码
  106. var own_input = this.htmlDoms.code_input.val().toUpperCase();
  107. this.code_chose = this.code_chose.toUpperCase();
  108. }else {
  109. var own_input = this.htmlDoms.code_input.val();
  110. }
  111. if(own_input == this.code_chose) {
  112. this.isEnd = true;
  113. this.options.success(this);
  114. }else {
  115. this.options.error(this);
  116. this.setCode();
  117. }
  118. },
  119. //刷新
  120. refresh : function() {
  121. this.isEnd = false;
  122. this.$element.find('.verify-code').click();
  123. }
  124. };
  125. //定义Slide的构造函数
  126. var Slide = function(ele, opt) {
  127. this.$element = ele,
  128. this.defaults = {
  129. type : 1,
  130. mode : 'fixed', //弹出式pop,固定fixed
  131. vOffset: 5,
  132. vSpace : 5,
  133. explain : '向右滑动完成验证',
  134. imgUrl : 'plugin/verify-master/images/',
  135. imgName : ['1.jpg', '2.jpg'],
  136. imgSize : {
  137. width: '400px',
  138. height: '200px',
  139. },
  140. blockSize : {
  141. width: '50px',
  142. height: '50px',
  143. },
  144. barSize : {
  145. width : '400px',
  146. height : '40px',
  147. },
  148. ready : function(){},
  149. success : function(){},
  150. error : function(){}
  151. },
  152. this.options = $.extend({}, this.defaults, opt)
  153. };
  154. //定义Slide的方法
  155. Slide.prototype = {
  156. init: function() {
  157. var _this = this;
  158. //加载页面
  159. this.loadDom();
  160. this.options.ready();
  161. this.$element[0].onselectstart = document.body.ondrag = function(){
  162. return false;
  163. };
  164. if(this.options.mode == 'pop') {
  165. this.$element.on('mouseover', function(e){
  166. _this.showImg();
  167. });
  168. this.$element.on('mouseout', function(e){
  169. _this.hideImg();
  170. });
  171. this.htmlDoms.out_panel.on('mouseover', function(e){
  172. _this.showImg();
  173. });
  174. this.htmlDoms.out_panel.on('mouseout', function(e){
  175. _this.hideImg();
  176. });
  177. }
  178. //按下
  179. this.htmlDoms.move_block.on('touchstart', function(e) {
  180. _this.start(e);
  181. });
  182. this.htmlDoms.move_block.on('mousedown', function(e) {
  183. _this.start(e);
  184. });
  185. //拖动
  186. window.addEventListener("touchmove", function(e) {
  187. _this.move(e);
  188. });
  189. window.addEventListener("mousemove", function(e) {
  190. _this.move(e);
  191. });
  192. //鼠标松开
  193. window.addEventListener("touchend", function() {
  194. _this.end();
  195. });
  196. window.addEventListener("mouseup", function() {
  197. _this.end();
  198. });
  199. //刷新
  200. _this.$element.find('.verify-refresh').on('click', function() {
  201. _this.refresh();
  202. });
  203. },
  204. //初始化加载
  205. loadDom : function() {
  206. this.img_rand = Math.floor(Math.random() * this.options.imgName.length); //随机的背景图片
  207. var panelHtml = '';
  208. var tmpHtml = '';
  209. if(this.options.type != 1) { //图片滑动
  210. panelHtml += '<div class="verify-img-out" ><div class="verify-img-panel"><div class="verify-refresh"><i class="iconfont icon-refresh"></i></div><div class="verify-gap"></div></div></div>';
  211. tmpHtml = '<div class="verify-sub-block"></div>';
  212. }
  213. panelHtml += '<div class="verify-bar-area"><span class="verify-msg">'+this.options.explain+'</span><div class="verify-left-bar"><span class="verify-msg"></span><div class="verify-move-block"><i class="verify-icon iconfont icon-right"></i>'+tmpHtml+'</div></div></div>';
  214. this.$element.append(panelHtml);
  215. this.htmlDoms = {
  216. gap : this.$element.find('.verify-gap'),
  217. sub_block : this.$element.find('.verify-sub-block'),
  218. out_panel : this.$element.find('.verify-img-out'),
  219. img_panel : this.$element.find('.verify-img-panel'),
  220. bar_area : this.$element.find('.verify-bar-area'),
  221. move_block : this.$element.find('.verify-move-block'),
  222. left_bar : this.$element.find('.verify-left-bar'),
  223. msg : this.$element.find('.verify-msg'),
  224. icon : this.$element.find('.verify-icon'),
  225. refresh :this.$element.find('.verify-refresh')
  226. };
  227. this.status = false; //鼠标状态
  228. this.isEnd = false; //是够验证完成
  229. this.setSize = this.resetSize(this); //重新设置宽度高度
  230. this.$element.css('position', 'relative');
  231. if(this.options.mode == 'pop') {
  232. this.htmlDoms.out_panel.css({'display': 'none', 'position': 'absolute', 'bottom': '42px'});
  233. this.htmlDoms.sub_block.css({'display': 'none'});
  234. }else {
  235. this.htmlDoms.out_panel.css({'position': 'relative'});
  236. }
  237. this.htmlDoms.gap.css({'width': this.options.blockSize.width, 'height': this.options.blockSize.height});
  238. this.htmlDoms.sub_block.css({'width': this.options.blockSize.width, 'height': this.options.blockSize.height});
  239. this.htmlDoms.out_panel.css('height', parseInt(this.setSize.img_height) + this.options.vSpace + 'px');
  240. this.htmlDoms.img_panel.css({'width': this.setSize.img_width, 'height': this.setSize.img_height, 'background': 'url(' + this.options.imgUrl + this.options.imgName[this.img_rand]+')', 'background-size' : this.setSize.img_width + ' '+ this.setSize.img_height});
  241. this.htmlDoms.bar_area.css({'width': this.setSize.bar_width, 'height': this.options.barSize.height, 'line-height':this.options.barSize.height});
  242. this.htmlDoms.move_block.css({'width': this.options.barSize.height, 'height': this.options.barSize.height});
  243. this.htmlDoms.left_bar.css({'width': this.options.barSize.height, 'height': this.options.barSize.height});
  244. this.randSet();
  245. },
  246. //鼠标按下
  247. start: function(e) {
  248. if(this.isEnd == false) {
  249. this.htmlDoms.msg.text('');
  250. this.htmlDoms.move_block.css('background-color', '#337ab7');
  251. this.htmlDoms.left_bar.css('border-color', '#337AB7');
  252. this.htmlDoms.icon.css('color', '#fff');
  253. e.stopPropagation();
  254. this.status = true;
  255. }
  256. },
  257. //鼠标移动
  258. move: function(e) {
  259. if(this.status && this.isEnd == false) {
  260. if(this.options.mode == 'pop') {
  261. this.showImg();
  262. }
  263. if(!e.touches) { //兼容移动端
  264. var x = e.clientX;
  265. }else { //兼容PC端
  266. var x = e.touches[0].pageX;
  267. }
  268. var bar_area_left = Slide.prototype.getLeft(this.htmlDoms.bar_area[0]);
  269. var move_block_left = x - bar_area_left; //小方块相对于父元素的left值
  270. if(this.options.type != 1) { //图片滑动
  271. if(move_block_left >= this.htmlDoms.bar_area[0].offsetWidth - parseInt(parseInt(this.options.blockSize.width)/2) - 2) {
  272. move_block_left = this.htmlDoms.bar_area[0].offsetWidth - parseInt(parseInt(this.options.blockSize.width)/2) - 2;
  273. }
  274. }else { //普通滑动
  275. if(move_block_left >= this.htmlDoms.bar_area[0].offsetWidth - parseInt(parseInt(this.options.barSize.height)/2) + 3) {
  276. this.$element.find('.verify-msg:eq(1)').text('松开验证');
  277. move_block_left = this.htmlDoms.bar_area[0].offsetWidth - parseInt(parseInt(this.options.barSize.height)/2) + 3;
  278. }else {
  279. this.$element.find('.verify-msg:eq(1)').text('');
  280. }
  281. }
  282. if(move_block_left <= 0) {
  283. move_block_left = parseInt(parseInt(this.options.blockSize.width)/2);
  284. }
  285. //拖动后小方块的left值
  286. this.htmlDoms.move_block.css('left', move_block_left-parseInt(parseInt(this.options.blockSize.width)/2) + "px");
  287. this.htmlDoms.left_bar.css('width', move_block_left-parseInt(parseInt(this.options.blockSize.width)/2) + "px");
  288. }
  289. },
  290. //鼠标松开
  291. end: function() {
  292. var _this = this;
  293. //判断是否重合
  294. if(this.status && this.isEnd == false) {
  295. if(this.options.type != 1) { //图片滑动
  296. var vOffset = parseInt(this.options.vOffset);
  297. if(parseInt(this.htmlDoms.gap.css('left')) >= (parseInt(this.htmlDoms.move_block.css('left')) - vOffset) && parseInt(this.htmlDoms.gap.css('left')) <= (parseInt(this.htmlDoms.move_block.css('left')) + vOffset)) {
  298. this.htmlDoms.move_block.css('background-color', '#5cb85c');
  299. this.htmlDoms.left_bar.css({'border-color': '#5cb85c', 'background-color': '#fff'});
  300. this.htmlDoms.icon.css('color', '#fff');
  301. this.htmlDoms.icon.removeClass('icon-right');
  302. this.htmlDoms.icon.addClass('icon-check');
  303. this.htmlDoms.refresh.hide();
  304. this.isEnd = true;
  305. this.options.success(this);
  306. }else{
  307. this.htmlDoms.move_block.css('background-color', '#d9534f');
  308. this.htmlDoms.left_bar.css('border-color', '#d9534f');
  309. this.htmlDoms.icon.css('color', '#fff');
  310. this.htmlDoms.icon.removeClass('icon-right');
  311. this.htmlDoms.icon.addClass('icon-close');
  312. setTimeout(function () {
  313. _this.refresh();
  314. }, 400);
  315. this.options.error(this);
  316. }
  317. }else { //普通滑动
  318. if(parseInt(this.htmlDoms.move_block.css('left')) >= (parseInt(this.setSize.bar_width) - parseInt(this.options.barSize.height) - parseInt(this.options.vOffset))) {
  319. this.htmlDoms.move_block.css('background-color', '#5cb85c');
  320. this.htmlDoms.left_bar.css({'color': '#4cae4c', 'border-color': '#5cb85c', 'background-color': '#fff' });
  321. this.htmlDoms.icon.css('color', '#fff');
  322. this.htmlDoms.icon.removeClass('icon-right');
  323. this.htmlDoms.icon.addClass('icon-check');
  324. this.htmlDoms.refresh.hide();
  325. this.$element.find('.verify-msg:eq(1)').text('验证成功');
  326. this.isEnd = true;
  327. this.options.success(this);
  328. }else {
  329. this.$element.find('.verify-msg:eq(1)').text('');
  330. this.htmlDoms.move_block.css('background-color', '#d9534f');
  331. this.htmlDoms.left_bar.css('border-color', '#d9534f');
  332. this.htmlDoms.icon.css('color', '#fff');
  333. this.htmlDoms.icon.removeClass('icon-right');
  334. this.htmlDoms.icon.addClass('icon-close');
  335. this.isEnd = true;
  336. setTimeout(function () {
  337. _this.$element.find('.verify-msg:eq(1)').text('');
  338. _this.refresh();
  339. _this.isEnd = false;
  340. }, 400);
  341. this.options.error(this);
  342. }
  343. }
  344. this.status = false;
  345. }
  346. },
  347. //弹出式
  348. showImg : function() {
  349. this.htmlDoms.out_panel.css({'display': 'block'});
  350. this.htmlDoms.sub_block.css({'display': 'block'});
  351. },
  352. //固定式
  353. hideImg : function() {
  354. this.htmlDoms.out_panel.css({'display': 'none'});
  355. this.htmlDoms.sub_block.css({'display': 'none'});
  356. },
  357. resetSize : function(obj) {
  358. var img_width,img_height,bar_width,bar_height; //图片的宽度、高度,移动条的宽度、高度
  359. var parentWidth = obj.$element.parent().width() || $(window).width();
  360. var parentHeight = obj.$element.parent().height() || $(window).height();
  361. if(obj.options.imgSize.width.indexOf('%')!= -1){
  362. img_width = parseInt(obj.options.imgSize.width)/100 * parentWidth + 'px';
  363.   }else {
  364. img_width = obj.options.imgSize.width;
  365. }
  366. if(obj.options.imgSize.height.indexOf('%')!= -1){
  367. img_height = parseInt(obj.options.imgSize.height)/100 * parentHeight + 'px';
  368.   }else {
  369. img_height = obj.options.imgSize.height;
  370. }
  371. if(obj.options.barSize.width.indexOf('%')!= -1){
  372. bar_width = parseInt(obj.options.barSize.width)/100 * parentWidth + 'px';
  373.   }else {
  374. bar_width = obj.options.barSize.width;
  375. }
  376. if(obj.options.barSize.height.indexOf('%')!= -1){
  377. bar_height = parseInt(obj.options.barSize.height)/100 * parentHeight + 'px';
  378.   }else {
  379. bar_height = obj.options.barSize.height;
  380. }
  381. return {img_width : img_width, img_height : img_height, bar_width : bar_width, bar_height : bar_height};
  382. },
  383. //随机出生点位
  384. randSet: function() {
  385. var rand1 = Math.floor(Math.random()*9+1);
  386. var rand2 = Math.floor(Math.random()*9+1);
  387. var top = rand1 * parseInt(this.setSize.img_height)/15 + parseInt(this.setSize.img_height) * 0.1;
  388. var left = rand2 * parseInt(this.setSize.img_width)/15 + parseInt(this.setSize.img_width) * 0.1;
  389. this.$element.find('.verify-gap').css({'top': top, 'left': left});
  390. this.$element.find('.verify-sub-block').css({'top':'-'+(parseInt(this.setSize.img_height)- top + this.options.vSpace)+'px', 'background-image': 'url('+ this.options.imgUrl + this.options.imgName[this.img_rand]+')', 'background-size': this.setSize.img_width + ' '+ this.setSize.img_height,'background-position-y': '-'+top+ 'px', 'background-position-x': '-'+left+'px'});
  391. },
  392. //刷新
  393. refresh: function() {
  394. this.htmlDoms.refresh.show();
  395. this.$element.find('.verify-msg:eq(1)').text('');
  396. this.$element.find('.verify-msg:eq(1)').css('color', '#000');
  397. this.htmlDoms.move_block.animate({'left':'0px'}, 'fast');
  398. this.htmlDoms.left_bar.animate({'width': '40px'}, 'fast');
  399. this.htmlDoms.left_bar.css({'border-color': '#ddd'});
  400. this.htmlDoms.move_block.css('background-color', '#fff');
  401. this.htmlDoms.icon.css('color', '#000');
  402. this.htmlDoms.icon.removeClass('icon-close');
  403. this.htmlDoms.icon.addClass('icon-right');
  404. this.$element.find('.verify-msg:eq(0)').text(this.options.explain);
  405. this.randSet();
  406. this.img_rand = Math.floor(Math.random() * this.options.imgName.length); //随机的背景图片
  407. this.$element.find('.verify-img-panel').css({'background': 'url('+ this.options.imgUrl +this.options.imgName[this.img_rand]+')', 'background-size': this.setSize.img_width + ' '+ this.setSize.img_height});
  408. this.$element.find('.verify-sub-block').css({'background-image': 'url('+ this.options.imgUrl +this.options.imgName[this.img_rand]+')', 'background-size': this.setSize.img_width + ' '+ this.setSize.img_height});
  409. this.isEnd = false;
  410. },
  411. //获取left值
  412. getLeft: function(node) {
  413. var left = $(node).offset().left;
  414. // var nowPos = node.offsetParent;
  415. //
  416. // while(nowPos != null) {  
  417. // left += $(nowPos).offset().left; 
  418. // nowPos = nowPos.offsetParent;  
  419. // }
  420. return left;
  421. }
  422. };
  423. //定义Points的构造函数
  424. var Points = function(ele, opt) {
  425. this.$element = ele,
  426. this.defaults = {
  427. mode : 'fixed', //弹出式pop,固定fixed
  428. defaultNum : 4, //默认的文字数量
  429. checkNum : 3, //校对的文字数量
  430. vSpace : 5, //间隔
  431. imgUrl : 'plugin/verify-master/images/',
  432. imgName : ['1.jpg', '2.jpg'],
  433. imgSize : {
  434. width: '400px',
  435. height: '200px',
  436. },
  437. barSize : {
  438. width : '400px',
  439. height : '40px',
  440. },
  441. ready : function(){},
  442. success : function(){},
  443. error : function(){}
  444. },
  445. this.options = $.extend({}, this.defaults, opt)
  446. };
  447. //定义Points的方法
  448. Points.prototype = {
  449. init : function() {
  450. var _this = this;
  451. //加载页面
  452. _this.loadDom();
  453. _this.refresh();
  454. _this.options.ready();
  455. this.$element[0].onselectstart = document.body.ondrag = function(){
  456. return false;
  457. };
  458. if(this.options.mode == 'pop') {
  459. this.$element.on('mouseover', function(e){
  460. _this.showImg();
  461. });
  462. this.$element.on('mouseout', function(e){
  463. _this.hideImg();
  464. });
  465. this.htmlDoms.out_panel.on('mouseover', function(e){
  466. _this.showImg();
  467. });
  468. this.htmlDoms.out_panel.on('mouseout', function(e){
  469. _this.hideImg();
  470. });
  471. }
  472. //点击事件比对
  473. _this.$element.find('.verify-img-panel canvas').on('click', function(e) {
  474. _this.checkPosArr.push(_this.getMousePos(this, e));
  475. if(_this.num == _this.options.checkNum) {
  476. _this.num = _this.createPoint(_this.getMousePos(this, e));
  477. setTimeout(function () {
  478. var flag = _this.comparePos(_this.fontPos, _this.checkPosArr);
  479. if(flag == false) { //验证失败
  480. _this.options.error(_this);
  481. _this.$element.find('.verify-bar-area').css({'color': '#d9534f', 'border-color': '#d9534f'});
  482. _this.$element.find('.verify-msg').text('验证失败');
  483. setTimeout(function () {
  484. _this.$element.find('.verify-bar-area').css({'color': '#000','border-color': '#ddd'});
  485. _this.refresh();
  486. }, 400);
  487. }else { //验证成功
  488. _this.$element.find('.verify-bar-area').css({'color': '#4cae4c', 'border-color': '#5cb85c'});
  489. _this.$element.find('.verify-msg').text('验证成功');
  490. _this.$element.find('.verify-refresh').hide();
  491. _this.$element.find('.verify-img-panel').unbind('click');
  492. _this.options.success(_this);
  493. }
  494. }, 400);
  495. }
  496. if(_this.num < _this.options.checkNum) {
  497. _this.num = _this.createPoint(_this.getMousePos(this, e));
  498. }
  499. });
  500. //刷新
  501. _this.$element.find('.verify-refresh').on('click', function() {
  502. _this.refresh();
  503. });
  504. },
  505. //加载页面
  506. loadDom : function() {
  507. this.fontPos = []; //选中的坐标信息
  508. this.checkPosArr = []; //用户点击的坐标
  509. this.num = 1; //点击的记数
  510. this.img_rand = Math.floor(Math.random() * this.options.imgName.length); //随机的背景图片
  511. var panelHtml = '';
  512. var tmpHtml = '';
  513. this.setSize = Slide.prototype.resetSize(this); //重新设置宽度高度
  514. panelHtml += '<div class="verify-img-out"><div class="verify-img-panel"><div class="verify-refresh" style="z-index:3"><i class="iconfont icon-refresh"></i></div><canvas width="'+this.setSize.img_width+'" height="'+this.setSize.img_height+'"></canvas></div></div><div class="verify-bar-area"><span class="verify-msg"></span></div>';
  515. this.$element.append(panelHtml);
  516. this.htmlDoms = {
  517. out_panel : this.$element.find('.verify-img-out'),
  518. img_panel : this.$element.find('.verify-img-panel'),
  519. bar_area : this.$element.find('.verify-bar-area'),
  520. msg : this.$element.find('.verify-msg'),
  521. };
  522. this.$element.css('position', 'relative');
  523. if(this.options.mode == 'pop') {
  524. this.htmlDoms.out_panel.css({'display': 'none', 'position': 'absolute', 'bottom': '42px'});
  525. }else {
  526. this.htmlDoms.out_panel.css({'position': 'relative'});
  527. }
  528. //this.htmlDoms.out_panel.css('height', parseInt(this.setSize.img_height) + this.options.vSpace + 'px');
  529. //this.htmlDoms.out_panel.css({'display': 'none', 'position': 'absolute'});
  530. this.htmlDoms.img_panel.css({'width': this.setSize.img_width, 'height': this.setSize.img_height, 'background-size' : this.setSize.img_width + ' '+ this.setSize.img_height, 'margin-bottom': this.options.vSpace + 'px'});
  531. this.htmlDoms.bar_area.css({'width': this.options.barSize.width, 'height': this.options.barSize.height, 'line-height':this.options.barSize.height});
  532. },
  533. //绘制合成的图片
  534. drawImg : function(obj, img) {
  535. //准备canvas环境
  536. var canvas = this.$element.find('canvas')[0];
  537. //var canvas=document.getElementById("myCanvas");
  538. var ctx=canvas.getContext("2d");
  539. // 绘制图片
  540. ctx.drawImage(img,0,0, parseInt(this.setSize.img_width), parseInt(this.setSize.img_height));
  541. // 绘制水印
  542. var fontSizeArr = ['italic small-caps bold 20px microsoft yahei', 'small-caps normal 25px arial', '34px microsoft yahei'];
  543. var fontStr = '天地玄黄宇宙洪荒日月盈昃辰宿列张寒来暑往秋收冬藏闰余成岁律吕调阳云腾致雨露结为霜金生丽水玉出昆冈剑号巨阙珠称夜光果珍李柰菜重芥姜海咸河淡鳞潜羽翔龙师火帝鸟官人皇始制文字乃服衣裳推位让国有虞陶唐吊民伐罪周发殷汤坐朝问道垂拱平章爱育黎首臣伏戎羌遐迩体率宾归王'; //不重复的汉字
  544. var fontChars = [];
  545. var avg = Math.floor(parseInt(this.setSize.img_width)/(parseInt(this.options.defaultNum)+1));
  546. var tmp_index = '';
  547. var color2Num = Math.floor(Math.random() * 5);
  548. for(var i = 1; i <= this.options.defaultNum; i++) {
  549. fontChars[i-1] = this.getChars(fontStr, fontChars);
  550. tmp_index = Math.floor(Math.random()*3);
  551. ctx.font = fontSizeArr[tmp_index];
  552. ctx.fillStyle = _code_color2[color2Num];
  553. if(Math.floor(Math.random() * 2) == 1) {
  554. var tmp_y = Math.floor(parseInt(this.setSize.img_height)/2) + tmp_index*20 + 20;
  555. }else {
  556. var tmp_y = Math.floor(parseInt(this.setSize.img_height)/2) - tmp_index*20;
  557. }
  558. ctx.fillText(fontChars[i-1],avg * i, tmp_y);
  559. this.fontPos[i-1] = {'char': fontChars[i-1], 'x': avg * i, 'y': tmp_y};
  560. }
  561. for(var i = 0; i < (this.options.defaultNum-this.options.checkNum); i++) {
  562. this.shuffle(this.fontPos).pop();
  563. }
  564. var msgStr = '';
  565. for(var i = 0; i < this.fontPos.length; i++) {
  566. msgStr += this.fontPos[i].char + ',';
  567. }
  568. this.htmlDoms.msg.text('请顺序点击【' + msgStr.substring(0,msgStr.length-1) + '】');
  569. return this.fontPos;
  570. },
  571. //获取坐标
  572. getMousePos :function(obj, event) {
  573. var e = event || window.event;
  574. var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
  575. var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
  576. var x = e.clientX - ($(obj).offset().left - $(window).scrollLeft());
  577. var y = e.clientY - ($(obj).offset().top - $(window).scrollTop());
  578. return {'x': x, 'y': y};
  579. },
  580. //递归去重
  581. getChars : function(fontStr, fontChars) {
  582. var tmp_rand = parseInt(Math.floor(Math.random() * fontStr.length));
  583. if(tmp_rand > 0) {
  584. tmp_rand = tmp_rand - 1;
  585. }
  586. tmp_char = fontStr.charAt(tmp_rand);
  587. if($.inArray(tmp_char, fontChars) == -1) {
  588. return tmp_char;
  589. }else {
  590. return Points.prototype.getChars(fontStr, fontChars);
  591. }
  592. },
  593. //洗牌数组
  594. shuffle : function(arr) {
  595. var m = arr.length, i;
  596. var tmpF;
  597. while (m) {
  598. i = (Math.random() * m--) >>> 0;
  599. tmpF = arr[m];
  600. arr[m] = arr[i];
  601. arr[i] = tmpF;
  602. //[arr[m], arr[i]] = [arr[i], arr[m]]; //低版本浏览器不支持此写法
  603. }
  604. return arr;
  605. },
  606. //创建坐标点
  607. createPoint : function (pos) {
  608. this.htmlDoms.img_panel.append('<div class="point-area" style="background-color:#1abd6c;color:#fff;z-index:9999;width:30px;height:30px;text-align:center;line-height:30px;border-radius: 50%;position:absolute;top:'+parseInt(pos.y-10)+'px;left:'+parseInt(pos.x-10)+'px;">'+this.num+'</div>');
  609. return ++this.num;
  610. },
  611. //比对坐标点
  612. comparePos : function (fontPos, checkPosArr) {
  613. var flag = true;
  614. for(var i = 0; i < fontPos.length; i++) {
  615. if(!(parseInt(checkPosArr[i].x) + 40 > fontPos[i].x && parseInt(checkPosArr[i].x) - 40 < fontPos[i].x && parseInt(checkPosArr[i].y) + 40 > fontPos[i].y && parseInt(checkPosArr[i].y) - 40 < fontPos[i].y)) {
  616. flag = false;
  617. break;
  618. }
  619. }
  620. return flag;
  621. },
  622. //弹出式
  623. showImg : function() {
  624. this.htmlDoms.out_panel.css({'display': 'block'});
  625. },
  626. //固定式
  627. hideImg : function() {
  628. this.htmlDoms.out_panel.css({'display': 'none'});
  629. },
  630. //刷新
  631. refresh: function() {
  632. var _this = this;
  633. this.$element.find('.point-area').remove();
  634. this.fontPos = [];
  635. this.checkPosArr = [];
  636. this.num = 1;
  637. this.img_rand = Math.floor(Math.random() * this.options.imgName.length); //随机的背景图片
  638. var img = new Image();
  639. img.src = this.options.imgUrl +this.options.imgName[this.img_rand];
  640. // 加载完成开始绘制
  641. $(img).on('load', function(e) {
  642. this.fontPos = _this.drawImg(_this, this);
  643. });
  644. _this.$element.find('.verify-bar-area').css({'color': '#000', 'border-color': '#ddd'});
  645. _this.$element.find('.verify-msg').text('验证失败');
  646. _this.$element.find('.verify-refresh').show();
  647. },
  648. };
  649. //在插件中使用codeVerify对象
  650. $.fn.codeVerify = function(options, callbacks) {
  651. var code = new Code(this, options);
  652. code.init();
  653. };
  654. //在插件中使用slideVerify对象
  655. $.fn.slideVerify = function(options, callbacks) {
  656. var slide = new Slide(this, options);
  657. slide.init();
  658. };
  659. //在插件中使用clickVerify对象
  660. $.fn.pointsVerify = function(options, callbacks) {
  661. var points = new Points(this, options);
  662. points.init();
  663. };
  664. })(jQuery, window, document);