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

How to move an item relatively from it's container( basic geometry and ensemble topology)

Explorer ,
Aug 31, 2017 Aug 31, 2017

Copy link to clipboard

Copied

Hi,
I have a file containing images [BROWN], text[RED] and some pathitems frames[YELLOW and GREY]. I've seen that all the stuff is aligned by the center of each image like shown in the picture.

The image will later be cropped by the yellow frame, I'm looking for a method to move the text closer to the bottom of the yellow frame. In a perfect world text should also rotate following the yellow frame bottom path to avoid being cropped.

I'm pretty sure it can be done easily in a couple of lines if it were a rectangle because there is a rectangle method. Instead here is an apparent parallelogram composed by 200 anchor points (imported from another software).

  • YELLOW : hundred points pathItems
  • RED : textFrames
  • BROWN : rectangular image that has a square center. A bitmap image
  • GREY : pathItems rectangles that I plan to use for control of textFrame position

I'm very new to Ai JS scripting so I don't know (yet) every items of all the 300 hundred pages of the JS DOM. I'm lacking ideas for methods (either JS or ESTK).

I can select any object, move item, do any aiAction, do any actionmenu, calculate half the height of a rectangle... but what I need is a snippet to find that vertical offset to be sure to keep text inside the yellow frame... This is basic geometry and topology, my brain can perfectly use a mouse to do it at least.

My idea is to draw a line from the image center and intercept a line (or spline) of the yellow frame; then calculating the tangent angle for the text. Otherwise define parallelogram by using a (u;v) vector reference like in a good old maths problem!

Thanks for your time

EDIT I've found a fun <Canvas> script

TOPICS
Scripting

Views

851

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

correct answers 1 Correct answer

Enthusiast , Sep 02, 2017 Sep 02, 2017

OK, this works for your template.

function get_line(p) {

    var ps = p.pathPoints,

        g = p.geometricBounds,

        i = 0,

        br/*bottomRight*/, pre, next;

    for (; i < ps.length; i++) {

        pre = (i == 0) ? ps[ps.length - 1] : ps[i - 1];

        next = (i == ps.length - 1) ? ps[0] : ps[i + 1];

        br = ps.anchor;

        if ((pre.anchor[0] - br[0]) < (pre.anchor[1] - br[1]) &&

            (br[0] - next.anchor[0]) > (br[1] - next.anchor[1])

        ) {

            return [[g[0], g[3]],

...

Votes

Translate

Translate
Adobe
Enthusiast ,
Aug 31, 2017 Aug 31, 2017

Copy link to clipboard

Copied

Hi, select a yellow path and try this. It will add a pathText item and copy the original text to it.

function get_line(p) {

    var ps = p.pathPoints,

        g = p.geometricBounds,

        i = 0,

        y2 = g[1];

    for (; i < ps.length; i++) {

        if (ps.anchor[0].toFixed(5) === g[2].toFixed(5) && y2 > ps.anchor[1]) {

            y2 = ps.anchor[1];

        };

    };

    return [

        [g[0], g[3]],

        [g[2], y2]

    ]

}

function get_text(p) {

    var g = p.geometricBounds,

        t = activeDocument.textFrames,

        i = 0,

        gt;

    for (; i < t.length; i++) {

        gt = t.geometricBounds;

        if (gt[0] > g[0] && gt[1] < g[1] && gt[2] < g[2] && gt[3] > g[3]) {

            return t

        }

    };

}

function create_pathText(p) {

    var text = get_text(p),

        l = activeDocument.pathItems.add(),

        t = (l.setEntirePath(get_line(p)), activeDocument.textFrames.pathText(l)),

        attr = t.textRange.characterAttributes,

        _attr = text.textRange.characterAttributes;

    t.contents = text.contents;

    attr.size = _attr.size;

    attr.textFont = _attr.textFont;

    attr.fillColor = _attr.fillColor;

    attr.baselineShift = 10; // offset to bottom

    t.textRange.paragraphAttributes.justification = Justification.CENTER;

    text.remove();

}

create_pathText(app.selection[0]);

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
Explorer ,
Sep 01, 2017 Sep 01, 2017

Copy link to clipboard

Copied

This is excellent thanks! I've been googling geometricBounds, characterAttributes, pathPoints and toFixed. So my template looks like this now

REM: Because the template was too small, "toFixed" method made coordinates a bit off. Not an issue though


I'm focusing now on tweaking geometricBounds to catch to bottom right coordinate. Question: is the array of geometricBounds forced to be a rectangle?

Maybe by trying to rebuild a polygon (or a parallelogram) from a rectangle with these bounds can be a solution...


(( Once done, I will use my select function. This could run without user interaction because the yellow frame (so a compundpathitem?) can be selected easily into it's layer; it has a specific thickness. Then calling it with layer.pathitems in a for loop. ))

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
Enthusiast ,
Sep 02, 2017 Sep 02, 2017

Copy link to clipboard

Copied

OK, this works for your template.

function get_line(p) {

    var ps = p.pathPoints,

        g = p.geometricBounds,

        i = 0,

        br/*bottomRight*/, pre, next;

    for (; i < ps.length; i++) {

        pre = (i == 0) ? ps[ps.length - 1] : ps[i - 1];

        next = (i == ps.length - 1) ? ps[0] : ps[i + 1];

        br = ps.anchor;

        if ((pre.anchor[0] - br[0]) < (pre.anchor[1] - br[1]) &&

            (br[0] - next.anchor[0]) > (br[1] - next.anchor[1])

        ) {

            return [[g[0], g[3]], br]

        };

    };

}

function get_text(p) {

    var g = p.geometricBounds,

        t = activeDocument.textFrames,

        i = 0,

        gt;

    for (; i < t.length; i++) {

        gt = t.geometricBounds;

        if (gt[0] > g[0] && gt[1] < g[1] && gt[2] < g[2] && gt[3] > g[3]) {

            return t

        }

    };

}

function create_pathText(p) {

    var text = get_text(p),

        l = activeDocument.pathItems.add(),

        t = (l.setEntirePath(get_line(p)), activeDocument.textFrames.pathText(l));

    text.textRange.move(t, ElementPlacement.PLACEATBEGINNING);

    t.textRange.characterAttributes.baselineShift = 10; // offset to bottom 

    t.textRange.paragraphAttributes.justification = Justification.CENTER;

    text.remove();

}

create_pathText(app.selection[0]);

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
Explorer ,
Sep 04, 2017 Sep 04, 2017

Copy link to clipboard

Copied

LATEST

Just awesome! Thanks a lot for extending my understanding of ExtendScript possibilities

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