user1876246
user1876246

Reputation: 1229

Script to fill objects with colours - uniform distribution but in no discernible pattern

I am working on writing a script for Adobe Illustrator in javascript to fill objects with selected colours.

I have 32 objects and 12 colour swatches. I want to fill the 32 objects using each colour twice and then fill the remainder 8 objects with a random selection. I want to fill the objects in no discernible pattern, so just looping through each object and assigning it the next swatch colour will not do.

This is what I have so far, however it is not using each colour at least twice and filling at random.

myObjects = app.activeDocument.selection;
myDocument = app.activeDocument;

if (myObjects instanceof Array) {
    colourSwatches = myDocument.swatches.getSelected();

    //if there are swatches
    if (colourSwatches.length != 0) {
        for (i = 0; i < myObjects.length; i++) {

            //if the selection is a path or compound path
            if (myObjects[i].typename == "PathItem" || myObjects[i].typename == "CompoundPathItem") {

                selItem = myObjects[i];
                selItem.filled = true;

                //select colour from swatches at random and then fill 
                swatchIndex = Math.round( Math.random() * (colourSwatches.length - 1 ));

                if (selItem.typename == "PathItem") {
                    selItem.fillColor = colourSwatches[swatchIndex].color;
                } else {
                    selItem.pathItems[0].fillColor = colourSwatches[swatchIndex].color;
                }
            }
        }
    }
}

Upvotes: 1

Views: 745

Answers (2)

akinuri
akinuri

Reputation: 12027

32 objects:

32 boxes

12 colors:

12 colors

var document     = app.activeDocument;
var objects      = document.selection; // 32 objects
var swatchColors = document.swatches.getSelected(); // 12 colors
var colors       = swatchColors; // 12 colors
colors           = colors.concat(swatchColors); // duplicate the 12 colors, 12*2 colors

// add 8 random colors
for (var i = 0; i < 8; i++) {
    // create random index in [0, 11]
    var randomIndex = Math.floor(Math.random() * swatchColors.length);
    // add the random color to colors array
    colors.push(swatchColors[randomIndex]);
    // remove the added color from the swatches so no extra duplicates
    swatchColors.splice(randomIndex, 1);
}

// now we have 32 objects and 32 colors
// in colors array, there are (12 * 2) + 8 random colors
for (var i = 0; i < objects.length; i++) {
    objects[i].fillColor = colors[i].color;
}

After execution:

Objects colored

Objects are iterated from top to bottom, left to right. This is the document.selection order. So the first 24 colors are applied in the same order they are in swatches. You can shuffle the colors if you want a random order.

Upvotes: 0

Jongware
Jongware

Reputation: 22457

Instead of picking swatches at random (that's where you lose control), do this:

  1. Build an array of your target size (32) and fill it with the required swatches (12). You don't have to randomize this array.
  2. For every object, pick a random entry.
  3. Remove the picked entry from the array.
  4. Loop until satisfied.

I.e., untested, but something like this:

var targetArray = [];
// fill with the set of required colors, times 2
for (i=0; i < 12; i++)
{
  targetArray[2*i] = i;
  targetArray[2*i+1] = i;
}
// fill up to contain 32 items
for (i=24; i<32; i++)
  targetArray[i] = Math.floor(Math.random() * colourSwatches.length);

(see Getting random value from an array for that random expression.)

Now you have an array containing the indexes for swatches to use. Loop over your objects and pick random items from the array until you are finished (which would be good) or you run out of items to pick (which would indicate your count of items to fill is not correct):

for (i = 0; i < myObjects.length; i++)
{
    arrayIndex = Math.floor(Math.random() * targetArray.length);
    swatchIndex = targetArray[arrayIndex];
    targetArray.splice (arrayIndex,1);
    selItem.fillColor = colourSwatches[swatchIndex].color;
}

Upvotes: 1

Related Questions