ng-captcha
Version:
A pure front-end angular captcha module.
161 lines (155 loc) • 17.1 kB
JavaScript
import { Component, ViewChild, Output, EventEmitter, Input, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class CaptchaComponent {
constructor() {
this.generateCode = new 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 {?}
*/
ngOnInit() {
this.init();
this.refresh();
}
/**
* @return {?}
*/
onClick() {
this.refresh();
}
/**
* @return {?}
*/
init() {
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
/**
* @return {?}
*/
refresh() {
this.code = '';
/** @type {?} */
const 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 (let i = 0; i < 4; i++) {
/** @type {?} */
const 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 {?} */
const x = this.canvas.width / 5 * i;
/** @type {?} */
const y = this.canvas.height / 2;
/** @type {?} */
const deg = this.randomNum(-30, 30)
// setting rotate and origin point
;
// 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 (let 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 (let 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 {?}
*/
randomNum(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
/**
* return a random color
* @param {?=} min
* @param {?=} max
* @return {?}
*/
randomColor(min = 0, max = 255) {
/** @type {?} */
const r = this.randomNum(min, max);
/** @type {?} */
const g = this.randomNum(min, max);
/** @type {?} */
const b = this.randomNum(min, max);
return `rgb(${r}, ${g}, ${b})`;
}
}
CaptchaComponent.decorators = [
{ type: 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 = () => [];
CaptchaComponent.propDecorators = {
width: [{ type: Input }],
height: [{ type: Input }],
generateCode: [{ type: Output }],
container: [{ type: ViewChild, args: ['captchaContainer',] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class CaptchaModule {
}
CaptchaModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule
],
declarations: [CaptchaComponent],
exports: [CaptchaComponent]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
export { CaptchaModule, CaptchaComponent as ɵa };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctY2FwdGNoYS5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmctY2FwdGNoYS9saWIvY2FwdGNoYS5jb21wb25lbnQudHMiLCJuZzovL25nLWNhcHRjaGEvbGliL2NhcHRjaGEubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBWaWV3Q2hpbGQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjYXB0Y2hhJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NhcHRjaGEuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jYXB0Y2hhLmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBDYXB0Y2hhQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSB3aWR0aFxuICBASW5wdXQoKSBoZWlnaHRcbiAgQE91dHB1dCgpIGdlbmVyYXRlQ29kZSA9IG5ldyBFdmVudEVtaXR0ZXIoKVxuICBAVmlld0NoaWxkKCdjYXB0Y2hhQ29udGFpbmVyJykgY29udGFpbmVyXG4gIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXG4gIGxldHRlcnMgPSBbXCIwXCIsIFwiMVwiLCBcIjJcIiwgXCIzXCIsIFwiNFwiLCBcIjVcIiwgXCI2XCIsIFwiN1wiLCBcIjhcIiwgXCI5XCIsIFwiYVwiLCBcImJcIiwgXCJjXCIsIFwiZFwiLCBcImVcIiwgXCJmXCIsIFwiZ1wiLCBcImhcIiwgXCJpXCIsIFwialwiLCBcImtcIiwgXCJsXCIsIFwibVwiLCBcIm5cIiwgXCJvXCIsIFwicFwiLCBcInFcIiwgXCJyXCIsIFwic1wiLCBcInRcIiwgXCJ1XCIsIFwidlwiLCBcIndcIiwgXCJ4XCIsIFwieVwiLCBcInpcIiwgXCJBXCIsIFwiQlwiLCBcIkNcIiwgXCJEXCIsIFwiRVwiLCBcIkZcIiwgXCJHXCIsIFwiSFwiLCBcIklcIiwgXCJKXCIsIFwiS1wiLCBcIkxcIiwgXCJNXCIsIFwiTlwiLCBcIk9cIiwgXCJQXCIsIFwiUVwiLCBcIlJcIiwgXCJTXCIsIFwiVFwiLCBcIlVcIiwgXCJWXCIsIFwiV1wiLCBcIlhcIiwgXCJZXCIsIFwiWlwiXVxuICBjb2RlID0gJydcblxuICBjb25zdHJ1Y3RvcigpIHsgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaW5pdCgpXG4gICAgdGhpcy5yZWZyZXNoKClcbiAgfVxuXG4gIG9uQ2xpY2soKSB7XG4gICAgdGhpcy5yZWZyZXNoKClcbiAgfVxuXG4gIHByaXZhdGUgaW5pdCgpIHtcbiAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHRoaXMud2lkdGggfHwgMTAwXG4gICAgdGhpcy5jYW52YXMuaGVpZ2h0ID0gdGhpcy5oZWlnaHQgfHwgNTBcbiAgICB0aGlzLmNhbnZhcy5zdHlsZS5jdXJzb3IgPSAncG9pbnRlcidcbiAgICB0aGlzLmNhbnZhcy5pbm5lckhUTUwgPSAnw6bCgsKow6fCmsKEw6bCtcKPw6jCp8KIw6XCmcKow6fCicKIw6bCnMKsw6TCuMKNw6bClMKvw6bCjMKBY2FudmFzJ1xuICAgIHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy5jYW52YXMpXG4gIH1cblxuICAvLyBnZW5lcmF0ZSBjb2RlXG4gIHByaXZhdGUgcmVmcmVzaCgpIHtcbiAgICB0aGlzLmNvZGUgPSAnJ1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY2FudmFzLmdldENvbnRleHQoJzJkJylcbiAgICBjdHgudGV4dEJhc2VsaW5lID0gJ21pZGRsZSdcbiAgICBjdHguZmlsbFN0eWxlID0gdGhpcy5yYW5kb21Db2xvcigxODAsIDI0MClcbiAgICBjdHguZmlsbFJlY3QoMCwgMCwgdGhpcy5jYW52YXMud2lkdGgsIHRoaXMuY2FudmFzLmhlaWdodClcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgICBjb25zdCBsZXR0ZXIgPSB0aGlzLmxldHRlcnNbdGhpcy5yYW5kb21OdW0oMCwgdGhpcy5sZXR0ZXJzLmxlbmd0aCldXG4gICAgICB0aGlzLmNvZGUgKz0gbGV0dGVyXG4gICAgICBjdHguZm9udCA9IHRoaXMucmFuZG9tTnVtKHRoaXMuY2FudmFzLmhlaWdodCAvIDIsIHRoaXMuY2FudmFzLmhlaWdodCkgKyAncHggU2ltSGVpJ1xuICAgICAgY3R4LmZpbGxTdHlsZSA9IHRoaXMucmFuZG9tQ29sb3IoNTAsIDE2MClcbiAgICAgIGN0eC5zaGFkb3dPZmZzZXRYID0gdGhpcy5yYW5kb21OdW0oLTMsIDMpXG4gICAgICBjdHguc2hhZG93T2Zmc2V0WSA9IHRoaXMucmFuZG9tTnVtKC0zLCAzKVxuICAgICAgY3R4LnNoYWRvd0JsdXIgPSB0aGlzLnJhbmRvbU51bSgtMywgMylcbiAgICAgIGN0eC5zaGFkb3dDb2xvciA9ICdyZ2IoMCwgMCwgMCwgMC4zKSdcbiAgICAgIGNvbnN0IHggPSB0aGlzLmNhbnZhcy53aWR0aCAvIDUgKiBpXG4gICAgICBjb25zdCB5ID0gdGhpcy5jYW52YXMuaGVpZ2h0IC8gMlxuICAgICAgY29uc3QgZGVnID0gdGhpcy5yYW5kb21OdW0oLTMwLCAzMClcbiAgICAgIC8vIHNldHRpbmcgcm90YXRlIGFuZCBvcmlnaW4gcG9pbnRcbiAgICAgIGN0eC50cmFuc2xhdGUoeCwgeSlcbiAgICAgIGN0eC5yb3RhdGUoZGVnICogTWF0aC5QSSAvIDE4MClcbiAgICAgIGN0eC5maWxsVGV4dChsZXR0ZXIsIDAsIDApXG4gICAgICAvLyByZXNldCByb3RhdGUgYW5kIG9yaWdpbiBwb2ludFxuICAgICAgY3R4LnJvdGF0ZSgtZGVnICogTWF0aC5QSSAvIDE4MClcbiAgICAgIGN0eC50cmFuc2xhdGUoLXgsIC15KVxuICAgIH1cblxuICAgIC8vIGRyYXcgaW50ZXJmZXJpbmcgbGluZVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgICBjdHguc3Ryb2tlU3R5bGUgPSB0aGlzLnJhbmRvbUNvbG9yKDQwLCAxODApXG4gICAgICBjdHguYmVnaW5QYXRoKClcbiAgICAgIGN0eC5tb3ZlVG8odGhpcy5yYW5kb21OdW0oMCwgdGhpcy5jYW52YXMud2lkdGgpLCB0aGlzLnJhbmRvbU51bSgwLCB0aGlzLmNhbnZhcy5oZWlnaHQpKVxuICAgICAgY3R4LmxpbmVUbyh0aGlzLnJhbmRvbU51bSgwLCB0aGlzLmNhbnZhcy53aWR0aCksIHRoaXMucmFuZG9tTnVtKDAsIHRoaXMuY2FudmFzLmhlaWdodCkpXG4gICAgICBjdHguc3Ryb2tlKClcbiAgICB9XG5cbiAgICAvLyBkcmF3IGludGVyZmVyaW5nIHBvaW50XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNhbnZhcy53aWR0aCAvIDQ7IGkrKykge1xuICAgICAgY3R4LmZpbGxTdHlsZSA9IHRoaXMucmFuZG9tQ29sb3IoKVxuICAgICAgY3R4LmJlZ2luUGF0aCgpXG4gICAgICBjdHguYXJjKHRoaXMucmFuZG9tTnVtKDAsIHRoaXMuY2FudmFzLndpZHRoKSwgdGhpcy5yYW5kb21OdW0oMCwgdGhpcy5jYW52YXMuaGVpZ2h0KSwgMSwgMCwgMiAqIE1hdGguUEkpXG4gICAgICBjdHguZmlsbCgpXG4gICAgfVxuXG4gICAgdGhpcy5nZW5lcmF0ZUNvZGUuZW1pdCh0aGlzLmNvZGUudG9Mb3dlckNhc2UoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiByZXR1cm4gYSByYW5kb20gaW50ZWdlclxuICAgKiBAcGFyYW0gbWluIMOmwpzCgMOlwrDCj8OlwoDCvFxuICAgKiBAcGFyYW0gbWF4IMOmwpzCgMOlwqTCp8OlwoDCvFxuICAgKi9cbiAgcHJpdmF0ZSByYW5kb21OdW0obWluLCBtYXgpIHtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKG1heCAtIG1pbikgKyBtaW4pXG4gIH1cblxuICAvKipcbiAgICogcmV0dXJuIGEgcmFuZG9tIGNvbG9yXG4gICAqL1xuICBwcml2YXRlIHJhbmRvbUNvbG9yKG1pbiA9IDAsIG1heCA9IDI1NSkge1xuICAgIGNvbnN0IHIgPSB0aGlzLnJhbmRvbU51bShtaW4sIG1heClcbiAgICBjb25zdCBnID0gdGhpcy5yYW5kb21OdW0obWluLCBtYXgpXG4gICAgY29uc3QgYiA9IHRoaXMucmFuZG9tTnVtKG1pbiwgbWF4KVxuICAgIHJldHVybiBgcmdiKCR7cn0sICR7Z30sICR7Yn0pYFxuICB9XG5cbn1cbiIsImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ2FwdGNoYUNvbXBvbmVudCB9IGZyb20gJy4vY2FwdGNoYS5jb21wb25lbnQnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlXG4gIF0sXG4gIGRlY2xhcmF0aW9uczogW0NhcHRjaGFDb21wb25lbnRdLFxuICBleHBvcnRzOiBbQ2FwdGNoYUNvbXBvbmVudF1cbn0pXG5leHBvcnQgY2xhc3MgQ2FwdGNoYU1vZHVsZSB7IH1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUEsTUFPYSxnQkFBZ0I7SUFVM0I7UUFOVSxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUE7UUFFM0MsV0FBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDekMsWUFBTyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FB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