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

Script that sorts items in selection

Explorer ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

I'm trying to write a script that sorts/arranges the items in the selection (no strokes and all using spot colors) by "lightest to darkest". It's part of a larger goal to hopefully automate making separations for screenprinting but I'm stuck on this aspect. I've tried to accomplish this in several ways but the one I think has the most promise is converting each item's fill to grayscale, storing the original fill colors and the new gray values of each item in an array as objects, sorting the array based on gray values, and then making the items then match the new order of the array and returning the items to their original fill color. But I can't seem to make that work. Is there an easier way to accomplish this that I'm just not thinking of? also, is it possible to just assign a number to a zorder of an item rather than lengthy looping SENDBACKWARDS/SENDFORWARDS for the function? Thanks in advance.

TOPICS
Scripting

Views

452

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

Community Expert , Feb 09, 2024 Feb 09, 2024

Hi @Isaac265865188lnf, I have some functions I have previously written on hand, so I have put together this script quickly to do what I think you want. At the least it will show you a different approach and I think that will be useful.

- Mark

 

Screenshot 2024-02-10 at 08.39.46.png

/**
 * Sort the selected items by their darkness value
 * (we use convert to grayscale, but you may want
 * to try other methods, too) and re-order so that
 * the darker items are in front of lighter items.
 * @author m1b
 * @discussion https://community
...

Votes

Translate

Translate
Adobe
Guide ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

Sorting shouldn't be a problem.  How are you converting a color to grayscale? 

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 ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

I have one function that creates the objects pushed to the array with properties for original colors (item.fillColor.spot.name) and a gray property I leave blank. Then I use app.executeMenuCommand('Colors7') to convert to grayscale. And another function pushes each item's grey equivalent to the gray property of the object.

 

 

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 ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

var doc = app.activeDocument;
var selection = doc.selection;
var objectsInSelection = [];
var grayObjectsInSelection = [];

//=============================================================================

function findFills() {

	// Iterate through selected objects
	for (var i = 0; i < selection.length; i++) {
	    var item = selection[i];
	    var fillColor = item.fillColor ? item.fillColor.spot.name : "None";
	    
	    // Create an object for each item in the selection
	    var obj = {
	        fillColor: fillColor,
	        grayAmount: "", // Placeholder for gray amount
	        order: i // Index of the item in the selection
	    }
	    objectsInSelection.push(obj);
	}
}

//==============================================================================

function findGrayFills() {

	// Iterate through selected objects
	for (var i = 0; i < selection.length; i++) {
	    var item = selection[i];
	    var fillColorGray = item.fillColor ? item.fillColor.gray : "None";
	    
	    // Create an object for each item in the selection
	    var obj = {
	        fillColor: objectsInSelection[i].fillColor,
	        grayAmount: fillColorGray,
	        order: i // Index of the item in the selection
	    }
	    grayObjectsInSelection.push(obj);
	    objectsInSelection[i].grayAmount = fillColorGray;
	}
}

//=============================================================================
// Define the comparison function for sorting
function compare(a, b) {
    if (a.grayAmount < b.grayAmount) {
        return -1;
    }
    if (a.grayAmount > b.grayAmount) {
        return 1;
    }
    return 0;
}

//===========================================
function sortSelection(){
sorting function i cant figure out
}
//========================================

findFills();
app.executeMenuCommand('Colors7');
findGrayFills();
objectsInSelection.sort(compare);
sortSelection();

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 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

Hi @Isaac265865188lnf, I have some functions I have previously written on hand, so I have put together this script quickly to do what I think you want. At the least it will show you a different approach and I think that will be useful.

- Mark

 

Screenshot 2024-02-10 at 08.39.46.png

/**
 * Sort the selected items by their darkness value
 * (we use convert to grayscale, but you may want
 * to try other methods, too) and re-order so that
 * the darker items are in front of lighter items.
 * @author m1b
 * @discussion https://community.adobe.com/t5/illustrator-discussions/script-that-sorts-items-in-selection/m-p/14413597
 */
