• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
2

How to generate a curved line or closed shape via javascript?

Contributor ,
Feb 01, 2024 Feb 01, 2024

Copy link to clipboard

Copied

Greetings, I'm trying to generate a specific curved closed shape (it's not a perfect circle) based on the shape data that I copied and pasted into a text file. Ideally I would like to subtract this shape from a rectangle/square as shown in the screenshot 2, but I can't chatGPT to generate the correct code just to draw the shape below shown in Screenshot 1.

 

Any help on this problem is much appreciated 🙂

 

I just get this error in illustrator and ChatGPT and keeps generating the same error after it has given me a "revised" version that should work.

Error 24: pathArray[i].substr().split().map is not a function

Line: 38

 

 

    var values = pathArray[i].substr(1).split(/[ ,]+/).map(parseFloat);

 

 

when running the full ChatGPT code below

 

Screenshot 1 from illustrator showing shaped to be subtracted

shape.jpg

Shape data from right clicking on the shape/object above copying and then pasting into a text file:

 

 

<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 446.92 416.26"><defs><style>.cls-1{fill:#ed160a;stroke-width:0px;}</style></defs><path class="cls-1" d="M27.55,240.35c4.53-13.12,9.69-26.03,15.52-38.64,5.59-12.1,11.81-23.91,18.69-35.32,6.59-10.91,13.79-21.44,21.6-31.52,7.46-9.62,15.48-18.82,24.11-27.41,8.79-8.74,18.21-16.85,28.13-24.29,10.57-7.94,21.69-15.12,33.19-21.65,12.26-6.95,24.94-13.15,37.9-18.68,13.77-5.87,27.85-10.99,42.13-15.46,15.07-4.71,30.37-8.71,45.8-12.07,16.14-3.51,32.42-6.34,48.79-8.57,34.29-4.68,68.92-6.74,103.53-6.74H0v416.26c0-30.43,2.14-60.86,6.79-90.94,4.46-28.86,11.23-57.38,20.76-84.98Z"/></svg>

 

 

 

Screenshot 2 from illustrator showing the intened composite shape result

shape2.jpg

 

 

ChatGPT generated code for only making the curved shape from screenshot 1

 

 

// Create a new document with a 24" x 24" artboard
var doc = app.documents.add(DocumentColorSpace.CMYK);
var artboard = doc.artboards[0];
artboard.artboardRect = [0, 0, 24 * 72, -24 * 72]; // 24 inches converted to points

// Create a new layer
var layer = doc.layers.add();
layer.name = "CurvedCorners";

// Add the curved shape at position x, y = 0, 0
var curvedPathData = "M27.55,240.35c4.53-13.12,9.69-26.03,15.52-38.64,5.59-12.10,11.81-23.91,18.69-35.32,6.59-10.91,13.79-21.44,21.60-31.52,7.46-9.62,15.48-18.82,24.11-27.41,8.79-8.74,18.21-16.85,28.13-24.29,10.57-7.94,21.69-15.12,33.19-21.65,12.26-6.95,24.94-13.15,37.90-18.68,13.77-5.87,27.85-10.99,42.13-15.46,15.07-4.71,30.37-8.71,45.80-12.07,16.14-3.51,32.42-6.34,48.79-8.57,34.29-4.68,68.92-6.74,103.53-6.74H0v416.26c0-30.43,2.14-60.86,6.79-90.94,4.46-28.86,11.23-57.38,20.76-84.98Z";
var curvedShape = layer.pathItems.add();
curvedShape.setEntirePath(createPathFromData(curvedPathData));
curvedShape.stroked = false;
curvedShape.filled = true;
curvedShape.fillColor = spotColor; // Assuming you have spotColor defined

// Center the curved shape on the artboard
var centerX = (artboard.artboardRect[2] + artboard.artboardRect[0]) / 2;
var centerY = (artboard.artboardRect[1] + artboard.artboardRect[3]) / 2;
var xOffset = centerX - (curvedShape.width / 2);
var yOffset = centerY - (curvedShape.height / 2);
curvedShape.position = [xOffset, yOffset];

