UNPKG

ng-captcha

Version:

A pure front-end angular captcha module.

161 lines (155 loc) 17.1 kB
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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