Skip to main content
Participating Frequently
January 19, 2023
Answered

Script to center texts inside paths

  • January 19, 2023
  • 2 replies
  • 2176 views

Hello,

I need to center texts inside closed paths (mostly rectangle shapes). The texts are on one layer and the paths on another. It feels like there must be a faster way than to do this by hand... is there a script that could speed up the process?

Thanks!

This topic has been closed for replies.
Correct answer femkeblanco

Thanks Carlos. You're right it works great on the sample file, the only problem is when there is no text inside a rectangle then all the texts will be shuffled (sometimes centered in a different rectangle than the one they were inside originally). It's already a big help, just a bit scary to run on a file with hundreds of rectangle/texts where I might miss an empy one!


"it seems to no work on the rectangles that have a rotation?"

That's because the script relys upon the bounding boxes, and the bounding boxes of the rotated rectangles overlap.  Try this.  It worked on a simple test doc, but it has not been rigorously tested.  (I cannot open your file becuase of my Illustrator.)

var doc = app.activeDocument;
for (var i = 0; i < doc.pathItems.length; i++) {
    var shapeItem = doc.pathItems[i];
    for (var j = 0; j < doc.textFrames.length; j++) {
        var textItem = doc.textFrames[j];
        var centre = [
            textItem.position[0] + textItem.width / 2, 
            textItem.position[1] - textItem.height / 2
        ];
        if (pointIsInPoly(shapeItem.pathPoints, centre)) {
            textItem.position = [
                shapeItem.position[0] + shapeItem.width / 2 - textItem.width / 2,
                shapeItem.position[1] - shapeItem.height / 2 + textItem.height / 2
            ];
        }
    }
}
// Jonas Raoni Soares Silva
// http://jsfromhell.com/math/is-point-in-poly
function pointIsInPoly(poly, pt){
    for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
        ((poly[i].anchor[1] <= pt[1] && pt[1] < poly[j].anchor[1]) || (poly[j].anchor[1] <= pt[1] && pt[1] < poly[i].anchor[1]))
        && (pt[0] < (poly[j].anchor[0] - poly[i].anchor[0]) * (pt[1] - poly[i].anchor[1]) / (poly[j].anchor[1] - poly[i].anchor[1]) + poly[i].anchor[0])
        && (c = !c);
    return c;
}

 

2 replies

Kurt Gold
Adobe Expert
January 19, 2023

It may be helpful if you could share at least one sample Illustrator file that shows the initial situation as well as the desired result.

 

Denis_251Author
Participating Frequently
January 20, 2023

The rectangles are "paths" and the type "text". The texts bounding box might sometimes be outside of the paths but their centers will be inside. Here's an exemple; the green rectangles show the texts centered; the others are in their original position (from an autocad file). Thanks.

Denis_251Author
Participating Frequently
January 23, 2023

"it seems to no work on the rectangles that have a rotation?"

That's because the script relys upon the bounding boxes, and the bounding boxes of the rotated rectangles overlap.  Try this.  It worked on a simple test doc, but it has not been rigorously tested.  (I cannot open your file becuase of my Illustrator.)

var doc = app.activeDocument;
for (var i = 0; i < doc.pathItems.length; i++) {
    var shapeItem = doc.pathItems[i];
    for (var j = 0; j < doc.textFrames.length; j++) {
        var textItem = doc.textFrames[j];
        var centre = [
            textItem.position[0] + textItem.width / 2, 
            textItem.position[1] - textItem.height / 2
        ];
        if (pointIsInPoly(shapeItem.pathPoints, centre)) {
            textItem.position = [
                shapeItem.position[0] + shapeItem.width / 2 - textItem.width / 2,
                shapeItem.position[1] - shapeItem.height / 2 + textItem.height / 2
            ];
        }
    }
}
// Jonas Raoni Soares Silva
// http://jsfromhell.com/math/is-point-in-poly
function pointIsInPoly(poly, pt){
    for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
        ((poly[i].anchor[1] <= pt[1] && pt[1] < poly[j].anchor[1]) || (poly[j].anchor[1] <= pt[1] && pt[1] < poly[i].anchor[1]))
        && (pt[0] < (poly[j].anchor[0] - poly[i].anchor[0]) * (pt[1] - poly[i].anchor[1]) / (poly[j].anchor[1] - poly[i].anchor[1]) + poly[i].anchor[0])
        && (c = !c);
    return c;
}

 


Thanks a lot! This works great even when there are empty rectangles.

CarlosCanto
Adobe Expert
January 19, 2023

try this script, it doesn't have any error checking so make sure your text layer is the top most layer, shape layer is right below it and you have the same number of text items and shape items

 

// center text on one layer to shape on the layer below
// https://community.adobe.com/t5/illustrator-discussions/script-to-center-texts-inside-paths/td-p/13503494

var idoc = app.activeDocument;
var textLayer = idoc.layers[0]
var shapeLayer = idoc.layers[1]

for (var a=0; a<textLayer.pageItems.length; a++) {
    textItem = textLayer.pageItems[a];
    shapeItem = shapeLayer.pageItems[a];
    
    textItem.position = [
        shapeItem.position[0] + shapeItem.width/2 - textItem.width/2,
        shapeItem.position[1] - shapeItem.height/2 + textItem.height/2
    ]
}

 

 

Denis_251Author
Participating Frequently
January 19, 2023

Thanks Carlos. Unfortunately some files will have paths without texts inside. But what I failed to precise is that the texts are all different: I'd need each text to be centered in the rectangle that is around it..

femkeblanco
Brainiac
January 19, 2023

Are the rectangles paths (not groups, for example)?  Is the type text (not paths)?  Is the text's bounding box completely within the path?  If so, @CarlosCanto's script can be easily modified to centre the text relative to the path it's in.