Skip to main content
Known Participant
October 23, 2024
Answered

How to generate SVG string using extendsript?

  • October 23, 2024
  • 1 reply
  • 407 views

Hi,

 

I try to generate svg string using extendscript everything is working properly except flip.

 

My code

var doc = app.activeDocument;
// Get the current selection in Illustrator
var selectedItems = doc.selection;//[0];

// Check if a path item is selected and convert it to an SVG path string
if (selectedItems.length > 0) {
    //var selectedItem = app.activeDocument.selection[0];
	// Loop through each item in the selection
    for (var i = 0; i < selectedItems.length; i++) {
        var item = selectedItems[i];//alert(item.typename);	
		
		if (item.typename === 'CompoundPathItem' || item.typename === "PathItem" || item.typename === "GroupItem") {
			var svgString = compoundOrGroupItemToSVG(item);
			alert(svgString);  // Output the generated SVG string
		} else {
			alert("Please select a PathItem.");
		}
	}
} else {
    alert("No item selected.");
}

function applyTransform(pathItem, point) {
    if (!point || point.length < 2) {
        alert("Invalid point: " + point);
        return point; // Return the original point if transformation cannot be applied
    }
	var artboardHeight = getArtboardHeight();alert(artboardHeight);
    var matrix = pathItem.matrix;

    // If matrix is undefined, fallback to untransformed coordinates
    if (!matrix) {
        //alert("Matrix is undefined for pathItem. Using untransformed coordinates.");
		return point;
		return [point[0], artboardHeight - point[1]];
    }

    // Apply the transformation matrix
    var newX = (matrix.mValueA * point[0]) + (matrix.mValueC * point[1]) + matrix.mValueTX;
    var newY = (matrix.mValueB * point[0]) + (matrix.mValueD * point[1]) + matrix.mValueTY;
	
	// Invert the y-axis to match SVG coordinate system (flip vertically)
    //newY = -newY;
	// Flip the y-axis
    newY = artboardHeight - newY;
        return [newX, newY];
}

// Recursive function to handle GroupItems and apply transformations
function compoundOrGroupItemToSVG(item) {
    var svgString = '';

    alert("Item Type: " + item.typename);

    if (item.typename === 'GroupItem') {
        // For GroupItems, recursively process each child item
        for (var i = 0; i < item.pageItems.length; i++) {
            svgString += compoundOrGroupItemToSVG(item.pageItems[i]) + ' ';
        }
    } else if (item.typename === 'CompoundPathItem') {
        for (var i = 0; i < item.pathItems.length; i++) {
            svgString += pathItemToSVG(item.pathItems[i]) + ' ';
        }
    } else if (item.typename === 'PathItem') {
        svgString = pathItemToSVG(item);
    } else {
        throw new Error("Unsupported item type. Please select a valid PathItem, CompoundPathItem, or GroupItem.");
    }

    return svgString.replace(/^\s+|\s+$/g, '');
}

// Function to handle PathItems, including applying transformations
function pathItemToSVG(pathItem) {
    if (!pathItem || !pathItem.pathPoints) {
        alert("Invalid PathItem or no path points found.");
        return '';
    }

    var svgString = '';
    alert("Path Points Length: " + pathItem.pathPoints.length);

    for (var i = 0; i < pathItem.pathPoints.length; i++) {
        var point = pathItem.pathPoints[i];
        var anchor = applyTransform(pathItem, point.anchor);  // Apply transformations to the anchor
        var leftDirection = applyTransform(pathItem, point.leftDirection);  // Transform leftDirection
        var rightDirection = applyTransform(pathItem, point.rightDirection);  // Transform rightDirection

        if (i === 0) {
            svgString += 'M ' + anchor[0] + ' ' + anchor[1] + ' ';
        } else {
            var prevPoint = pathItem.pathPoints[i - 1];
            var prevRightDirection = applyTransform(pathItem, prevPoint.rightDirection);
            var prevAnchor = applyTransform(pathItem, prevPoint.anchor);

            var isPrevCurve = !arePointsEqual(prevRightDirection, prevAnchor);
            var isCurrentCurve = !arePointsEqual(leftDirection, anchor);

            if (isPrevCurve || isCurrentCurve) {
                svgString += 'C ' + prevRightDirection[0] + ' ' + prevRightDirection[1] + ', ' +
                    leftDirection[0] + ' ' + leftDirection[1] + ', ' +
                    anchor[0] + ' ' + anchor[1] + ' ';
            } else {
                svgString += 'L ' + anchor[0] + ' ' + anchor[1] + ' ';
            }
        }
    }

    if (pathItem.closed) {
        var lastPoint = pathItem.pathPoints[pathItem.pathPoints.length - 1];
        var firstPoint = pathItem.pathPoints[0];

        var lastRightDirection = applyTransform(pathItem, lastPoint.rightDirection);
        var firstLeftDirection = applyTransform(pathItem, firstPoint.leftDirection);

        if (!arePointsEqual(lastRightDirection, lastPoint.anchor) || !arePointsEqual(firstLeftDirection, firstPoint.anchor)) {
            svgString += 'C ' + lastRightDirection[0] + ' ' + lastRightDirection[1] + ', ' +
                firstLeftDirection[0] + ' ' + firstLeftDirection[1] + ', ' +
                firstPoint.anchor[0] + ' ' + firstPoint.anchor[1] + ' ';
        } else {
            svgString += 'L ' + firstPoint.anchor[0] + ' ' + firstPoint.anchor[1] + ' ';
        }

        svgString += 'Z'; // Close the path
    }

    return svgString.replace(/^\s+|\s+$/g, '');
}

// Function to check if two points are equal
function arePointsEqual(p1, p2) {
    return Math.round(p1[0]) === Math.round(p2[0]) && Math.round(p1[1]) === Math.round(p2[1]);
}

// Get artboard height (required to flip y-axis correctly)
function getArtboardHeight() {
    var doc = app.activeDocument;
    var artboard = doc.artboards[doc.artboards.getActiveArtboardIndex()];
    var artboardRect = artboard.artboardRect;
    return artboardRect[1] - artboardRect[3]; // Top - Bottom gives height
}

in ai file

 

After generate the svg string. it shows like this.

 

 

M 36.5816654535147 -14.3002793939668 L 41.7569670791854 -24.7865985150902 L 53.3293037524545 -26.4681631279418 L 44.9554777737085 -34.6306182796943 L 46.9322634877535 -46.1561965240799 L 36.5816527913412 -40.7145521183866 L 26.2310368778262 -46.1561866005604 L 28.2078336418708 -34.630610251399 L 19.8340154887783 -26.4681470713513 L 31.4063537742213 -24.78659355333 L 36.5816654535147 -14.3002793939668 Z

 

Please advice on this

This topic has been closed for replies.
Correct answer m1b

Hi @Arunkumar25715058ufpl, try changing this part:

// If matrix is undefined, fallback to untransformed coordinates
if (!matrix) {
    //$.writeln("Matrix is undefined for pathItem. Using untransformed coordinates.");
    return [point[0],-point[1]];
}

- Mark

1 reply

m1b
Community Expert
m1bCommunity ExpertCorrect answer
Community Expert
October 26, 2024

Hi @Arunkumar25715058ufpl, try changing this part:

// If matrix is undefined, fallback to untransformed coordinates
if (!matrix) {
    //$.writeln("Matrix is undefined for pathItem. Using untransformed coordinates.");
    return [point[0],-point[1]];
}

- Mark

Known Participant
November 1, 2024

Thanks @m1b 

m1b
Community Expert
Community Expert
November 1, 2024

You're welcome!