index.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. 'use strict';
  2. const chToPath = require('./ch-to-path');
  3. const random = require('./random');
  4. const optionMngr = require('./option-manager');
  5. const opts = optionMngr.options;
  6. const getLineNoise = function (width, height, options) {
  7. const hasColor = options.color;
  8. const noiseLines = [];
  9. const min = options.inverse ? 7 : 1;
  10. const max = options.inverse ? 15 : 9;
  11. let i = -1;
  12. while (++i < options.noise) {
  13. const start = `${random.int(1, 21)} ${random.int(1, height - 1)}`;
  14. const end = `${random.int(width - 21, width - 1)} ${random.int(1, height - 1)}`;
  15. const mid1 = `${random.int((width / 2) - 21, (width / 2) + 21)} ${random.int(1, height - 1)}`;
  16. const mid2 = `${random.int((width / 2) - 21, (width / 2) + 21)} ${random.int(1, height - 1)}`;
  17. const color = hasColor ? random.color() : random.greyColor(min, max);
  18. noiseLines.push(`<path d="M${start} C${mid1},${mid2},${end}" stroke="${color}" fill="none"/>`);
  19. }
  20. return noiseLines;
  21. };
  22. const getText = function (text, width, height, options) {
  23. const len = text.length;
  24. const spacing = (width - 2) / (len + 1);
  25. const min = options.inverse ? 10 : 0;
  26. const max = options.inverse ? 14 : 4;
  27. let i = -1;
  28. const out = [];
  29. while (++i < len) {
  30. const x = spacing * (i + 1);
  31. const y = height / 2;
  32. const charPath = chToPath(text[i], Object.assign({x, y}, options));
  33. const color = options.color ?
  34. random.color(options.background) : random.greyColor(min, max);
  35. out.push(`<path fill="${color}" d="${charPath}"/>`);
  36. }
  37. return out;
  38. };
  39. const createCaptcha = function (text, options) {
  40. text = text || random.captchaText();
  41. options = Object.assign({}, opts, options);
  42. const width = options.width;
  43. const height = options.height;
  44. const bg = options.background;
  45. if (bg) {
  46. options.color = true;
  47. }
  48. const bgRect = bg ?
  49. `<rect width="100%" height="100%" fill="${bg}"/>` : '';
  50. const paths =
  51. [].concat(getLineNoise(width, height, options))
  52. .concat(getText(text, width, height, options))
  53. .sort(() => Math.random() - 0.5)
  54. .join('');
  55. const start = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0,0,${width},${height}">`;
  56. const xml = `${start}${bgRect}${paths}</svg>`;
  57. return xml;
  58. };
  59. const create = function (options) {
  60. const text = random.captchaText(options);
  61. const data = createCaptcha(text, options);
  62. return {text, data};
  63. };
  64. const createMathExpr = function (options) {
  65. const expr = random.mathExpr(options.mathMin, options.mathMax, options.mathOperator);
  66. const text = expr.text;
  67. const data = createCaptcha(expr.equation, options);
  68. return {text, data};
  69. };
  70. module.exports = createCaptcha;
  71. module.exports.randomText = random.captchaText;
  72. module.exports.create = create;
  73. module.exports.createMathExpr = createMathExpr;
  74. module.exports.options = opts;
  75. module.exports.loadFont = optionMngr.loadFont;