(function () {

    var doc = app.activeDocument,
        items = doc.selection,
        ordered = Array(items.length);

    // calculate the darkness and add to a sortable array
    for (var i = 0; i < items.length; i++) {

        if (undefined != items[i].fillColor)

            ordered[i] = {
                uuid: items[i].uuid,
                value: getGrayScaleValueFor(items[i].fillColor),
            };

    }

    // sort by darkness, descending
    ordered.sort(function (a, b) { return b.value - a.value });

    // make an item to act as a layer reference
    var reference = doc.groupItems.add();
    reference.move(items[0], ElementPlacement.PLACEBEFORE);

    try {

        // move each item to above the reference, in new order
        for (var i = 0, item; i < ordered.length; i++) {
            item = doc.getPageItemFromUuid(ordered[i].uuid);
            item.move(reference, ElementPlacement.PLACEBEFORE);
        }

    }

    catch (error) {
        alert(error);
    }

    finally {
        // clean up
        reference.remove();
    }

})();


/**
 * Returns a grayscale value, given a color breakdown.
 * @author m1b
 * @version 2022-05-23
 * @param {Array<Number>|Color} breakdown - array of color values, eg. [c, m, y, k] or [r, g, b], or a Color, eg. CMYKColor.
 * @returns {Number}
 */
function getGrayScaleValueFor(breakdown) {

    if ('Array' !== breakdown.constructor.name)
        breakdown = getColorBreakdown(breakdown);

    var gray;

    if (breakdown.length === 4)
        gray = app.convertSampleColor(ImageColorSpace.CMYK, breakdown, ImageColorSpace.GrayScale, ColorConvertPurpose.defaultpurpose);

    else if (breakdown.length === 3)
        gray = app.convertSampleColor(ImageColorSpace.RGB, breakdown, ImageColorSpace.GrayScale, ColorConvertPurpose.defaultpurpose);

    return gray;

};


/**
 * Returns an array of color channel values.
 * @author m1b
 * @version 2022-05-23
 * @param {Swatch|Color} col - an Illustrator Swatch or Color.
 * @param {Number} [tintFactor] - a number in range 0..1 (default: 1).
 * @returns {Array<Number>}
 */
function getColorBreakdown(col, tintFactor) {

    tintFactor = tintFactor || 1;

    if (col.hasOwnProperty('color'))
        col = col.color;

    if (col.constructor.name == 'SpotColor')
        col = col.spot.color;

    if (col.constructor.name === 'CMYKColor')
        return [col.cyan * tintFactor, col.magenta * tintFactor, col.yellow * tintFactor, col.black * tintFactor];

    else if (col.constructor.name === 'RGBColor')
        return [col.red * tintFactor, col.green * tintFactor, col.blue * tintFactor];

    else if (col.constructor.name === 'GrayColor')
        return [col.gray * tintFactor];

};

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 ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

This. Works. PERFECTLY!!  Exactly what I was trying to do. I've been stuck trying to figure the logic required for a few days. I can't thank you enough!

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 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

LATEST

Good to hear! 🙂

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
Guide ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

Here's a simple snippet that sorts paths horizontally based on the black value of the fill. 

femkeblanco_2-1707516129073.pngfemkeblanco_3-1707516134885.png

var doc  = app.activeDocument;
var paths = doc.pathItems;

var array1 = [];
for (var i = 0; i < paths.length; i++) {
    array1.push(paths[i]);
}

array1.sort(function(a, b) {
    return b.fillColor.spot.color.black - a.fillColor.spot.color.black;
})

bubbleSort(array1);

function bubbleSort(a){
    for (var i = a.length-1; i > 0; i--){
        for (var j = 0; j < i; j++){
            if (a[j].top > a[j+1].top){
                var temp = a[j].top;
                a[j].top = a[j+1].top;
                a[j+1].top = temp;
            }
        }
    }
}

 

 

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 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

Nice! 🙂

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 ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

I was looking to reorganize the items in the selection by their zOrder as they would end up in the order each ink would be printed BUT what you've done here would/will also prove very handy for listing swatch/inks in their correct order visually on customer proofs and such. Thank you!

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
Guide ,
Feb 09, 2024 Feb 09, 2024

Copy link to clipboard

Copied

It can easily be modified to sort in zOrder. 

var doc  = app.activeDocument;
var paths = doc.pathItems;

var array1 = [];
for (var i = 0; i < paths.length; i++) {
    array1.push(paths[i]);
}

array1.sort(function(a, b) {
    return b.fillColor.spot.color.black - a.fillColor.spot.color.black;
})

bubbleSort(array1);

function bubbleSort(a){
    for (var i = a.length-1; i > 0; i--){
        for (var j = 0; j < i; j++){
            if (a[j].zOrderPosition > a[j+1].zOrderPosition){
                a[j].move(a[j+1], ElementPlacement.PLACEAFTER);
            }
        }
    }
}

 

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