Skip to main content
rcraighead
Legend
March 2, 2022
Answered

set "fillColor" using a variable?

  • March 2, 2022
  • 1 reply
  • 1086 views

I'd like to assign a color to a selection  based on the selection name (or any other variable). How do I do that? I tried defining a color and giving it the selection name but AI VSCode says "Object expected".

var Bar = new RGBColor();
Bar.red = 0;
Bar.green = 0;
Bar.blue = 255;

setCustomCrop()
function setCustomCrop() {
var aDoc = app.activeDocument;
var selMask = selection[0].name;
customCrop = selMask;
var CropGroup = aDoc.groupItems['CropGroup'];
var myItem = CropGroup.pageItems;
var myMask = myItem[customCrop];
myMask.locked = false;
myMask.fillColor = selMask;
myMask.blendingMode = BlendModes.MULTIPLY;
myMask.opacity = 50;
myMask.stroked = false;
myMask.locked = true;
myItem[customCrop + '_Ref'].remove();
This topic has been closed for replies.
Correct answer femkeblanco

You need to assign a fillColor a color object, not a name.  How you target your item depends on your needs. 

 

To assign a selected item a color:

app.selection[0].fillColor = Bar;

 

A selection element won't accept a string identifier.  So if you want to target a selected item by name, you will have to iterate through the selection collection and test for the name:

for (var i = 0; i < app.selection.length; i++) {
    if (app.selection[i].name == "Something") {
        app.selection[i].fillColor = Bar;
    }
}

 

But in your case the above only applies if you are specifically selecting members of groups.  The selection collection contains only top level items (i.e. only the group), so it won't contain members of groups.  If you are targeting a member of a group by name, do you need it selected? 

setCustomCrop()
function setCustomCrop() {
    var aDoc = app.activeDocument;
    var CropGroup = aDoc.groupItems['CropGroup'];
    var myItems = CropGroup.pageItems;
    var myMask = myItems["Something"];
    myMask.fillColor = Bar;
    // ...
}

 

1 reply

femkeblanco
femkeblancoCorrect answer
Legend
March 2, 2022

You need to assign a fillColor a color object, not a name.  How you target your item depends on your needs. 

 

To assign a selected item a color:

app.selection[0].fillColor = Bar;

 

A selection element won't accept a string identifier.  So if you want to target a selected item by name, you will have to iterate through the selection collection and test for the name:

for (var i = 0; i < app.selection.length; i++) {
    if (app.selection[i].name == "Something") {
        app.selection[i].fillColor = Bar;
    }
}

 

But in your case the above only applies if you are specifically selecting members of groups.  The selection collection contains only top level items (i.e. only the group), so it won't contain members of groups.  If you are targeting a member of a group by name, do you need it selected? 

setCustomCrop()
function setCustomCrop() {
    var aDoc = app.activeDocument;
    var CropGroup = aDoc.groupItems['CropGroup'];
    var myItems = CropGroup.pageItems;
    var myMask = myItems["Something"];
    myMask.fillColor = Bar;
    // ...
}

 

rcraighead
Legend
March 2, 2022

Thanks, @femkeblanco .

Yes, the artist will have an selected. That item name should be used to assign the color. Your solution works perfectly! I have 5 named color possibilities. Does that mean I need to add 4 "else if" statements to iterate through all the possibilites?

EDIT:
I realized since I have a single item selected the "for" loop is not needed. This now works:

function setCustomCrop() {
    var aDoc = app.activeDocument;
    var selMask = selection[0];
    customCrop = selMask.name;
    var CropGroup = aDoc.groupItems['CropGroup'];
    var myItem = CropGroup.pageItems;
    var myMask = myItem[customCrop];
    myMask.locked = false;
    if (selMask.name == "Bar") {
        selMask.fillColor = Bar;
    } else if (selMask.name == "Round") {
        selMask.fillColor = Round;
    } else if (selMask.name == "Heart") {
        selMask.fillColor = Heart;
    } else if (selMask.name == "SmallHeart") {
        selMask.fillColor = SmallHeart;
    } else if (selMask.name == "LargeHeart") {
        selMask.fillColor = LargeHeart;
    }
…
Inventsable
Legend
March 2, 2022

Hi Craig, we could make this a bit more dynamic and less reliant on the hard-coded values for selMask.fillColor assignment and name checking. Consider this:

 

// Store all our colors in a global object with key values matching mask names:
var masks = {
    Bar: createRGB(255, 0, 0),
    Round: createRGB(0, 255, 0),
    Heart: createRGB(0, 0, 255)
}

// Create a simple utility function to allow us to more easily make RGB colors:
function createRGB(red, green, blue) {
    var temp = new RGBColor();
    temp.red = red;
    temp.green = green;
    temp.blue = blue;
    return temp;
}

// Now we dynamically retreive all our key mask names:
var keys = [];
for (var key in masks) keys.push(key);
// And create a RegEx to check them:
var maskRX = new RegExp("^(" + keys.join("|") + ")$");
// Equivalent to /^(Bar|Round|Heart)$/

function setCustomCrop() {
    var aDoc = app.activeDocument;
    var selMask = selection[0];
    customCrop = selMask.name;
    var CropGroup = aDoc.groupItems['CropGroup'];
    var myItem = CropGroup.pageItems;
    var myMask = myItem[customCrop];
    myMask.locked = false;

    // If the name matches our RegEx above:
    if (maskRX.test(selMask.name))
        selMask.fillColor = masks[selMask.name] 
    // ^ We use the name to match the color from our masks variable

  /**
   * No need for long ternary chains and makes our code more dynamic
   * because adding a new mask is as simple as adding:
   * 
   * SmallHeart: createRGB(150, 50, 50)
   * 
   * In the original "masks" variable at the top.
   */
}

 

 

In ES6 this would be much easier:

 

let maskRX = new RegExp(`^(${Object.keys(masks).join("|")})$`);

 

 

I mention this mostly because the more we rely on static or hard-coded values, the more opportunities we have to get errors on typos and misspellings, and the more modifications you'd have to make to the script in multiple locations if you were to change one of these variable names or add/remove them. Doing this in a dynamic way has a bit of an overhead cost but afterwards can save a lot of time and energy maintaining it later on, because I can now have any number of masks all neatly organized in the "masks" variable.