add and document options for manipulating path
This commit is contained in:
parent
e5f5f760d6
commit
8be61c1f7c
11
README.md
11
README.md
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}">`;
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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": {
|
||||
|
|
Loading…
Reference in New Issue