/**
 * Function to create a path from SVG path data
 *  {string} pathData - SVG path data
 *  {Array} - Path points array
 */
function createPathFromData(pathData) {
  var pathPoints = [];
  var pathArray = pathData.match(/[A-Za-z][^A-Za-z]*/g);

  for (var i = 0; i < pathArray.length; i++) {
    var command = pathArray[i].charAt(0);
    var values = pathArray[i].substr(1).split(/[ ,]+/).map(parseFloat);

    if (command === "M") {
      pathPoints.push({ anchor: [values[0], values[1]], type: PathPointType.CORNER });
    } else if (command === "C") {
      pathPoints.push({ anchor: [values[4], values[5]], leftDirection: [values[0], values[1]], rightDirection: [values[2], values[3]], type: PathPointType.SMOOTH });
    }
  }

  return pathPoints;
}

 

 

 

TOPICS
Draw and design , How-to , Scripting

Views

456

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
Feb 01, 2024 Feb 01, 2024

Copy link to clipboard

Copied

Hi @TestriteVisual, just to be clear, can you confirm that you are trying to write a SVG path data parser? For example to convert this:

 

 

<path
d="M0,0c73.488,0,100,29.651,100,100l-89.4-9.5-.6,59.5c30.083,0,24.367,30,70,30"
style="fill:#fff; stroke:#1d1d1b; stroke-miterlimit:10;" />

 

 

into an Illustrator pathItem?

 

If that is not correct please clarify what you are doing.

 

Some notes:

1. Your error occurs because the script uses Javascript ES6 .map method of Array that Extendscript doesn't have. Convert this to a "for" loop. You can try asking ChatGPT to do this for you.

 

2. parsing a svg path data string is significantly more involved than your sample script attempts to handle, for example "l" denotes *one or more* straight lines segments and that coordinates are relative to the previous point (Illustrator pathPoint values are relative to artboard or document origin.) Also you have to handle "v" (vertical line) and all the other symbols that svg uses.

 

3. The script attempts to use PathItem.setEntirePath() giving an array of fake (but fully specified) PathPoints, but setEntirePath method only creates pathItems with straight line segments and only accepts an array of points [x, y]. The only way I know to make the pathItem is something like this:

 

 

var myPathItem = doc.pathItems.add();
var p = myPathItem.pathPoints.add();
p.anchor = [0, 0];
p.leftDirection = [10, 10];
p.rightDirection = [10, -10];
p.pointType = PointType.SMOOTH;

 

 

 

Sorry it isn't a simple fix, but I hope that will get you pointed in a better direction.

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 01, 2024 Feb 01, 2024

Copy link to clipboard

Copied

