add and document options for manipulating path

This commit is contained in:
HF 2021-02-03 22:09:06 +01:00
parent e5f5f760d6
commit 8be61c1f7c
6 changed files with 60 additions and 12 deletions

View File

@ -66,6 +66,17 @@ If no option is passed, you will get a random string of four characters and corr
* `stroke`: 'black' // style/color of the svg path stroke
* `fill`: 'black' // style/color of the svg strokes fill
Options that change the variation of the path:
* `nodeDeviation: 0.1
* `truncateLineProbability`: 0.5
* `truncateCurveProbability`: 0.5
* `truncateCurvePositionMin`: 0.4
* `truncateCurvePositionMax`: 0.6
* `connectionPathDeviation` : 10.0
(when using fill, set connectionPathDeviation far lower as it covers parts of the paths and is harder for humans to read - and consider converting it [to PNG](https://morioh.com/p/2a17965187b6) before serving, to stop bots from being able to read those obstructed paths)
This function returns an object that has the following property:
* `data`: string // svg path data
* `text`: string // captcha text

30
index.d.ts vendored
View File

@ -66,6 +66,36 @@ declare class ConfigObject {
* max value of the math expression
*/
mathMax?: number;
/**
* default: 0.5
* changing line probabilities
*/
truncateLineProbability?: number;
/**
* default: 0.5
* changing line probabilities
*/
truncateCurveProbability?: number;
/**
* default: 0.4
* changing line probabilities
*/
truncateCurvePositionMin?: number;
/**
* default: 0.6
* changing line probabilities
*/
truncateCurvePositionMax?: number;
/**
* default: 10.0
* changing line probabilities
*/
connectionPathDeviation?: number;
/**
* default: 0.2
* changing line probabilities
*/
nodeDeviation?: number;
}
/**
* result of captcha generation

View File

@ -53,7 +53,7 @@ const createCaptcha = function (text, options) {
/* Randomize nodes and randomly split them */
path = randomizePath(path, options);
/* Join characters with random lines */
path = randomizePath.removeGaps(path);
path = randomizePath.removeGaps(path, options);
/* Create xml */
const start = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0,0,${width},${height}">`;

View File

@ -21,7 +21,9 @@ const options = {
truncateLineProbability: 0.5,
truncateCurveProbability: 0.5,
truncateCurvePositionMin: 0.4,
truncateCurvePositionMax: 0.6
truncateCurvePositionMax: 0.6,
connectionPathDeviation: 10.0,
nodeDeviation: 0.2,
};
const loadFont = filepath => {

View File

@ -1,8 +1,8 @@
'use strict';
const assert = require('assert');
function rndPathCmd(cmd) {
const r = (Math.random() * 0.2) - 0.1;
function rndPathCmd(cmd, deviation) {
const r = (Math.random() * deviation * 2) - deviation;
switch (cmd.type) {
case 'M':
@ -145,7 +145,7 @@ function randomizePathNodes(commands, opts) {
* @param qDist ratio of curves to lines
* @return array of path commands
*/
function connectPoints(xa, ya, xb, yb, qDist, avgDist) {
function connectPoints(xa, ya, xb, yb, qDist, avgDist, deviation) {
const dist = distance(xa, ya, xb, yb);
const min = avgDist / 15;
const max = avgDist * 4;
@ -155,12 +155,16 @@ function connectPoints(xa, ya, xb, yb, qDist, avgDist) {
const path = [];
while (drawDist < dist) {
const ratio = drawDist / dist;
const x = (xb - xa) * ratio + xa + Math.random() * 10 - 5;
const y = (yb - ya) * ratio + ya + Math.random() * 10 - 5;
const x = (xb - xa) * ratio + xa + Math.random()
* deviation * 2 - deviation;
const y = (yb - ya) * ratio + ya + Math.random()
* deviation * 2 - deviation;
const point = {};
if (Math.random() < qDist) {
const x1 = randomRange(xp, x) + Math.random() * 4 - 2;
const y1 = randomRange(yp, y) + Math.random() * 4 - 2;
const x1 = randomRange(xp, x) + Math.random()
* deviation - deviation / 2;
const y1 = randomRange(yp, y) + Math.random()
* deviation - deviation / 2;
point.type = 'Q';
point.x1 = x1;
point.y1 = y1;
@ -181,7 +185,7 @@ function connectPoints(xa, ya, xb, yb, qDist, avgDist) {
/*
* Removes gaps in path (Z and following M command)
*/
function removeGaps(path) {
function removeGaps(path, options) {
if (!path.commands.length) {
return path;
}
@ -234,6 +238,7 @@ function removeGaps(path) {
prevCommand.x, prevCommand.y,
nextCommand.x, nextCommand.y,
qDist, avgDist,
options.connectionPathDeviation,
);
commands = commands.concat(points);
} else {
@ -247,7 +252,7 @@ function removeGaps(path) {
module.exports = function (path, opts) {
// Randomize path commands
path.commands.forEach(rndPathCmd);
path.commands.forEach((c) => rndPathCmd(c, opts.nodeDeviation));
path.commands = randomizePathNodes(path.commands, opts);
return path;
};

View File

@ -1,6 +1,6 @@
{
"name": "ppfun-captcha",
"version": "1.6.1",
"version": "1.6.2",
"description": "Generate single-path svg captcha in node.js or express.js",
"main": "index.js",
"scripts": {