I tried to make a script that will do an action a couple of times (loop) based on the number of colors that the selected art have. And if there is a way to store the color names in an array it would be great too.
I can't figure it out on my own and I only have the basics of the script:
var doc = app.activeDocument;
var sel = doc.selection[0];
var selcolors = 0;
//====================
//Here I need to get how many colors the selected art have and set it to selcolors
//====================
for(i = 0; i < selcolors; i++)
{
//Set of actions
}
Any help will be appreciated!
It depends on what exactly you're trying to do with the colors and what kind of colors you're using.
For example for spot colors it can be something like this:
var doc = app.activeDocument;
var sel = doc.selection;
// get all path items from the selection
var pathItems = [];
for (var i=0; i<sel.length; i++) get_all_pathItems(sel[i], pathItems);
// put all the colors into the object
var obj = {};
for (var i=0; i<pathItems.length; i++) {
var item = pathItems[i];
if (item.filled) {
var color = item.fillColor;
if (color instanceof SpotColor) obj[color.spot.name] = color;
}
if (item.stroked) {
var color = item.strokeColor;
if (color instanceof SpotColor) obj[color.spot.name] = color;
}
}
// get a number of the colors from the object
var n = 0;
for (key in obj) n++;
// updated lines below:
// run some actions, perhaps you don't even need the number
for (key in obj) {
if (key == 'White') continue; // skip White color
// action 1
// action 2
// etc...
}
// ----------------------------------------------------------
// recursive function to fill the given array with all pathItems of given item
function get_all_pathItems(item, arr) {
try { if (item instanceof PathItem) arr.push(item) } catch(e) {}
try {
if (item instanceof GroupItem) {
var paths = item.pathItems;
for (var i=0; i<paths.length; i++) arr.push(paths[i]);
var groups = item.groupItems;
for (var i=0; i<groups.length; i++) get_all_pathItems(groups[i], arr);
}
} catch(e) {}
}
And there is one problem. In Illustrator a group of items can have its own color (fill and stroke). As far as I know you can't get the color of the group with a script. A script can get only colors of a path items, not groups.
Update
Here is the the updated code that selects objects with the same color of fill or stroke and do actions in the loop:
var doc = app.activeDocument;
var sel = doc.selection;
// get all path items from the selection
var pathItems = [];
for (var i=0; i<sel.length; i++) get_all_pathItems(sel[i], pathItems);
// put all the colors into the object
var obj = {};
for (var i=0; i<pathItems.length; i++) {
var item = pathItems[i];
if (item.filled) {
var color = item.fillColor;
if (color instanceof SpotColor) obj[color.spot.name] = color;
}
if (item.stroked) {
var color = item.strokeColor;
if (color instanceof SpotColor) obj[color.spot.name] = color;
}
}
delete obj['White'] // remove White from the object
// add empty arrays to every color in the object
for (color in obj) obj[color].items = [];
// fill the arrays of the object with items of the same fill or stroke color
for (var i=0; i<pathItems.length; i++) {
var item = pathItems[i];
if (item.filled) {
var color = item.fillColor;
if (color instanceof SpotColor) {
if (color.spot.name in obj) obj[color.spot.name].items.push(item);
}
}
if (item.stroked) {
var color = item.strokeColor;
if (color instanceof SpotColor) {
if (color.spot.name in obj) obj[color.spot.name].items.push(item);
}
}
}
for (color in obj) {
app.selection = obj[color].items; // select all object from the color's array
// do action with the selected objects
}
// ----------------------------------------------------------
// recursive function to fill the given array with all pathItems of given item
function get_all_pathItems(item, arr) {
try { if (item instanceof PathItem) arr.push(item) } catch(e) {}
try {
if (item instanceof GroupItem) {
var paths = item.pathItems;
for (var i=0; i<paths.length; i++) arr.push(paths[i]);
var groups = item.groupItems;
for (var i=0; i<groups.length; i++) get_all_pathItems(groups[i], arr);
}
} catch(e) {}
}
Just in case. If you need to get the "collective" size (width and height) of the items with the same color you can do something like this:
// loop through the colors and get sizes of items with the same colors
var report = [];
for (color in obj) {
var items = obj[color].items
var size = get_size(items);
report.push([
'Color: ' + color,
'Number of items: ' + items.length,
'Width: ' + size.width,
'Height: ' + size.height,
].join('\n'));
}
alert(report.join('\n\n')); // show the report
// ------------------------------------------------------------------
// function to get the collective size {width, height} of given items
function get_size(array) {
var tops = [], lefts = [], rights = [], bottoms = [];
for (var i=0; i<array.length; i++) {
if (array[i].guides) continue; // skip guides just in case
tops.push(array[i].visibleBounds[1]);
lefts.push(array[i].visibleBounds[0]);
rights.push(array[i].visibleBounds[2]);
bottoms.push(array[i].visibleBounds[3]);
};
var top = Math.max.apply(null, tops);
var left = Math.min.apply(null, lefts);
var right = Math.max.apply(null, rights);
var bottom = Math.min.apply(null, bottoms);
return {width:right-left, height:bottom-top};
}
It will show you the sizes (the alert window) for every spot color of selected artwork. Of course you can save the report into a text file as well.
Update 2
Here is the full implementation of the code which draws marks for every spot color of selected items. The code considered masks and text objects. The marks are aligned by the center of top selected object.
if (app.activeDocument.selection.length != 0) main();
function main() {
// disable warnings
var uInterration = app.userInteractionLevel;
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
// save selection and deselect all
var orig_selection = app.selection;
app.selection = null;
// duplicate the objects that were selected and select the duplicates
var duplicates = [];
for (var i=0; i<orig_selection.length; i++) duplicates.push(orig_selection[i].duplicate());
app.selection = duplicates;
// UPDATED get the horizontal and vertical axes for the marks from the top object
var top_object = app.selection[0];
if (top_object.clipped || top_object instanceof GroupItem) {
var top_inner_object = top_object.pageItems[0];
if (top_inner_object.clipped) top_object = top_inner_object.pageItems[0];
}
var vertical_axis = top_object.position[0] + top_object.width/2;
var horizontal_axis = top_object.position[1] - top_object.height/2;
// expand the selected objects
// ungroup all groups, flat all masks, outline texts, release compound paths)
expand_selected_items();
// create the object with colors and pathItems
var obj = make_color_object(app.activeDocument.selection);
// loop through the object and make the marks for every color
for (color in obj) {
var size = get_size(obj[color].items); // get sizes
draw_marks(size, horizontal_axis, vertical_axis, obj[color]);
}
// remove the temp objects and restore the original selection
for (var i=app.selection.length-1; i>=0; i--) app.selection[i].remove();
app.selection = orig_selection;
// restore warnings
app.userInteractionLevel = uInterration;
}
// ----------------------------------------------------------------------------
// function returns the 'collective' size and edges of given array of items
// {left, top, right, bottom, width, height}
function get_size(items) {
var tops = [], lefts = [], rights = [], bottoms = [];
for (var i=0; i<items.length; i++) {
if (items[i].guides) continue;
tops.push(items[i].visibleBounds[1]);
lefts.push(items[i].visibleBounds[0]);
rights.push(items[i].visibleBounds[2]);
bottoms.push(items[i].visibleBounds[3]);
};
var top = Math.max.apply(null, tops);
var left = Math.min.apply(null, lefts);
var right = Math.max.apply(null, rights);
var bottom = Math.min.apply(null, bottoms);
return {left:left, top:top, right:right, bottom:bottom, width:right-left, height:top-bottom};
}
// function 'expands' all selected objects
// (releases masks and compound paths, ungroups groups, outlines strokes and texts)
function expand_selected_items() {
app.executeMenuCommand('ungroup');
app.executeMenuCommand('ungroup');
app.executeMenuCommand('outline'); // text to curves
app.executeMenuCommand('ungroup');
app.executeMenuCommand('OffsetPath v22'); // expand stroke
app.executeMenuCommand('Live Pathfinder Divide'); // expand masks (Live)
app.executeMenuCommand('expandStyle'); // Live --> plain
app.executeMenuCommand('noCompoundPath'); // release compound paths
app.executeMenuCommand('ungroup');
}
// function makes the color object from given array of pathItems:
// {color1:{color, items:[pathItems]}, color2:{color, items:[pathItems]}, ...}
function make_color_object(items) {
var obj = {};
var add_color_into_obj = function(color, obj) {
if (color instanceof SpotColor)
obj[color.spot.name] = color;
}
var put_item_into_color = function(color, obj, item) {
if (color instanceof SpotColor && color.spot.name in obj)
obj[color.spot.name].items.push(item);
}
// add colors into the object
for (var i=0; i<items.length; i++) {
if (items[i].filled) add_color_into_obj(items[i].fillColor, obj);
// if (items[i].stroked) add_color_into_obj(items[i].strokeColor, obj); // there is no stroked objects anyway
}
delete obj['White']; // remove White color from the object
// add empty arrays to every color in the object
for (color in obj) obj[color].items = [];
// fill the arrays of the object with items of the same fill or stroke color
for (var i=0; i<items.length; i++) {
if (items[i].filled) put_item_into_color(items[i].fillColor, obj, items[i]);
// if (items[i].stroked) put_item_into_color(items[i].strokeColor, obj, items[i]); // there is no stroked objects anyway
}
return obj;
}
// function draws the four marks around the given area
// the marks will be aligned by the given horizontal and vertical axes
function draw_marks(area, horiz, vert, color) {
var mm = 2.83464566929134; // mm/pt
var space = 5 * mm;
var len = 3 * mm;
var strokeWidth = 1; // pt
var x1,x2,y1,y2;
// select or make the group
var group_name = 'Marks';
try {
var group = app.activeDocument.groupItems.getByName(group_name) }
catch(e) {
var group = app.activeDocument.groupItems.add();
group.name = group_name;
}
// subfunction to draw the mark with given coords
var draw_mark = function(x1,y1,x2,y2,label) {
var mark = app.activeDocument.pathItems.add();
mark.setEntirePath([[x1,y1],[x2,y2]]);
mark.filled = false;
mark.stroked = true;
mark.strokeWidth = strokeWidth;
mark.strokeOverprint = true;
mark.strokeColor = color;
mark.name = color.spot.name + ' - ' + label;
return mark;
}
y1 = y2 = horiz;
x1 = area.left - len - space;
x2 = x1 + len;
draw_mark(x1,y1,x2,y2,'left').moveToEnd(group);
x1 = area.right + space;
x2 = x1 + len;
draw_mark(x1,y1,x2,y2,'right').moveToEnd(group);
x1 = x2 = vert;
y1 = area.top + space + len;
y2 = y1 - len;
draw_mark(x1,y1,x2,y2,'top').moveToEnd(group);
y1 = area.bottom - space;
y2 = y1 - len;
draw_mark(x1,y1,x2,y2,'bottom').moveToEnd(group);
}
Result (the dashed lines were added manually to show the logic behind the mark positions):