I realise that you may not be interested in an actual SVG parser (I still don't know exactly why you need to input SVG string rather than just drawing the shape you want using Illustrator-style path data) but, for my own interest, I had a quick look at what's involved in parsing an SVG path data string and it seems that we can get a long way without too much effort—meaning that a very incomplete script can still handle many real-world examples.

 

So I've written this script that takes the svg path data string and creates a path item:

 

/**
 * Starting point for a simple SVG path data string parser
 * and converter to Illustrator path item.
 * eg. <path d="M200,0c57.3,0,100-.883,100,100s-56.589,104.282-75,100" />
 * @author m1b
 * @discussion https://community.adobe.com/t5/illustrator-discussions/how-to-generate-a-curved-line-or-closed-shape-via-javascript/m-p/14394430
 */
(function () {

    var doc = app.activeDocument;

    var testData1 = "M27.55,240.35c4.53-13.12,9.69-26.03,15.52-38.64,5.59-12.10,11.81-23.91,18.69-35.32,6.59-10.91,13.79-21.44,21.60-31.52,7.46-9.62,15.48-18.82,24.11-27.41,8.79-8.74,18.21-16.85,28.13-24.29,10.57-7.94,21.69-15.12,33.19-21.65,12.26-6.95,24.94-13.15,37.90-18.68,13.77-5.87,27.85-10.99,42.13-15.46,15.07-4.71,30.37-8.71,45.80-12.07,16.14-3.51,32.42-6.34,48.79-8.57,34.29-4.68,68.92-6.74,103.53-6.74H0v416.26c0-30.43,2.14-60.86,6.79-90.94,4.46-28.86,11.23-57.38,20.76-84.98Z";
    var testData2 = "M0,0c73.488,0,100,29.651,100,100l-89.4-9.5-.6,59.5c30.083,0,24.367,30,70,30";
    var testData3 = "M200,0c57.3,0,100-.883,100,100s-56.589,104.282-75,100c-215-50-29.536-110.551,0-110.551v46.035h117.828l13.587-24.81-28.355-20.674,28.355-20.086-17.131-40.76";

    var item1 = pathItemFromSVGData(doc, testData1);
    var item2 = pathItemFromSVGData(doc, testData2);
    var item3 = pathItemFromSVGData(doc, testData3);

})();


/**
 * Draws and returns an Illustrator PathItem created
 * using an SVG path element's data string.
 * NOTE: this function is a stub, and does not handle
 * many possibilities, eg. C and S symbols do not currently
 * calculate the `mirror` direction point, but it must.
 * @author m1b
 * @version 2024-02-08
 * @param {Document|Layer|GroupItem} container - the container for the new path item, a DOM object.
 * @param {String} svgPathDataString - an SVG path element's data string, eg. "M200,0c57.3,0,100-.883,100,100s-56.589,104.282-75,100".
 * @returns {PathItem}
 */
function pathItemFromSVGData(container, svgPathDataString) {

    // create the path item
    var item = container.pathItems.add();

    // parse the svg string
    var data = parseSVGPathDataString(svgPathDataString);

    var d, // the data for one svg command
        val, // the values for the command
        c, // sub-value(s)
        pos, // the most-recent position [x, y]
        p, // the most-recently created point (we don't need this but might want it for something)
        mirror; // the mirrored counterpart of a direction point

    while (d = data.shift()) {

        val = d.values;

        switch (d.symbol) {

            case 'M': // absolute move to
                pos = val[0];
                break;

            case 'm': // relative move to
                pos = rel(val[0]);
                break;

            case 'L': // absolute line to
                while (c = val.shift()) {
                    pos = c;
                    p = addPoint(item, pos);
                }
                break;

            case 'l': // relative line to
                while (c = val.shift()) {
                    pos = rel(c);
                    p = addPoint(item, pos);
                }
                break;

            case 'C': // absolute bezier curve
                while (val.length && (c = val.splice(0, 3))) {
                    if (p) {
                        p.rightDirection = c[0];
                        p.pointType = PointType.SMOOTH;
                    }
                    else {
                        addPoint(item, pos, undefined, c[0], PointType.CORNER);
                    }
                    p = addPoint(item, c[2], c[1], undefined, PointType.CORNER);
                    pos = c[2];
                }
                break;

            case 'c': // relative bezier curve
                while (val.length && (c = val.splice(0, 3))) {
                    if (p) {
                        p.rightDirection = rel(c[0]);
                        p.pointType = PointType.SMOOTH;
                    }
                    else {
                        addPoint(item, pos, undefined, rel(c[0]), PointType.CORNER);
                    }
                    p = addPoint(item, rel(c[2]), rel(c[1]), undefined, PointType.CORNER);
                    pos = rel(c[2]);
                    mirror = rel([-c[1][1], -c[1][0]]);
                }
                break;

            case 'S': // absolute smooth bezier curve
                while (val.length && (c = val.splice(0, 2))) {
                    if (p) {
                        p.rightDirection = mirror;
                        p.pointType = PointType.SMOOTH;
                    }
                    else {
                        addPoint(item, pos, undefined, mirror, PointType.SMOOTH);
                    }
                    p = addPoint(item, c[1], c[0], undefined, PointType.SMOOTH);
                    pos = c[1];
                    mirror = [-c[0][1], -c[0][0]];
                }
                break;

            case 's': // relative smooth bezier curve
                while (val.length && (c = val.splice(0, 2))) {
                    if (p) {
                        p.rightDirection = mirror;
                        p.pointType = PointType.SMOOTH;
                    }
                    else {
                        addPoint(item, pos, undefined, mirror, PointType.SMOOTH);
                    }
                    p = addPoint(item, rel(c[1]), rel(c[0]), undefined, PointType.SMOOTH);
                    pos = rel(c[1]);
                    mirror = rel([-c[0][1], -c[0][0]]);
                }
                break;

            case 'H': // absolute horizontal line
                while (undefined !== (c = val.shift())) {
                    pos[0] = c;
                    p = addPoint(item, pos);
                }
                break;

            case 'h': // relative horizontal line
                while (undefined !== (c = val.shift())) {
                    pos[0] += c;
                    p = addPoint(item, pos);
                }
                break;

            case 'V': // absolute vertical line
                while (undefined !== (c = val.shift())) {
                    pos[1] = c;
                    p = addPoint(item, pos);
                }
                break;

            case 'v': // relative vertical line
                while (undefined !== (c = val.shift())) {
                    pos[1] += c;
                    p = addPoint(item, pos);
                }
                break;

            case 'Q': // absolute quadratic Bézier curve
                break;

            case 'q': // relative quadratic Bézier curve
                break;

            case 'T': // absolute smooth quadratic Bézier curve
                break;

            case 't': // relative smooth quadratic Bézier curve
                break;

            case 'A': // absolute elliptical arc
                break;

            case 'a': // relative elliptical arc
                break;

            case 'Z': // close path
                item.closed = true;
                break;

            default:
                throw Error('pathItemFromSVGData: unknown symbol "' + d.symbol + '"');

        }

    }

    return item;

    /**
     * Return `point` offset by `pos`.
     * @param {point} point - [x,y]
     * @returns {point}
     */
    function rel(point) { return [pos[0] + point[0], pos[1] + point[1]]; };

};


/**
 * Adds a PathPoint to a PathItem.
 * @author m1b
 * @version 2024-02-02
 * @param {PathItem} item - the pathItem to add the point to.
 * @param {point} anchor - a point [x, y].
 * @param {point} [leftDirection] - a point [x, y] (default: copy of anchor point).
 * @param {point} [rightDirection] - a point [x, y] (default: copy of anchor point).
 * @param {PointType} [pointType] - an Illustrator PointType (default: PointType.CORNER).
 * @returns {PathPoint}
 */
function addPoint(item, anchor, leftDirection, rightDirection, pointType) {

    var p = item.pathPoints.add();
    p.anchor = anchor;
    p.leftDirection = leftDirection || anchor;
    p.rightDirection = rightDirection || anchor;
    p.pointType = pointType || PointType.CORNER;

    return p;

};

/**
 * Returns an array of data for each command
 * parsed from the given `svgPathDataString`.
 *
 * For example:
 *   "M200,0c57.3,0,100-.883,100,100Z"
 * Returns:
 *   [
 *     { symbol: "M", values: [[200, 0]] },
 *     { symbol: "c", values: [[57.3, 0], [100, 0.883], [100, -100]] },
 *     { symbol: "Z" }
 *   ]
 *
 * NOTE: because Illustrator, we flip the sign on Y axis coordinates.
 * @author m1b
 * @version 2024-02-02
 * @param {String} svgPathDataString - an SVG path element's data string, eg. "M200,0c57.3,0,100-.883,100,100s-56.589,104.282-75,100".
 * @returns {Array<Object>} - array of {symbol: values: }.
 */
function parseSVGPathDataString(svgPathDataString) {

    var commands = [],
        symbolMatcher = /([MmLlHhVvCcSsQqTtAaZ])([^MmLlHhVvCcSsQqTtAaZ]*)/g,
        minus = /(.)-/g,
        command,
        values,
        symbol,
        len,
        match;

    while (match = symbolMatcher.exec(svgPathDataString)) {

        symbol = match[1];
        command = { symbol: symbol };
        command.values = [];
        commands.push(command);

        if (0 === match[2].length)
            continue;

        // parse the coordinate values
        values = match[2].replace(minus, '$1,-').split(',');

        // has single numbers, not arrays
        var hasSingleNumbers = (-1 !== 'vhVH'.search(symbol));

        // add the values
        while (len = values.length) {
            if (hasSingleNumbers) {
                if ('v' === symbol.toLowerCase())
                    command.values.push(-Number(values.shift()));
                else
                    command.values.push(Number(values.shift()));
            }
            else
                command.values.push([Number(values.shift()), -Number(values.shift())]);
        }

    }

    return commands;

};

 

Edit 2024-02-08: fixed bug mentioned by @renél80416020 where I was adding extra points on curves.

 

My test data strings create these: (testData1 is yours @TestriteVisual).

Screenshot 2024-02-02 at 13.11.37.png

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Feb 05, 2024 Feb 05, 2024

Copy link to clipboard

Copied

Hi thanks for the reply, I'm not a programmer so just cutting/pasting snippets that i can get to work and generating code using ChatGPT are my only methods, so I'm completely open to whatever may be the easiest/simplest way to generate this exact curve using a script. I ran a shorter version of the the code you provided just to generate the curve shape, in a new open document and it ran fine on my end. Just want to confirm, do I need this entire code to be able to generate this exact curve? If possible, would you be able to let me know how I can have the script mirror the curve shape, so that I could end up with a composite shape like shown below? Thanks again 

This is the shape at the bottom I'm trying to create by subtracting to identical left/fright curves from a rectangle

1.jpg

 

Shorter version for just the curve shape

 

/**
 * Starting point for a simple SVG path data string parser
 * and converter to Illustrator path item.
 * eg. <path d="M200,0c57.3,0,100-.883,100,100s-56.589,104.282-75,100" />
 *  m1b
 * @discussion https://community.adobe.com/t5/illustrator-discussions/how-to-generate-a-curved-line-or-closed-shape-via-javascript/m-p/14394430
 */
(function () {

    var doc = app.activeDocument;

    var testData1 = "M27.55,240.35c4.53-13.12,9.69-26.03,15.52-38.64,5.59-12.10,11.81-23.91,18.69-35.32,6.59-10.91,13.79-21.44,21.60-31.52,7.46-9.62,15.48-18.82,24.11-27.41,8.79-8.74,18.21-16.85,28.13-24.29,10.57-7.94,21.69-15.12,33.19-21.65,12.26-6.95,24.94-13.15,37.90-18.68,13.77-5.87,27.85-10.99,42.13-15.46,15.07-4.71,30.37-8.71,45.80-12.07,16.14-3.51,32.42-6.34,48.79-8.57,34.29-4.68,68.92-6.74,103.53-6.74H0v416.26c0-30.43,2.14-60.86,6.79-90.94,4.46-28.86,11.23-57.38,20.76-84.98Z";

    var item1 = pathItemFromSVGData(doc, testData1);

})();


/**
 * Draws and returns an Illustrator PathItem created
 * using an SVG path element's data string.
 * NOTE: this function is a stub, and does not handle
 * many possibilities, eg. C and S symbols do not currently
 * calculate the `mirror` direction point, but it must.
 *  m1b
 *  2024-02-02
 *  {Document|Layer|GroupItem} container - the container for the new path item, a DOM object.
 *  {String} svgPathDataString - an SVG path element's data string, eg. "M200,0c57.3,0,100-.883,100,100s-56.589,104.282-75,100".
 *  {PathItem}
 */
function pathItemFromSVGData(container, svgPathDataString) {

    // create the path item
    var item = container.pathItems.add();

    // parse the svg string
    var data = parseSVGPathDataString(svgPathDataString);

    var d, // the data for one svg command
        val, // the values for the command
        c, // sub-value(s)
        pos, // the most-recent position [x, y]
        p, // the most-recently created point (we don't need this but might want it for something)
        mirror; // the mirrored counterpart of a direction point

    while (d = data.shift()) {

        val = d.values;

        switch (d.symbol) {

            case 'M': // absolute move to
                pos = val[0];
                break;

            case 'm': // relative move to
                pos = rel(val[0]);
                break;

            case 'L': // absolute line to
                while (c = val.shift()) {
                    pos = c;
                    p = addPoint(item, pos);
                }
                break;

            case 'l': // relative line to
                while (c = val.shift()) {
                    pos = rel(c);
                    p = addPoint(item, pos);
                }
                break;

            case 'C': // absolute bezier curve
                while (val.length && (c = val.splice(0, 3))) {
                    addPoint(item, pos, undefined, c[0], PointType.CORNER);
                    p = addPoint(item, c[2], c[1], undefined, PointType.CORNER);
                    pos = c[2];
                }
                break;

            case 'c': // relative bezier curve
                while (val.length && (c = val.splice(0, 3))) {
                    addPoint(item, pos, undefined, rel(c[0]), PointType.CORNER);
                    p = addPoint(item, rel(c[2]), rel(c[1]), undefined, PointType.CORNER);
                    pos = rel(c[2]);
                    mirror = rel([-c[1][1], -c[1][0]]);
                }
                break;

            case 'S': // absolute smooth bezier curve
                while (val.length && (c = val.splice(0, 2))) {
                    addPoint(item, pos, undefined, mirror, PointType.SMOOTH);
                    p = addPoint(item, rel(c[1]), rel(c[0]), undefined, PointType.SMOOTH);
                    pos = c[1];
                }
                break;

            case 's': // relative smooth bezier curve
                while (val.length && (c = val.splice(0, 2))) {
                    addPoint(item, pos, undefined, mirror, PointType.SMOOTH);
                    p = addPoint(item, rel(c[1]), rel(c[0]), undefined, PointType.SMOOTH);
                    pos = rel(c[1]);
                    mirror = rel([-c[0][1], -c[0][0]]);
                }
                break;

            case 'H': // absolute horizontal line
                while (undefined !== (c = val.shift())) {
                    pos[0] = c;
                    p = addPoint(item, pos);
                }
                break;

            case 'h': // relative horizontal line
                while (undefined !== (c = val.shift())) {
                    pos[0] += c;
                    p = addPoint(item, pos);
                }
                break;

            case 'V': // absolute vertical line
                while (undefined !== (c = val.shift())) {
                    pos[1] = c;
                    p = addPoint(item, pos);
                }
                break;

            case 'v': // relative vertical line
                while (undefined !== (c = val.shift())) {
                    pos[1] += c;
                    p = addPoint(item, pos);
                }
                break;

            case 'Q': // absolute quadratic Bézier curve
                break;

            case 'q': // relative quadratic Bézier curve
                break;

            case 'T': // absolute smooth quadratic Bézier curve
                break;

            case 't': // relative smooth quadratic Bézier curve
                break;

            case 'A': // absolute elliptical arc
                break;

            case 'a': // relative elliptical arc
                break;

            case 'Z': // close path
                item.closed = true;
                break;

            default:
                throw Error('pathItemFromSVGData: unknown symbol "' + d.symbol + '"');

        }

    }

    return item;

    /**
     * Return `point` offset by `pos`.
     *  {point} point - [x,y]
     *  {point}
     */
    function rel(point) { return [pos[0] + point[0], pos[1] + point[1]]; };

};


/**
 * Adds a PathPoint to a PathItem.
 *  m1b
 *  2024-02-02
 *  {PathItem} item - the pathItem to add the point to.
 *  {point} anchor - a point [x, y].
 *  {point} [leftDirection] - a point [x, y] (default: copy of anchor point).
 *  {point} [rightDirection] - a point [x, y] (default: copy of anchor point).
 *  {PointType} [pointType] - an Illustrator PointType (default: PointType.CORNER).
 *  {PathPoint}
 */
function addPoint(item, anchor, leftDirection, rightDirection, pointType) {

    var p = item.pathPoints.add();
    p.anchor = anchor;
    p.leftDirection = leftDirection || anchor;
    p.rightDirection = rightDirection || anchor;
    p.pointType = pointType || PointType.CORNER;

    return p;

};

/**
 * Returns an array of data for each command
 * parsed from the given `svgPathDataString`.
 * 
 * For example:
 *   "M200,0c57.3,0,100-.883,100,100Z"
 * Returns:
 *   [
 *     { symbol: "M", values: [[200, 0]] },
 *     { symbol: "c", values: [[57.3, 0], [100, 0.883], [100, -100]] },
 *     { symbol: "Z" }
 *   ]
 * 
 * NOTE: because Illustrator, we flip the sign on Y axis coordinates.
 *  m1b
 *  2024-02-02
 *  {String} svgPathDataString - an SVG path element's data string, eg. "M200,0c57.3,0,100-.883,100,100s-56.589,104.282-75,100".
 *  {Array<Object>} - array of {symbol: values: }.
 */
function parseSVGPathDataString(svgPathDataString) {

    var commands = [],
        symbolMatcher = /([MmLlHhVvCcSsQqTtAaZ])([^MmLlHhVvCcSsQqTtAaZ]*)/g,
        minus = /(.)-/g,
        command,
        values,
        symbol,
        len,
        match;

    while (match = symbolMatcher.exec(svgPathDataString)) {

        symbol = match[1];
        command = { symbol: symbol };
        command.values = [];
        commands.push(command);

        if (0 === match[2].length)
            continue;

        // parse the coordinate values
        values = match[2].replace(minus, '$1,-').split(',');

        // has single numbers, not arrays
        var hasSingleNumbers = (-1 !== 'vhVH'.search(symbol));

        // add the values
        while (len = values.length) {
            if (hasSingleNumbers) {
                if ('v' === symbol.toLowerCase())
                    command.values.push(-Number(values.shift()));
                else
                    command.values.push(Number(values.shift()));
            }
            else
                command.values.push([Number(values.shift()), -Number(values.shift())]);
        }

    }

    return commands;

};

 

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 07, 2024 Feb 07, 2024

Copy link to clipboard

Copied

Bonjour, pouquoi voulez vous créer cette courbe par script, alors qu'on peut ouvrir le SVG et utiliser Pathfinder soustraction?

toto.png

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 07, 2024 Feb 07, 2024

Copy link to clipboard

Copied

LATEST

Hi @TestriteVisual, yes you need all the functions to make this work. Also see updated script where I fixed a bug that René noticed.

 

But, like @renél80416020, I'm confused about what you are actually doing. If you want to go deeper here, please explain in detail your starting conditions and what you are trying to do. Why do you talk about path finder? Why not just draw the path(s) you want? And what does SVG have to do with it? Why not draw paths normally using pathItems.add and pathPoints.add? It is hard to give sensible answers when we have no idea of what you are doing and why you choose a difficult way.

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 07, 2024 Feb 07, 2024

Copy link to clipboard

Copied

Bonjour Mark

Juste une remarque, sur la courbe les points sont doubles...

René

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 07, 2024 Feb 07, 2024

Copy link to clipboard

Copied

@renél80416020 You are right, René! I've fixed the bug and edited the script above. - Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines