Copy link to clipboard
Copied
I've got a section of code (shown below) that creates two spot colours and applies the first to all white elements, this works as intended.
The second fill needs to be applied to the selection after offset path section of the script but doesn't seem to be working at filling anything.
I've tried a workaround that fills the selection by locking the first layer, creating a new layer, pasting in place and applying the fill. This works in applying the fill but then I'm unable to unlock the layer I locked previously anymore?
Ideally I'd just like to be able to apply the swatch 'Underbase' to the selection after the offset path.
Any ideas? Thank you in advance?
addSpot('White Overprint', 39, 0, 39, 0);
function addSpot(name, c, m, y, k) {
try {
swatch = app.activeDocument.swatches[name]; // if swatch exists....
addSpot(name += '1', c, m, y, k); // ...add 1 to swatch name
} catch (e) {
var newSpot = app.activeDocument.spots.add();
newSpot.name = name;
var newColor = new CMYKColor();
newColor.cyan = c;
newColor.magenta = m;
newColor.yellow = y;
newColor.black = k;
newSpot.colorType = ColorModel.SPOT;
newSpot.color = newColor;
var newSpotColor = new SpotColor();
newSpotColor.spot = newSpot;
}
}
// Get the swatch called "White Overprint"
var swatch = app.activeDocument.swatches.getByName("White Overprint");
// Loop through all path items in the document
for (var i = 0; i < app.activeDocument.pathItems.length; i++) {
var pathRef = app.activeDocument.pathItems[i];
// Check if the path item's fill color is white
if (pathRef.fillColor.typename === "CMYKColor" && pathRef.fillColor.cyan == 0 && pathRef.fillColor.magenta == 0 && pathRef.fillColor.yellow == 0 && pathRef.fillColor.black == 0) {
pathRef.filled = true;
pathRef.fillColor = swatch.color;
}
}
///app.executeMenuCommand("OffsetPath v23");
var idoc = app.activeDocument;
var sel = idoc.selection[0];
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
var offset = "-0.3";
// offset path Effect with Round Joins
var xmlstringOffsetPath = '<LiveEffect name="Adobe Offset Path"><Dict data="R mlim 4 R ofst value I jntp 0 "/></LiveEffect>'; // 0 = round, 1=bevel, 2=miter
xmlstringOffsetPath = xmlstringOffsetPath.replace("value", offset);
idoc.selection = null;
var dup = sel.duplicate(sel, ElementPlacement.PLACEAFTER);
try {
dup.filled = false;
} catch (e) {}
dup.selected = true; // select it before applying effects
// apply offset path Effect
dup.applyEffect(xmlstringOffsetPath);
app.redraw();
// expand appearance
app.executeMenuCommand('expandStyle');
app.userInteractionLevel = UserInteractionLevel.DISPLAYALERTS;
app.executeMenuCommand('cut');
app.executeMenuCommand('AdobeLayerPalette2');
app.executeMenuCommand('pasteInPlace');
// Get Layer 1
var layer1 = app.activeDocument.layers.getByName("Layer 1");
// Lock Layer 1
layer1.locked = true;
addSpot('Underbase', 100, 0, 0, 0);
function addSpot(name, c, m, y, k) {
try {
swatch2 = app.activeDocument.swatches[name]; // if swatch exists....
addSpot(name += '1', c, m, y, k); // ...add 1 to swatch name
} catch (e) {
var newSpot = app.activeDocument.spots.add();
newSpot.name = name;
var newColor = new CMYKColor();
newColor.cyan = c;
newColor.magenta = m;
newColor.yellow = y;
newColor.black = k;
newSpot.colorType = ColorModel.SPOT;
newSpot.color = newColor;
var newSpotColor = new SpotColor();
newSpotColor.spot = newSpot;
}
}
// Get the swatch called "Underbase"
var swatch = app.activeDocument.swatches.getByName("Underbase");
// Loop through all path items in the document
for (var i = 0; i < app.activeDocument.pathItems.length; i++) {
var pathRef = app.activeDocument.pathItems[i];
pathRef.filled = true;
pathRef.fillColor = swatch.color;
}
}
// Get Layer 1
var layer1 = app.activeDocument.layers.getByName("Layer 1");
// Lock Layer 1
layer1.locked = false;
app.executeMenuCommand('Selectall');
app.executeMenuCommand('group');
Hi @RussellBeswick, I would advise you to divide this script into two scripts: one to apply the white overprint to all white pathItems, and another to apply the underbase to selected pathItems. Your script seemed confused about these two roles and in my script I assumed you meant to apply the underbase to all pathItems also.
As for "occasionally the fill doesn't apply to all items", this is almost certainly mostly due to CompoundPathItems. Setting the fillColor of a CompoundPathItem doesn't wo
...Could the 'Underbase' swatch be applied to path items in a named group/sublayer?
Sure. It all comes down to how you get the items. In your script (and my version) we use the pathItems property of Document (eg. app.activeDocument.pathItems). But Layer and GroupItem objects also have a pathItems property. So if you name a group (in the Layers Panel), "Special", for example, you can get a reference to it like this:
var doc = app.activeDocument,
group = doc.groupItems.getByName('Special'),
...
Copy link to clipboard
Copied
Hi @RussellBeswick, I'm not sure I've understood exactly what you are doing, but I hope I've got the gist.
I've re-written your script and I hope, even if it isn't exactly what you need, it will give you a good leg-up.
/**
* @discussion https://community.adobe.com/t5/illustrator-discussions/applying-spot-colour-to-selection-help-unlocking-layer/m-p/13621584
*/
(function () {
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
app.selection = null;
var doc = app.activeDocument;
var whiteOverprintSpot = addSpot(doc, 'White Overprint', 39, 0, 39, 0);
var underbaseSpot = addSpot(doc, 'Underbase', 100, 0, 0, 0);
var underbaseLayer = addLayer(doc, 'Underbase');
var items = [];
for (var i = 0; i < doc.pathItems.length; i++)
items.push(doc.pathItems[i]);
// Loop through all path items in the document
for (var i = 0; i < items.length; i++) {
var item = items[i];
// Check if the path item's fill color is white
// note: this won't trigger if white global color
if (
item.fillColor.typename === "CMYKColor"
&& item.fillColor.cyan == 0
&& item.fillColor.magenta == 0
&& item.fillColor.yellow == 0
&& item.fillColor.black == 0
) {
item.filled = true;
item.fillColor = whiteOverprintSpot;
}
if (item.fillColor.spot !== underbaseSpot.spot) {
var dup = makeOffsetDuplicate(item, '-0.3', underbaseLayer);
dup.filled = true;
dup.fillColor = underbaseSpot;
dup.fillOverprint = true;
}
}
function makeOffsetDuplicate(item, offset, layer) {
app.selection = null;
// offset path Effect with Round Joins
var xmlstringOffsetPath = '<LiveEffect name="Adobe Offset Path"><Dict data="R mlim 4 R ofst value I jntp 0 "/></LiveEffect>'; // 0 = round, 1=bevel, 2=miter
xmlstringOffsetPath = xmlstringOffsetPath.replace("value", offset);
var dup = item.duplicate(layer, ElementPlacement.PLACEATEND);
dup.selected = true; // select it before applying effects
dup.stroked = false; // not sure what you want to do with strokes? (maybe pathfinder unite?)
// apply offset path Effect
dup.applyEffect(xmlstringOffsetPath);
app.redraw();
// expand appearance
app.executeMenuCommand('expandStyle');
// get reference to the expanded page item
dup = layer.pageItems[layer.pageItems.length - 1];
app.selection = null;
return dup;
}
function addSpot(doc, name, c, m, y, k) {
var mySpot;
try {
mySpot = doc.swatches.getByName(name).color; // if swatch exists....
} catch (e) {
var newSpot = doc.spots.add();
newSpot.name = name;
var newColor = new CMYKColor();
newColor.cyan = c;
newColor.magenta = m;
newColor.yellow = y;
newColor.black = k;
newSpot.colorType = ColorModel.SPOT;
newSpot.color = newColor;
mySpot = new SpotColor();
mySpot.spot = newSpot;
}
return mySpot;
}
/**
* Adds a layer to document.
* If layer `name` exists, will return it,
* or will create a new layer.
* @param {Document} doc - an Illustrator document.
* @param {String} name - the name of the layer.
* @param {Boolean} [addSerialNumber] - whether to add a unique serial number (default false).
* @returns
*/
function addLayer(doc, name, addSerialNumber) {
var newLayer;
try {
newLayer = doc.layers.getByName(name);
if (addSerialNumber) {
var nameParts = name.split(/\s(\d+)$/),
nextSerialNumber = nameParts.length == 2 ? Number(nameParts[1]) + 1 : 1;
return addLayer(doc, nameParts[0] + ' ' + nextSerialNumber);
}
} catch (e) {
newLayer = doc.layers.add()
newLayer.name = name;
}
// do you want it moved to the bottom layer order?
// newLayer.move(doc, ElementPlacement.PLACEATEND);
return newLayer;
};
})();
Note: I tend to always put Illustrator script inside an IIFE because Illustrator has a weird polluted global name space. Basically you can access any property of App just by accessing the name of that property and it can't be overwritten in the global scope. See this:
(function () {
var name = 'The Name I Want'
$.writeln('name inside IIFE: ' + name)
})();
var name = 'The Name I Want'
$.writeln('name outside of IIFE: ' + name)
Results in this:
name inside IIFE: The Name I Want
name outside of IIFE: Adobe Illustrator
And no errors are thrown!
- Mark
Copy link to clipboard
Copied
Thanks very much for the response and time you've put in Mark @m1b .
This seems to apply the two spot colours but individually through the path elements of which there are anywhere between 10 and 1000+
I'm looking for it to apply the White Overprint to all items with a white fill, before running the offset path and then applying the 'Underbase' swatch to the offset version which is selected.
I've found that occasionally the fill doesn't apply to all items, could this be when there is a multiple different object types within the selection when running?
It might make more sense in the context of the whole script but this is just a small part and wouldn't want it being too much for advice on. It's also a functional mess which mostly works within my limited knowledge.
Copy link to clipboard
Copied
Hi @RussellBeswick, I would advise you to divide this script into two scripts: one to apply the white overprint to all white pathItems, and another to apply the underbase to selected pathItems. Your script seemed confused about these two roles and in my script I assumed you meant to apply the underbase to all pathItems also.
As for "occasionally the fill doesn't apply to all items", this is almost certainly mostly due to CompoundPathItems. Setting the fillColor of a CompoundPathItem doesn't work—you must set the fillColor of the first pathItem of the CompoundPathItem. The script can be extended to accommodate by adding this sort of thing:
if (item.typename == 'CompoundPathItem') {
item.pathItems[0].fillColor = whiteOverprintSpot;
}
else {
item.fillColor = whiteOverprintSpot;
}
Did you notice my use of functions addSpot and addLayer and makeOffsetDuplicate? By chunking down and de-coupling logical actions/objects into functions, not only does it save code-duplication, but it means you can test just individual bits of code easily—by checking if the function reliably returns a given output (or has a desired effect) for a given input. When you have bugs in your code, it helps to check what input a function is getting and whether it is handling it correctly, and what output a function is returning and whether it is the expected value, type, object, etc.
- Mark
Copy link to clipboard
Copied
Thanks for all this Mark @m1b, I'll look into using your suggested functions and IIFE's. I'll test out the fill you suggested for those cases it's not working as intended as well, thank you!
Could the 'Underbase' swatch be applied to path items in a named group/sublayer?
Copy link to clipboard
Copied
Could the 'Underbase' swatch be applied to path items in a named group/sublayer?
Sure. It all comes down to how you get the items. In your script (and my version) we use the pathItems property of Document (eg. app.activeDocument.pathItems). But Layer and GroupItem objects also have a pathItems property. So if you name a group (in the Layers Panel), "Special", for example, you can get a reference to it like this:
var doc = app.activeDocument,
group = doc.groupItems.getByName('Special'),
items = group.pathItems;
- Mark
Copy link to clipboard
Copied
To apply a spot color to a selection in your design software, such as Adobe Illustrator , follow these steps:
Select the object or objects that you want to apply the spot color to.
In the Swatches panel, select the spot color that you want to apply. If the spot color is not already in your Swatches panel, you can add it by clicking on the New Swatch button and selecting the color type as "Spot Color."
With the object or objects still selected, click on the Fill or Stroke color swatch in the Tools panel to apply the spot color to either the fill or stroke of the object.
As for unlocking a layer, if you are unable to select or edit an object on a layer in your design software, it's possible that the layer is locked. To unlock the layer, follow these steps:
In the Layers panel, select the layer that you want to unlock.
Click on the lock icon next to the layer name to unlock it. If the lock icon is not visible, the layer may already be unlocked.
You should now be able to select and edit objects on the unlocked layer.
By following these steps, you should be able to apply spot colors to your design and unlock layers for editing as needed.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now