UNPKG

ng-captcha

Version:

A pure front-end angular captcha module.

212 lines (204 loc) 20.2 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('ng-captcha', ['exports', '@angular/core', '@angular/common'], factory) : (factory((global['ng-captcha'] = {}),global.ng.core,global.ng.common)); }(this, (function (exports,core,common) { 'use strict'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var CaptchaComponent = /** @class */ (function () { function CaptchaComponent() { this.generateCode = new core.EventEmitter(); this.canvas = document.createElement('canvas'); this.letters = ["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"]; this.code = ''; } /** * @return {?} */ CaptchaComponent.prototype.ngOnInit = /** * @return {?} */ function () { this.init(); this.refresh(); }; /** * @return {?} */ CaptchaComponent.prototype.onClick = /** * @return {?} */ function () { this.refresh(); }; /** * @return {?} */ CaptchaComponent.prototype.init = /** * @return {?} */ function () { this.canvas.width = this.width || 100; this.canvas.height = this.height || 50; this.canvas.style.cursor = 'pointer'; this.canvas.innerHTML = '您的浏览器版本不支持canvas'; this.container.nativeElement.appendChild(this.canvas); }; // generate code // generate code /** * @return {?} */ CaptchaComponent.prototype.refresh = // generate code /** * @return {?} */ function () { this.code = ''; /** @type {?} */ var ctx = this.canvas.getContext('2d'); ctx.textBaseline = 'middle'; ctx.fillStyle = this.randomColor(180, 240); ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); for (var i = 0; i < 4; i++) { /** @type {?} */ var letter = this.letters[this.randomNum(0, this.letters.length)]; this.code += letter; ctx.font = this.randomNum(this.canvas.height / 2, this.canvas.height) + 'px SimHei'; ctx.fillStyle = this.randomColor(50, 160); ctx.shadowOffsetX = this.randomNum(-3, 3); ctx.shadowOffsetY = this.randomNum(-3, 3); ctx.shadowBlur = this.randomNum(-3, 3); ctx.shadowColor = 'rgb(0, 0, 0, 0.3)'; /** @type {?} */ var x = this.canvas.width / 5 * i; /** @type {?} */ var y = this.canvas.height / 2; /** @type {?} */ var deg = this.randomNum(-30, 30); // setting rotate and origin point ctx.translate(x, y); ctx.rotate(deg * Math.PI / 180); ctx.fillText(letter, 0, 0); // reset rotate and origin point ctx.rotate(-deg * Math.PI / 180); ctx.translate(-x, -y); } // draw interfering line for (var i = 0; i < 4; i++) { ctx.strokeStyle = this.randomColor(40, 180); ctx.beginPath(); ctx.moveTo(this.randomNum(0, this.canvas.width), this.randomNum(0, this.canvas.height)); ctx.lineTo(this.randomNum(0, this.canvas.width), this.randomNum(0, this.canvas.height)); ctx.stroke(); } // draw interfering point for (var i = 0; i < this.canvas.width / 4; i++) { ctx.fillStyle = this.randomColor(); ctx.beginPath(); ctx.arc(this.randomNum(0, this.canvas.width), this.randomNum(0, this.canvas.height), 1, 0, 2 * Math.PI); ctx.fill(); } this.generateCode.emit(this.code.toLowerCase()); }; /** * return a random integer * @param min 最小值 * @param max 最大值 */ /** * return a random integer * @param {?} min 最小值 * @param {?} max 最大值 * @return {?} */ CaptchaComponent.prototype.randomNum = /** * return a random integer * @param {?} min 最小值 * @param {?} max 最大值 * @return {?} */ function (min, max) { return Math.floor(Math.random() * (max - min) + min); }; /** * return a random color */ /** * return a random color * @param {?=} min * @param {?=} max * @return {?} */ CaptchaComponent.prototype.randomColor = /** * return a random color * @param {?=} min * @param {?=} max * @return {?} */ function (min, max) { if (min === void 0) { min = 0; } if (max === void 0) { max = 255; } /** @type {?} */ var r = this.randomNum(min, max); /** @type {?} */ var g = this.randomNum(min, max); /** @type {?} */ var b = this.randomNum(min, max); return "rgb(" + r + ", " + g + ", " + b + ")"; }; CaptchaComponent.decorators = [ { type: core.Component, args: [{ selector: 'captcha', template: "<div class=\"captcha-container\" #captchaContainer (click)=\"onClick()\"></div>", styles: [".captcha-container{display:inline-block;line-height:0}"] }] } ]; /** @nocollapse */ CaptchaComponent.ctorParameters = function () { return []; }; CaptchaComponent.propDecorators = { width: [{ type: core.Input }], height: [{ type: core.Input }], generateCode: [{ type: core.Output }], container: [{ type: core.ViewChild, args: ['captchaContainer',] }] }; return CaptchaComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var CaptchaModule = /** @class */ (function () { function CaptchaModule() { } CaptchaModule.decorators = [ { type: core.NgModule, args: [{ imports: [ common.CommonModule ], declarations: [CaptchaComponent], exports: [CaptchaComponent] },] } ]; return CaptchaModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ exports.CaptchaModule = CaptchaModule; exports.ɵa = CaptchaComponent; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctY2FwdGNoYS51bWQuanMubWFwIiwic291cmNlcyI6WyJuZzovL25nLWNhcHRjaGEvbGliL2NhcHRjaGEuY29tcG9uZW50LnRzIiwibmc6Ly9uZy1jYXB0Y2hhL2xpYi9jYXB0Y2hhLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgVmlld0NoaWxkLCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY2FwdGNoYScsXG4gIHRlbXBsYXRlVXJsOiAnLi9jYXB0Y2hhLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2FwdGNoYS5jb21wb25lbnQuY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgQ2FwdGNoYUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgd2lkdGhcbiAgQElucHV0KCkgaGVpZ2h0XG4gIEBPdXRwdXQoKSBnZW5lcmF0ZUNvZGUgPSBuZXcgRXZlbnRFbWl0dGVyKClcbiAgQFZpZXdDaGlsZCgnY2FwdGNoYUNvbnRhaW5lcicpIGNvbnRhaW5lclxuICBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxuICBsZXR0ZXJzID0gW1wiMFwiLCBcIjFcIiwgXCIyXCIsIFwiM1wiLCBcIjRcIiwgXCI1XCIsIFwiNlwiLCBcIjdcIiwgXCI4XCIsIFwiOVwiLCBcImFcIiwgXCJiXCIsIFwiY1wiLCBcImRcIiwgXCJlXCIsIFwiZlwiLCBcImdcIiwgXCJoXCIsIFwiaVwiLCBcImpcIiwgXCJrXCIsIFwibFwiLCBcIm1cIiwgXCJuXCIsIFwib1wiLCBcInBcIiwgXCJxXCIsIFwiclwiLCBcInNcIiwgXCJ0XCIsIFwidVwiLCBcInZcIiwgXCJ3XCIsIFwieFwiLCBcInlcIiwgXCJ6XCIsIFwiQVwiLCBcIkJcIiwgXCJDXCIsIFwiRFwiLCBcIkVcIiwgXCJGXCIsIFwiR1wiLCBcIkhcIiwgXCJJXCIsIFwiSlwiLCBcIktcIiwgXCJMXCIsIFwiTVwiLCBcIk5cIiwgXCJPXCIsIFwiUFwiLCBcIlFcIiwgXCJSXCIsIFwiU1wiLCBcIlRcIiwgXCJVXCIsIFwiVlwiLCBcIldcIiwgXCJYXCIsIFwiWVwiLCBcIlpcIl1cbiAgY29kZSA9ICcnXG5cbiAgY29uc3RydWN0b3IoKSB7IH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmluaXQoKVxuICAgIHRoaXMucmVmcmVzaCgpXG4gIH1cblxuICBvbkNsaWNrKCkge1xuICAgIHRoaXMucmVmcmVzaCgpXG4gIH1cblxuICBwcml2YXRlIGluaXQoKSB7XG4gICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoIHx8IDEwMFxuICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0IHx8IDUwXG4gICAgdGhpcy5jYW52YXMuc3R5bGUuY3Vyc29yID0gJ3BvaW50ZXInXG4gICAgdGhpcy5jYW52YXMuaW5uZXJIVE1MID0gJ8OmwoLCqMOnwprChMOmwrXCj8OowqfCiMOlwpnCqMOnwonCiMOmwpzCrMOkwrjCjcOmwpTCr8OmwozCgWNhbnZhcydcbiAgICB0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKVxuICB9XG5cbiAgLy8gZ2VuZXJhdGUgY29kZVxuICBwcml2YXRlIHJlZnJlc2goKSB7XG4gICAgdGhpcy5jb2RlID0gJydcbiAgICBjb25zdCBjdHggPSB0aGlzLmNhbnZhcy5nZXRDb250ZXh0KCcyZCcpXG4gICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnXG4gICAgY3R4LmZpbGxTdHlsZSA9IHRoaXMucmFuZG9tQ29sb3IoMTgwLCAyNDApXG4gICAgY3R4LmZpbGxSZWN0KDAsIDAsIHRoaXMuY2FudmFzLndpZHRoLCB0aGlzLmNhbnZhcy5oZWlnaHQpXG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7IGkrKykge1xuICAgICAgY29uc3QgbGV0dGVyID0gdGhpcy5sZXR0ZXJzW3RoaXMucmFuZG9tTnVtKDAsIHRoaXMubGV0dGVycy5sZW5ndGgpXVxuICAgICAgdGhpcy5jb2RlICs9IGxldHRlclxuICAgICAgY3R4LmZvbnQgPSB0aGlzLnJhbmRvbU51bSh0aGlzLmNhbnZhcy5oZWlnaHQgLyAyLCB0aGlzLmNhbnZhcy5oZWlnaHQpICsgJ3B4IFNpbUhlaSdcbiAgICAgIGN0eC5maWxsU3R5bGUgPSB0aGlzLnJhbmRvbUNvbG9yKDUwLCAxNjApXG4gICAgICBjdHguc2hhZG93T2Zmc2V0WCA9IHRoaXMucmFuZG9tTnVtKC0zLCAzKVxuICAgICAgY3R4LnNoYWRvd09mZnNldFkgPSB0aGlzLnJhbmRvbU51bSgtMywgMylcbiAgICAgIGN0eC5zaGFkb3dCbHVyID0gdGhpcy5yYW5kb21OdW0oLTMsIDMpXG4gICAgICBjdHguc2hhZG93Q29sb3IgPSAncmdiKDAsIDAsIDAsIDAuMyknXG4gICAgICBjb25zdCB4ID0gdGhpcy5jYW52YXMud2lkdGggLyA1ICogaVxuICAgICAgY29uc3QgeSA9IHRoaXMuY2FudmFzLmhlaWdodCAvIDJcbiAgICAgIGNvbnN0IGRlZyA9IHRoaXMucmFuZG9tTnVtKC0zMCwgMzApXG4gICAgICAvLyBzZXR0aW5nIHJvdGF0ZSBhbmQgb3JpZ2luIHBvaW50XG4gICAgICBjdHgudHJhbnNsYXRlKHgsIHkpXG4gICAgICBjdHgucm90YXRlKGRlZyAqIE1hdGguUEkgLyAxODApXG4gICAgICBjdHguZmlsbFRleHQobGV0dGVyLCAwLCAwKVxuICAgICAgLy8gcmVzZXQgcm90YXRlIGFuZCBvcmlnaW4gcG9pbnRcbiAgICAgIGN0eC5yb3RhdGUoLWRlZyAqIE1hdGguUEkgLyAxODApXG4gICAgICBjdHgudHJhbnNsYXRlKC14LCAteSlcbiAgICB9XG5cbiAgICAvLyBkcmF3IGludGVyZmVyaW5nIGxpbmVcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7IGkrKykge1xuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gdGhpcy5yYW5kb21Db2xvcig0MCwgMTgwKVxuICAgICAgY3R4LmJlZ2luUGF0aCgpXG4gICAgICBjdHgubW92ZVRvKHRoaXMucmFuZG9tTnVtKDAsIHRoaXMuY2FudmFzLndpZHRoKSwgdGhpcy5yYW5kb21OdW0oMCwgdGhpcy5jYW52YXMuaGVpZ2h0KSlcbiAgICAgIGN0eC5saW5lVG8odGhpcy5yYW5kb21OdW0oMCwgdGhpcy5jYW52YXMud2lkdGgpLCB0aGlzLnJhbmRvbU51bSgwLCB0aGlzLmNhbnZhcy5oZWlnaHQpKVxuICAgICAgY3R4LnN0cm9rZSgpXG4gICAgfVxuXG4gICAgLy8gZHJhdyBpbnRlcmZlcmluZyBwb2ludFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jYW52YXMud2lkdGggLyA0OyBpKyspIHtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSB0aGlzLnJhbmRvbUNvbG9yKClcbiAgICAgIGN0eC5iZWdpblBhdGgoKVxuICAgICAgY3R4LmFyYyh0aGlzLnJhbmRvbU51bSgwLCB0aGlzLmNhbnZhcy53aWR0aCksIHRoaXMucmFuZG9tTnVtKDAsIHRoaXMuY2FudmFzLmhlaWdodCksIDEsIDAsIDIgKiBNYXRoLlBJKVxuICAgICAgY3R4LmZpbGwoKVxuICAgIH1cblxuICAgIHRoaXMuZ2VuZXJhdGVDb2RlLmVtaXQodGhpcy5jb2RlLnRvTG93ZXJDYXNlKCkpXG4gIH1cblxuICAvKipcbiAgICogcmV0dXJuIGEgcmFuZG9tIGludGVnZXJcbiAgICogQHBhcmFtIG1pbiDDpsKcwoDDpcKwwo/DpcKAwrxcbiAgICogQHBhcmFtIG1heCDDpsKcwoDDpcKkwqfDpcKAwrxcbiAgICovXG4gIHByaXZhdGUgcmFuZG9tTnVtKG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChtYXggLSBtaW4pICsgbWluKVxuICB9XG5cbiAgLyoqXG4gICAqIHJldHVybiBhIHJhbmRvbSBjb2xvclxuICAgKi9cbiAgcHJpdmF0ZSByYW5kb21Db2xvcihtaW4gPSAwLCBtYXggPSAyNTUpIHtcbiAgICBjb25zdCByID0gdGhpcy5yYW5kb21OdW0obWluLCBtYXgpXG4gICAgY29uc3QgZyA9IHRoaXMucmFuZG9tTnVtKG1pbiwgbWF4KVxuICAgIGNvbnN0IGIgPSB0aGlzLnJhbmRvbU51bShtaW4sIG1heClcbiAgICByZXR1cm4gYHJnYigke3J9LCAke2d9LCAke2J9KWBcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENhcHRjaGFDb21wb25lbnQgfSBmcm9tICcuL2NhcHRjaGEuY29tcG9uZW50JztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZVxuICBdLFxuICBkZWNsYXJhdGlvbnM6IFtDYXB0Y2hhQ29tcG9uZW50XSxcbiAgZXhwb3J0czogW0NhcHRjaGFDb21wb25lbnRdXG59KVxuZXhwb3J0IGNsYXNzIENhcHRjaGFNb2R1bGUgeyB9XG4iXSwibmFtZXMiOlsiRXZlbnRFbWl0dGVyIiwiQ29tcG9uZW50IiwiSW5wdXQiLCJPdXRwdXQiLCJWaWV3Q2hpbGQiLCJOZ01vZHVsZSIsIkNvbW1vbk1vZHVsZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO1FBaUJFO1lBTlUsaUJBQVksR0FBRyxJQUFJQSxpQkFBWSxFQUFFLENBQUE7WUFFM0MsV0FBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDekMsWUFBTyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcs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