ng-captcha
Version:
A pure front-end angular captcha module.
212 lines (204 loc) • 20.2 kB
JavaScript
(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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