ng-captcha
Version:
A pure front-end angular captcha module.
146 lines • 16.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import { Component, ViewChild, Output, EventEmitter, Input } from '@angular/core';
export 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',] }]
};
if (false) {
/** @type {?} */
CaptchaComponent.prototype.width;
/** @type {?} */
CaptchaComponent.prototype.height;
/** @type {?} */
CaptchaComponent.prototype.generateCode;
/** @type {?} */
CaptchaComponent.prototype.container;
/** @type {?} */
CaptchaComponent.prototype.canvas;
/** @type {?} */
CaptchaComponent.prototype.letters;
/** @type {?} */
CaptchaComponent.prototype.code;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwdGNoYS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZy1jYXB0Y2hhLyIsInNvdXJjZXMiOlsibGliL2NhcHRjaGEuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLFNBQVMsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQU8xRixNQUFNLE9BQU8sZ0JBQWdCO0lBVTNCO1FBTlUsaUJBQVksR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFBO1FBRTNDLFdBQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3pDLFlBQU8sR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdB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QUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQTtJQUNoQyxDQUFDOzs7WUFwR0YsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSxTQUFTO2dCQUNuQiwyRkFBdUM7O2FBRXhDOzs7OztvQkFHRSxLQUFLO3FCQUNMLEtBQUs7MkJBQ0wsTUFBTTt3QkFDTixTQUFTLFNBQUMsa0JBQWtCOzs7O0lBSDdCLGlDQUFjOztJQUNkLGtDQUFlOztJQUNmLHdDQUEyQzs7SUFDM0MscUNBQXdDOztJQUN4QyxrQ0FBeUM7O0lBQ3pDLG1DQUFnVTs7SUFDaFUsZ0NBQVMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgVmlld0NoaWxkLCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY2FwdGNoYScsXG4gIHRlbXBsYXRlVXJsOiAnLi9jYXB0Y2hhLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2FwdGNoYS5jb21wb25lbnQuY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgQ2FwdGNoYUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgd2lkdGhcbiAgQElucHV0KCkgaGVpZ2h0XG4gIEBPdXRwdXQoKSBnZW5lcmF0ZUNvZGUgPSBuZXcgRXZlbnRFbWl0dGVyKClcbiAgQFZpZXdDaGlsZCgnY2FwdGNoYUNvbnRhaW5lcicpIGNvbnRhaW5lclxuICBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxuICBsZXR0ZXJzID0gW1wiMFwiLCBcIjFcIiwgXCIyXCIsIFwiM1wiLCBcIjRcIiwgXCI1XCIsIFwiNlwiLCBcIjdcIiwgXCI4XCIsIFwiOVwiLCBcImFcIiwgXCJiXCIsIFwiY1wiLCBcImRcIiwgXCJlXCIsIFwiZlwiLCBcImdcIiwgXCJoXCIsIFwiaVwiLCBcImpcIiwgXCJrXCIsIFwibFwiLCBcIm1cIiwgXCJuXCIsIFwib1wiLCBcInBcIiwgXCJxXCIsIFwiclwiLCBcInNcIiwgXCJ0XCIsIFwidVwiLCBcInZcIiwgXCJ3XCIsIFwieFwiLCBcInlcIiwgXCJ6XCIsIFwiQVwiLCBcIkJcIiwgXCJDXCIsIFwiRFwiLCBcIkVcIiwgXCJGXCIsIFwiR1wiLCBcIkhcIiwgXCJJXCIsIFwiSlwiLCBcIktcIiwgXCJMXCIsIFwiTVwiLCBcIk5cIiwgXCJPXCIsIFwiUFwiLCBcIlFcIiwgXCJSXCIsIFwiU1wiLCBcIlRcIiwgXCJVXCIsIFwiVlwiLCBcIldcIiwgXCJYXCIsIFwiWVwiLCBcIlpcIl1cbiAgY29kZSA9ICcnXG5cbiAgY29uc3RydWN0b3IoKSB7IH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmluaXQoKVxuICAgIHRoaXMucmVmcmVzaCgpXG4gIH1cblxuICBvbkNsaWNrKCkge1xuICAgIHRoaXMucmVmcmVzaCgpXG4gIH1cblxuICBwcml2YXRlIGluaXQoKSB7XG4gICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLndpZHRoIHx8IDEwMFxuICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0IHx8IDUwXG4gICAgdGhpcy5jYW52YXMuc3R5bGUuY3Vyc29yID0gJ3BvaW50ZXInXG4gICAgdGhpcy5jYW52YXMuaW5uZXJIVE1MID0gJ+aCqOeahOa1j+iniOWZqOeJiOacrOS4jeaUr+aMgWNhbnZhcydcbiAgICB0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMuY2FudmFzKVxuICB9XG5cbiAgLy8gZ2VuZXJhdGUgY29kZVxuICBwcml2YXRlIHJlZnJlc2goKSB7XG4gICAgdGhpcy5jb2RlID0gJydcbiAgICBjb25zdCBjdHggPSB0aGlzLmNhbnZhcy5nZXRDb250ZXh0KCcyZCcpXG4gICAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnXG4gICAgY3R4LmZpbGxTdHlsZSA9IHRoaXMucmFuZG9tQ29sb3IoMTgwLCAyNDApXG4gICAgY3R4LmZpbGxSZWN0KDAsIDAsIHRoaXMuY2FudmFzLndpZHRoLCB0aGlzLmNhbnZhcy5oZWlnaHQpXG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7IGkrKykge1xuICAgICAgY29uc3QgbGV0dGVyID0gdGhpcy5sZXR0ZXJzW3RoaXMucmFuZG9tTnVtKDAsIHRoaXMubGV0dGVycy5sZW5ndGgpXVxuICAgICAgdGhpcy5jb2RlICs9IGxldHRlclxuICAgICAgY3R4LmZvbnQgPSB0aGlzLnJhbmRvbU51bSh0aGlzLmNhbnZhcy5oZWlnaHQgLyAyLCB0aGlzLmNhbnZhcy5oZWlnaHQpICsgJ3B4IFNpbUhlaSdcbiAgICAgIGN0eC5maWxsU3R5bGUgPSB0aGlzLnJhbmRvbUNvbG9yKDUwLCAxNjApXG4gICAgICBjdHguc2hhZG93T2Zmc2V0WCA9IHRoaXMucmFuZG9tTnVtKC0zLCAzKVxuICAgICAgY3R4LnNoYWRvd09mZnNldFkgPSB0aGlzLnJhbmRvbU51bSgtMywgMylcbiAgICAgIGN0eC5zaGFkb3dCbHVyID0gdGhpcy5yYW5kb21OdW0oLTMsIDMpXG4gICAgICBjdHguc2hhZG93Q29sb3IgPSAncmdiKDAsIDAsIDAsIDAuMyknXG4gICAgICBjb25zdCB4ID0gdGhpcy5jYW52YXMud2lkdGggLyA1ICogaVxuICAgICAgY29uc3QgeSA9IHRoaXMuY2FudmFzLmhlaWdodCAvIDJcbiAgICAgIGNvbnN0IGRlZyA9IHRoaXMucmFuZG9tTnVtKC0zMCwgMzApXG4gICAgICAvLyBzZXR0aW5nIHJvdGF0ZSBhbmQgb3JpZ2luIHBvaW50XG4gICAgICBjdHgudHJhbnNsYXRlKHgsIHkpXG4gICAgICBjdHgucm90YXRlKGRlZyAqIE1hdGguUEkgLyAxODApXG4gICAgICBjdHguZmlsbFRleHQobGV0dGVyLCAwLCAwKVxuICAgICAgLy8gcmVzZXQgcm90YXRlIGFuZCBvcmlnaW4gcG9pbnRcbiAgICAgIGN0eC5yb3RhdGUoLWRlZyAqIE1hdGguUEkgLyAxODApXG4gICAgICBjdHgudHJhbnNsYXRlKC14LCAteSlcbiAgICB9XG5cbiAgICAvLyBkcmF3IGludGVyZmVyaW5nIGxpbmVcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7IGkrKykge1xuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gdGhpcy5yYW5kb21Db2xvcig0MCwgMTgwKVxuICAgICAgY3R4LmJlZ2luUGF0aCgpXG4gICAgICBjdHgubW92ZVRvKHRoaXMucmFuZG9tTnVtKDAsIHRoaXMuY2FudmFzLndpZHRoKSwgdGhpcy5yYW5kb21OdW0oMCwgdGhpcy5jYW52YXMuaGVpZ2h0KSlcbiAgICAgIGN0eC5saW5lVG8odGhpcy5yYW5kb21OdW0oMCwgdGhpcy5jYW52YXMud2lkdGgpLCB0aGlzLnJhbmRvbU51bSgwLCB0aGlzLmNhbnZhcy5oZWlnaHQpKVxuICAgICAgY3R4LnN0cm9rZSgpXG4gICAgfVxuXG4gICAgLy8gZHJhdyBpbnRlcmZlcmluZyBwb2ludFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jYW52YXMud2lkdGggLyA0OyBpKyspIHtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSB0aGlzLnJhbmRvbUNvbG9yKClcbiAgICAgIGN0eC5iZWdpblBhdGgoKVxuICAgICAgY3R4LmFyYyh0aGlzLnJhbmRvbU51bSgwLCB0aGlzLmNhbnZhcy53aWR0aCksIHRoaXMucmFuZG9tTnVtKDAsIHRoaXMuY2FudmFzLmhlaWdodCksIDEsIDAsIDIgKiBNYXRoLlBJKVxuICAgICAgY3R4LmZpbGwoKVxuICAgIH1cblxuICAgIHRoaXMuZ2VuZXJhdGVDb2RlLmVtaXQodGhpcy5jb2RlLnRvTG93ZXJDYXNlKCkpXG4gIH1cblxuICAvKipcbiAgICogcmV0dXJuIGEgcmFuZG9tIGludGVnZXJcbiAgICogQHBhcmFtIG1pbiDmnIDlsI/lgLxcbiAgICogQHBhcmFtIG1heCDmnIDlpKflgLxcbiAgICovXG4gIHByaXZhdGUgcmFuZG9tTnVtKG1pbiwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChtYXggLSBtaW4pICsgbWluKVxuICB9XG5cbiAgLyoqXG4gICAqIHJldHVybiBhIHJhbmRvbSBjb2xvclxuICAgKi9cbiAgcHJpdmF0ZSByYW5kb21Db2xvcihtaW4gPSAwLCBtYXggPSAyNTUpIHtcbiAgICBjb25zdCByID0gdGhpcy5yYW5kb21OdW0obWluLCBtYXgpXG4gICAgY29uc3QgZyA9IHRoaXMucmFuZG9tTnVtKG1pbiwgbWF4KVxuICAgIGNvbnN0IGIgPSB0aGlzLnJhbmRvbU51bShtaW4sIG1heClcbiAgICByZXR1cm4gYHJnYigke3J9LCAke2d9LCAke2J9KWBcbiAgfVxuXG59XG4iXX0=