Copy link to clipboard
Copied
I am attempting to write a JSFL script to replace the fill colors of shape elements in selected frames using a mapping table.
I can access a shape's fill properties but I cannot set them even though the documentation leads me to believe these properties are read/write.
When I omit the element.beginEdit() and element.endEdit() calls, the script completes successfully but the colors are not actually updated. When I include the beginEdit/endEdit my script crashes the first time i access the fill property with the error message "The following JavaScript error(s) occurred:" with no other information.
I have tried this in CS5.5, CS6 and CC, and it always fails the same way.
Am I doing something wrong or is it a bug? If it is a bug, has anyone found a work around? I appreciate any tips you can give me.
The script:
var replaceFills = {
'#ff0000': '#33cccc',
'#33cccc': '#ff0000',
'#66ff00': '#00ffff',
'#00ffff': '#66ff00',
'#2173a6': '#ff00ff',
'#ff00ff': '#2173a6',
'#195480': '#ff00ff',
'#ff00ff': '#195480', };
function recolor(element) {
if (element.elementType == "shape") {
element.beginEdit();
for (var j = 0; j < element.contours.length; j++) {
var c = element.contours
if (c.interior) {
if (c.fill.style == 'solid') {
if (c.fill.color in replaceFills) {
c.fill.color = replaceFills[c.fill.color];
}
}
}
}
element.endEdit();
}
}
function recolorFrame(frame) {
var elements = frame.elements;
for (var i = 0; i < elements.length; i++)
recolor(elements);
}
var curSelected = fl.getDocumentDOM().getTimeline().getSelectedFrames();
for (var i = 0; i < curSelected.length; i += 3) {
var layerIndex = curSelected;
var startIndex = curSelected[i + 1];
var endIndex = curSelected[i + 2];
var layer = fl.getDocumentDOM().getTimeline().layers[layerIndex];
for (var j = startIndex; j < endIndex; j++) {
var frame = layer.frames
if (j == frame.startFrame)
recolorFrame(frame);
}
}
Thanks,
Bill
Copy link to clipboard
Copied
Is it possible that you're trying to access the fill of a contour with a null fill? I don't see any null checks in your code.
Copy link to clipboard
Copied
Thanks for the tip but even accessing the fill field like if(!c.fill) fl.trace("Null fill");
results in the same error. The contour c is definitely not null because the c.interior
check works.
Copy link to clipboard
Copied
Just to make sure I'm understanding you--you've tried it with just
if (!c.fill) {
fl.trace('null fill');
}
and you've removed all references to c.fill.color and c.fill.style? And that still errors?
Also, what happens if you remove the empty element from your array?
Copy link to clipboard
Copied
OK, it looks like you can only get a usable fill object with getCustomFill(). So, if you need to edit on a per-contour basis, you're probably SOL. However, I found that this code works for one object on one frame. You'll probably need to edit it to make sure each object is selected before you fill it.
function recolorFrame(frame) {
var elements = frame.elements;
for (var i = 0; i < elements.length; i++) {
recolor(elements);
}
}function recolor(element) {
if (element.elementType == "shape") {
var fill = fl.getDocumentDOM().getCustomFill(element);
fill.color = '#FF0000';
fl.getDocumentDOM().setCustomFill(fill);
}
}var curSelected = fl.getDocumentDOM().getTimeline().getSelectedFrames();
for (var i = 0; i < curSelected.length; i += 3) {
var layerIndex = curSelected;
var startIndex = curSelected[i + 1];
var endIndex = curSelected[i + 2];
var layer = fl.getDocumentDOM().getTimeline().layers[layerIndex];
for (var j = startIndex; j < endIndex; j++) {
var frame = layer.frames
; if (j == frame.startFrame) recolorFrame(frame);
}
}
Copy link to clipboard
Copied
Thanks for your help. I do need to change the fill per contour and since I don't think I can select a contour via jsfl I guess what I want to do is not possible.
It seems odd though that the fill attribute is not modifiable. The docs don't say anything about it being read only.
Copy link to clipboard
Copied
The docs do say that the way to get a fill is through getCustomFill().
One thing you may find useful is that Search and Replace can operate per "scene", which translates to the local timeline, and it will remember your color choices. So you can use that if you can open each timeline and apply it, then repeat for the next color. You may even find something in the History when you do that that will help you.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now