Paint with numbers with Adobe Illustrator Javascript

Viewed 62

Hello thanks to moluapple, I got this script from the adobe support community, I'm a beginner in javascript but I have a task to make, I have to paint numbers in each color of the image, actually, I see that in this solution brings me numbers in each layer, but doesn't work for the colors, can someone has a similar solution?

Let me add the expected result which is for each color on the picture the script adds a number to the color 1 for green 2 for yellow etc, let me show you.enter image description here

here is the original link

https://community.adobe.com/t5/illustrator-discussions/script-insert-text-number-in-the-middle-of-visible-bounds-of-the-each-object/td-p/8088914/page/3

(function() {
var doc = app.activeDocument,
    lays = doc.layers,
    WORK_LAY = lays.add(),
    NUM_LAY = lays.add(),
    i = lays.length - 1,
    lay;

// main working loop
for (; i > 1; i--) {
    //process each layer
    lay = lays[i];
    lay.name = lay.name + " Num:" + (i - 1); // i-1 as 2 layers beed added.
    process(lay.pathItems, false);
    process(lay.compoundPathItems, true); // if any
}
//clean up
NUM_LAY.name = "Numbers";
WORK_LAY.remove();

function process(items, isCompound) {
    var j = 0,
        b, xy, s, p, op;

    for (; j < items.length; j++) {
        // process each pathItem
        op = items[j];
        // add stroke
        if (isCompound) {
            strokeComPath(op);
        } else {
            !op.closed && op.closed = true;
            op.filled = false;
            op.stroked = true;
        };
        b = getCenterBounds(op);
        xy = [b[0] + (b[2] - b[0]) / 2, b[1] + (b[3] - b[1]) / 2];
        s = (
            Math.min(op.height, op.width) < 20 ||
            (op.area && Math.abs(op.area) < 150)
            ) ? 4 : 6; // adjust font size for small area paths.
        add_nums(i - 1, xy, s);
    }
}

function getMinVisibleSize(b) {
    var s = Math.min(b[2] - b[0], b[1] - b[3]);
    return Math.abs(s);
}

function getGeometricCenter(p) {
    var b = p.geometricBounds;
    return [(b[0] + b[2]) / 2, (b[1] + b[3]) / 2];
}

// returns square of distance between p1 and p2
function getDist2(p1, p2) {
    return Math.pow(p1[0] + p2[0], 2) + Math.pow(p1[1] + p2[1], 2);
}

// returns visibleBounds of a path in a compoundPath p
// which is closest to center of the original path op
function findBestBounds(op, p) {
    var opc = getGeometricCenter(op);
    var idx = 0,
        d;
    var minD = getDist2(opc, getGeometricCenter(p.pathItems[0]));
    for (var i = 0, iEnd = p.pathItems.length; i < iEnd; i++) {
        d = getDist2(opc, getGeometricCenter(p.pathItems[i]));
        if (d < minD) {
            minD = d;
            idx = i;
        }
    }
    return p.pathItems[idx].visibleBounds;
}

function applyOffset(op, checkBounds) {
    var p = op.duplicate(WORK_LAY, ElementPlacement.PLACEATBEGINNING),
        // offset value the small the better, but meantime more slow. 
        offset = function() {
            var minsize = Math.min(p.width, p.height);
            if (minsize >= 50) {
                return '-1'
            } else if (20 < minsize && minsize < 50) {
                return '-0.5'
            } else {
                return '-0.2' // 0.2 * 2 (both side ) * 50 (Times) = 20
            }
        },
        xmlstring = '<LiveEffect name="Adobe Offset Path"><Dict data="I jntp 2 R mlim 4 R ofst #offset"/></LiveEffect>'
        .replace('#offset', offset()),
        TIMES = 100; // if shapes are too large, should increase the value.

    if (checkBounds) {
        // check its size only if it needs, because it's too slow
        while (TIMES-- && getMinVisibleSize(p.visibleBounds) > 3) p.applyEffect(xmlstring);
    } else {
        while (TIMES--) p.applyEffect(xmlstring);
    }
    return p;
}

function getCenterBounds(op) {
    var originalMinSize = getMinVisibleSize(op.visibleBounds);

    var p = applyOffset(op, false);

    if (getMinVisibleSize(p.visibleBounds) > originalMinSize) {
        // in some cases, path p becomes larger for some unknown reason
        p.remove();
        p = applyOffset(op, true);
    }

    var b = p.visibleBounds;

    if (getMinVisibleSize(b) > 10) {
        activeDocument.selection = [p];
        executeMenuCommand("expandStyle");
        p = activeDocument.selection[0];
        if (p.typename == "CompoundPathItem") {
            b = findBestBounds(op, p);
        }
    }

    p.remove();
    return b;
}

function add_nums(n, xy, s) {
    var txt = NUM_LAY.textFrames.add();

    txt.contents = n;
    txt.textRange.justification = Justification.CENTER;
    txt.textRange.characterAttributes.size = s;
    txt.position = [xy[0] - txt.width / 2, xy[1] + txt.height / 2];
}

function strokeComPath(compoundPath) {
    var p = compoundPath.pathItems,
        l = p.length,
        i = 0;

    for (; i < l; i++) {
        !p[i].closed && p[i].closed = true;
        p[i].stroked = true;
        p[i].filled = false;
    };
}

})();

2 Answers

I don't understand what exactly you're trying to gain. So here is a guess:

If you change the function process() this way:

function process(items, isCompound) {
    var j = 0,
        b, xy, s, p, op;

    for (; j < items.length; j++) {
        // process each pathItem
        op = items[j];
        c = op.fillColor;                       // <--- here
        color = 'CMYK ' +                       // <--- here
            [   Math.round(c.cyan),             // <--- here
                Math.round(c.magenta),          // <--- here
                Math.round(c.yellow),           // <--- here
                Math.round(c.black)             // <--- here
            ].join(',');                        // <--- here
        // add stroke
        if (isCompound) {
            strokeComPath(op);
        } else {
            !op.closed && op.closed = true;
            // op.filled = false;               // <--- here
            // op.stroked = true;               // <--- here
        };
        b = getCenterBounds(op);
        xy = [b[0] + (b[2] - b[0]) / 2, b[1] + (b[3] - b[1]) / 2];
        s = (
            Math.min(op.height, op.width) < 20 ||
            (op.area && Math.abs(op.area) < 150)
            ) ? 4 : 6; // adjust font size for small area paths.

        // add_nums(i - 1 + color, xy, s);
        add_nums(color, xy, s);                 // <--- here
    }
}

It will put CMYK percents inside the shapes instead of numbers.

enter image description here

Here is the another modification of the main function process(). It's turned out that it can be done if you add & modify just two lines:

function process(items, isCompound) {
    var j = 0,
        b, xy, s, p, op;

    for (; j < items.length; j++) {
        // process each pathItem
        op = items[j];
        try { color = op.fillColor.spot.name } catch(e) { continue } // <-- HERE
        // add stroke
        if (isCompound) {
            strokeComPath(op);
        } else {
            !op.closed && op.closed = true;
            op.filled = false;
            op.stroked = true;
        };
        b = getCenterBounds(op);
        xy = [b[0] + (b[2] - b[0]) / 2, b[1] + (b[3] - b[1]) / 2];
        s = (
            Math.min(op.height, op.width) < 20 ||
            (op.area && Math.abs(op.area) < 150)
            ) ? 4 : 6; // adjust font size for small area paths.

        add_nums(color, xy, s); // <--- HERE
    }
}

And the colors should be Spot Global colors. The script put in the middle of every shape a name of the swatch color.

Input:

enter image description here

Output:

enter image description here

Related