femkeblanco
Guide
femkeblanco
Guide
Activity
‎Oct 04, 2023
12:21 PM
1 Upvote
Create a color group with the desired colors in the desired order, select the color group and the text, and run var colors = app.activeDocument.swatches.getSelected();
var chars = app.selection[0].characters;
var counter = 0;
for (var i = 0; i < chars.length; i++) {
if (chars[i].contents != " ") {
chars[i].characterAttributes.fillColor = colors[counter].color;
if (counter < colors.length - 1) counter++;
else counter = 0;
}
}
... View more
‎Oct 04, 2023
11:12 AM
Is there a set of colors to choose from, or should the script generate the colors? Should the color be different from the color of the preceding letter, or all preceding letters in a body of text?
... View more
‎Oct 02, 2023
12:09 PM
The best way to get an answer is to attach a sample file using filesharing that represents what you have.
... View more
‎Oct 02, 2023
04:05 AM
2 Upvotes
geometricBounds = [left, top, right, bottom] Or
... View more
‎Oct 02, 2023
03:48 AM
Not extensively tested. var doc = app.activeDocument;
// get (selected) paths
var paths = [];
recurse(doc.selection);
function recurse(items) {
for (var i = 0; i < items.length; i++) {
if (items[i].typename == "PathItem") {
paths.push(items[i]);
} else if (items[i].typename == "GroupItem") {
recurse(items[i].pageItems);
} else if (items[i].typename == "CompoundPathItem") {
recurse(items[i].pathItems);
}
}
}
// get colors
var colors = [];
for (var i = 0; i < paths.length; i++) {
if (!isInArray(paths[i].strokeColor, colors)) {
colors.push(paths[i].strokeColor);
}
if (!isInArray(paths[i].fillColor, colors)) {
colors.push(paths[i].fillColor);
}
}
// get swatches
var swatches = [];
for (var i = 0; i < colors.length; i++) {
var swatch = doc.swatches.add();
swatch.color = colors[i];
for (var j = 0; j < doc.swatches.length; j++) {
if (areEqual(colors[i], doc.swatches[j].color)) {
swatch.name = doc.swatches[j].name;
break;
}
}
swatches.push(swatch);
}
// create swatchGroup
var swatchGroup = doc.swatchGroups.add();
swatchGroup.name = "Custom";
for (var i = 0; i < swatches.length; i++) {
swatchGroup.addSwatch(swatches[i]);
}
function isInArray(e, a) {
for (var i = 0; i < a.length; i++) {
if (areEqual(e, a[i])) {
return true;
}
}
return false;
}
function areEqual(o1, o2) {
for (var k in o1) {
if (o1.hasOwnProperty(k)) {
if (!o2.hasOwnProperty(k)) return false;
if (o1[k] != o2[k]) return false;
}
}
for (var k in o2) {
if (o2.hasOwnProperty(k)) {
if (!o1.hasOwnProperty(k)) return false;
if (o1[k] != o2[k]) return false;
}
}
return true;
}
... View more
‎Sep 27, 2023
10:27 AM
5 Upvotes
And here's a script that draws three types of Apollonian gaskets. This is adapted from a browser script that is dependent on the size of the canvas. I've kept it at the same size (400 pt) so as to show the same results; they can of course be manually scaled. (NB. All credit to the original creator; I just rewrote it for Illustrator.) // part 1: Complex class (manipulates complex numbers)
// abridged from Complex.js by Robert Eisele
// https://rawgit.com/infusion/Complex.js/master/complex.js
var parse = function (a, b) {
var z = {
're': 0,
'im': 0
};
if (a == undefined || a == null) {
z['re'] = z['im'] = 0;
} else if (b != undefined) {
z['re'] = a;
z['im'] = b;
} else
if (typeof a == 'object') {
z['re'] = a['re'];
z['im'] = a['im'];
} else if (typeof a == 'number') {
z['im'] = 0;
z['re'] = a;
}
return z;
};
var Complex = function (a, b) {
if (!(this instanceof Complex)) {
return new Complex(a, b);
}
var z = parse(a, b);
this['re'] = z['re'];
this['im'] = z['im'];
};
Complex.prototype = {
're': 0,
'im': 0,
'add': function(a, b) {
var z = new Complex(a, b);
return new Complex(
this['re'] + z['re'],
this['im'] + z['im']);
},
'sub': function(a, b) {
var z = new Complex(a, b);
return new Complex(
this['re'] - z['re'],
this['im'] - z['im']);
},
'mul': function(a, b) {
var z = new Complex(a, b);
if (z['im'] == 0 && this['im'] == 0) {
return new Complex(this['re'] * z['re'], 0);
}
return new Complex(
this['re'] * z['re'] - this['im'] * z['im'],
this['re'] * z['im'] + this['im'] * z['re']);
},
'div': function(a, b) {
var z = new Complex(a, b);
a = this['re'];
b = this['im'];
var c = z['re'];
var d = z['im'];
var t, x;
if (0 == d) {
return new Complex(a / c, b / c);
}
if (Math.abs(c) < Math.abs(d)) {
x = c / d;
t = c * x + d;
return new Complex(
(a * x + b) / t,
(b * x - a) / t);
} else {
x = d / c;
t = d * x + c;
return new Complex(
(a + b * x) / t,
(b - a * x) / t);
}
},
'sqrt': function() {
var a = this['re'];
var b = this['im'];
var r = this['abs']();
var re, im;
if (a >= 0) {
if (b == 0) {
return new Complex(Math.sqrt(a), 0);
}
re = 0.5 * Math.sqrt(2.0 * (r + a));
} else {
re = Math.abs(b) / Math.sqrt(2 * (r - a));
}
if (a <= 0) {
im = 0.5 * Math.sqrt(2.0 * (r - a));
} else {
im = Math.abs(b) / Math.sqrt(2 * (r + a));
}
return new Complex(re, b < 0 ? -im : im);
},
'abs': function() {
return Math.sqrt(this['re'] * this['re'] + this['im'] * this['im']);
}
};
// part 2: main
// adapted from Apollonian gasket by pimskie
// https://codepen.io/pimskie
var doc = app.activeDocument;
var DIM = 400;
var MID = DIM * 0.5;
var MIN_R = 2;
var Circle = function(r, center) {
this.r = r;
this.b = 1 / this.r;
this.center = center;
this.bc = this.center.mul(this.b);
};
var solveEquation = function(k1, k2, k3) {
var s = k1.add(k2).add(k3);
var k12 = k1.mul(k2);
var k13 = k1.mul(k3);
var k23 = k2.mul(k3);
var ksum = k12.add(k13).add(k23);
return ksum.sqrt().mul(2).add(s);
};
var getAdjacent = function(c1, c2, c3) {
var b1 = new Complex(c1.b);
var b2 = new Complex(c2.b);
var b3 = new Complex(c3.b);
var b4 = solveEquation(b1, b2, b3);
var r4 = Math.abs(1 / b4.re);
var pos4 = solveEquation(c1.bc, c2.bc, c3.bc).div(b4);
return new Circle(r4, pos4);
};
var flip = function(c4, c1, c2, c3) {
var bend = 2 * (c1.b + c2.b + c3.b) - c4.b;
var center = c1.bc.add(c2.bc).add(c3.bc).mul(2).sub(c4.bc).div(bend);
return new Circle(1 / bend, center);
};
var addCircle = function (circle) {
circles.push(circle);
};
var recurse = function(c1, c2, c3, c4, depth) {
depth = depth || 0;
var cn2 = flip(c2, c1, c3, c4);
var cn3 = flip(c3, c1, c2, c4);
var cn4 = flip(c4, c1, c2, c3);
if (cn2.r > MIN_R) {
addCircle(cn2);
recurse(cn2, c1, c3, c4, depth + 1);
}
if (cn3.r > MIN_R) {
addCircle(cn3);
recurse(cn3, c1, c2, c4, depth + 1);
}
if (cn4.r > MIN_R) {
addCircle(cn4);
recurse(cn4, c1, c2, c3, depth + 1);
}
};
var drawGasket = function(c1, c2, c3) {
var c4 = getAdjacent(c1, c2, c3);
var c5 = flip(c1, c2, c3, c4)
addCircle(c1);
addCircle(c2);
addCircle(c3);
addCircle(c4);
addCircle(c5);
recurse(c1, c2, c3, c4);
recurse(c5, c2, c3, c4);
};
var symmetricSet = function() {
var c1r = -MID;
var c1center = new Complex(MID, MID);
var c1 = new Circle(c1r, c1center);
var c2r = 100;
var c2center = new Complex(c2r, MID);
var c2 = new Circle(c2r, c2center);
var c3r = Math.abs(c1.r) - c2.r;
var c3x = c2.center.re + c2.r + c3r;
var c3y = c2.center.im;
var c3center = new Complex(c3x, c3y);
var c3 = new Circle(c3r, c3center);
return [
[c1, c2, c3]
];
};
var aSymmetricSet = function() {
var c1r = -MID;
var c1center = new Complex(MID, MID);
var c1 = new Circle(c1r, c1center);
var c2r = 160;
var c2center = new Complex(c2r, MID);
var c2 = new Circle(c2r, c2center);
var c3r = Math.abs(c1.r) - c2.r;
var c3x = c2.center.re + c2.r + c3r;
var c3y = c2.center.im;
var c3center = new Complex(c3x, c3y);
var c3 = new Circle(c3r, c3center);
return [
[c1, c2, c3]
];
};
var nestedSet = function() {
var c1r = -MID;
var c1center = new Complex(MID, MID);
var c1 = new Circle(c1r, c1center);
var c2r = 160;
var c2center = new Complex(MID, c2r);
var c2 = new Circle(c2r, c2center);
var c3r = MID - 160;
var c3center = new Complex(MID, DIM - c3r);
var c3 = new Circle(c3r, c3center);
var ci1r = -c2r;
var ci1center = new Complex(MID, Math.abs(ci1r));
var ci1 = new Circle(ci1r, ci1center);
var ci2r = Math.abs(ci1r) / 2;
var ci2center = new Complex(MID, ci2r);
var ci2 = new Circle(ci2r, ci2center);
var ci3r = Math.abs(ci1r) - ci2.r;
var ci3x = ci2.center.re;
var ci3y = ci2r + ci2r + ci3r;
var ci3center = new Complex(ci3x, ci3y);
var ci3 = new Circle(ci3r, ci3center);
return [
[c1, c2, c3],
[ci1, ci2, ci3]
];
};
var sets = {
'Symmetric': symmetricSet(),
'Asymmetric': aSymmetricSet(),
'Nested': nestedSet()
};
var drawCircle = function (c) {
var absR = Math.abs(c.r);
var d = absR * 2;
var dx = (doc.width - DIM) / 2 - d / 2;
var dy = (doc.height - DIM) / 2 - d / 2;
return doc.pathItems.ellipse(
-c.center.im - dy, c.center.re + dx,
d, d);
};
var circles;
var group;
var draw = function(selectedSet) {
circles = [];
group = doc.groupItems.add();
group.name = selectedSet;
var set = sets[selectedSet];
for (var i = 0; i < set.length; i++) {
var gasket = set[i];
drawGasket(gasket[0], gasket[1], gasket[2]);
}
for (var i = 0; i < circles.length; i++) {
drawCircle(circles[i]).moveToBeginning(group);
}
};
draw('Symmetric');
app.redraw();
// part 3: ScriptUI
var w = new Window("dialog");
var g = w.add("group");
var b1 = g.add("button", undefined, "Symmetric");
b1.preferredSize.width = 100;
var b2 = g.add("button", undefined, "Asymmetric");
b2.preferredSize.width = 100;
var b3 = g.add("button", undefined, "Nested");
b3.preferredSize.width = 100;
var b4 = w.add("button", undefined, "OK");
b4.preferredSize.width = 100;
var f1 = function (p1) {
doc.groupItems.removeAll();
draw(p1);
app.redraw();
};
b1.onClick = function () {
f1(b1.text);
};
b2.onClick = function () {
f1(b2.text);
};
b3.onClick = function () {
f1(b3.text);
};
w.show();
... View more
‎Sep 27, 2023
05:38 AM
1 Upvote
Or app.selection = null;
... View more
‎Sep 18, 2023
02:41 PM
I think what you want is exportForScreens. This is not available to me in CS6, so I cannot help you. But you can look at these links.
... View more
‎Sep 18, 2023
02:31 PM
var myName = "myPDF";
var myFile = new File("~/Desktop/" + myName);
var myPDF = new PDFSaveOptions();
myPDF.pDFPreset = "[PDF/X-4:2008]";
app.activeDocument.saveAs(myFile, myPDF);
// app.activeDocument.close(); You can change the name of the file in line 1, the location the file is saved to (presetnly the desktop) in line 2, or the name of the preset in line 4. Uncomment (remove // from) line 6 to close the doc after it is saved.
... View more
‎Sep 15, 2023
11:03 AM
1 Upvote
Mordy Golding has a video that I think explains things https://www.youtube.com/watch?v=GNxAmAIkuhM
... View more
‎Sep 12, 2023
10:29 AM
@Ton Frederiks I've added a line that makes the paths closed.
... View more
‎Sep 10, 2023
02:42 PM
3 Upvotes
Here's a script that draws a Sierpinski triangle that fits the open document. The number of recursions can be changed by changing the number of "levels" in line 2, although it is advised not to go too much above 10, otherwise Illustrator may become unresponsive. Adapted from: https://www.youtube.com/watch?v=e3Ll0_oxChU function main() {
var level = 5;
var doc = app.activeDocument;
function drawTriangle(p1, p2, p3) {
var path1 = doc.pathItems.add();
path1.setEntirePath([p1, p2, p3, p1]);
path1.closed = true;
}
function getMidpoint(p1, p2) {
return [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2];
}
var Triangle = function(p1, p2, p3) {
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.draw = function() {
drawTriangle(this.p1, this.p2, this.p3);
}
}
function drawSierpinskiTriangle(tri, depth) {
if (depth == level) return;
var m1 = getMidpoint(tri.p1, tri.p2);
var m2 = getMidpoint(tri.p2, tri.p3);
var m3 = getMidpoint(tri.p3, tri.p1);
var t0 = new Triangle(m1, m2, m3);
t0.draw();
var t1 = new Triangle(tri.p1, m1, m3);
var t2 = new Triangle(tri.p2, m1, m2);
var t3 = new Triangle(tri.p3, m2, m3);
drawSierpinskiTriangle(t1, depth + 1);
drawSierpinskiTriangle(t2, depth + 1);
drawSierpinskiTriangle(t3, depth + 1);
}
var size = doc.width < doc.height ? doc.width : doc.height;
var t = new Triangle(
[size / 2, 0],
[0, -size],
[size, -size]
);
t.draw();
drawSierpinskiTriangle(t, 0);
}
main();
... View more
‎Sep 08, 2023
10:54 AM
AI scripts are forward compatible. Any script that worked in 2013 should work in 2023.
... View more
‎Sep 07, 2023
03:16 PM
1 Upvote
Select items to rotate. var doc = app.activeDocument;
var targetItem = doc.pageItems.getByName("Target");
var targetPoint = [
targetItem.left + targetItem.width / 2,
targetItem.top - targetItem.height / 2
];
var selection = doc.selection;
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
var itemCenter = [item.left + item.width / 2, item.top - item.height / 2];
var deltaX = targetPoint[0] - itemCenter[0];
var deltaY = targetPoint[1] - itemCenter[1];
var angle = (Math.atan2(deltaY, deltaX) * (180 / Math.PI)) - 90;
item.rotate(angle);
}
... View more
‎Sep 07, 2023
11:48 AM
2 Upvotes
Not tested. Save before trying. var paths = app.activeDocument.pathItems;
for (var i = paths.length - 1; i > - 1; i--) {
if (paths[i].pathPoints.length <= 2) {
var ps = paths[i].pathPoints;
if (ps[0].anchor.toString() == ps[1].anchor.toString() &&
ps[0].rightDirection.toString() == ps[1].rightDirection.toString() &&
ps[0].leftDirection.toString() == ps[1].leftDirection.toString()) {
paths[i].remove();
}
}
}
... View more
‎Sep 05, 2023
12:29 PM
It's possible to write a script with a user interface so as to increase/decrease the number and/or size of dots to the user's liking. The outcome will be a group of paths though, not a pattern.
... View more
‎Sep 01, 2023
02:38 PM
1 Upvote
If I understand correctly, you want to select the colored squares, run the script and have it write the names of the corresponding swatches to the right of the squares. var doc = app.activeDocument;
var targets = doc.selection;
for (var i = 0; i < targets.length; i++) {
var size = targets[i].height / 2;
var text = doc.textFrames.pointText( [
targets[i].left + targets[i].width * 1.5,
targets[i].top - targets[i].height * 0.75 + size * 0.2,
] );
text.textRange.characterAttributes.size = size;
for (var j = 0; j < doc.swatches.length; j++) {
if (areEqual(targets[i].fillColor, doc.swatches[j].color)) {
text.contents = doc.swatches[j].name;
}
}
}
function areEqual(o1, o2) {
for (var k in o1) {
if (o1.hasOwnProperty(k)) {
if (!o2.hasOwnProperty(k)) return false;
if (o1[k] != o2[k]) return false;
}
}
for (var k in o2) {
if (o2.hasOwnProperty(k)) {
if (!o1.hasOwnProperty(k)) return false;
if (o1[k] != o2[k]) return false;
}
}
return true;
}
... View more
‎Aug 27, 2023
02:48 AM
This version should have that option: https://assets.adobe.com/public/7cf1dee2-08bc-435f-6fbc-546d36937712
... View more
‎Aug 27, 2023
02:43 AM
1 Upvote
You could try pushing the top level groups and sublayers into arrays, concatenating the arrays, then reverse sorting the concatenated array by absoluteZOrderPosition. The sorted array should be a combined collection of groups and sublayers in the order shown in the Layers panel. absoluteZOrderPosition does not work in CS6, so I cannot try it.
... View more
‎Aug 26, 2023
01:30 PM
I still fear we are talking at cross purposes, but here goes. Iterate the collection, comparing the specified (e.g. selected) item with each item in the collection. When they are the same item, you have your index: var groups = app.activeDocument.layers["edit clipart"].groupItems;
for (var i = 0; i < groups.length; i++) {
if (app.selection[0] == groups[i]) {
alert(i);
}
}
... View more
‎Aug 26, 2023
02:12 AM
1 Upvote
Could you expound on the question? As I presently understand it, the question is how to find the index of a specified item in a collection (which begs the question of why want the index if the item is specified).
... View more
‎Aug 17, 2023
02:28 PM
Script-wise, it's easy in theory: Create a grid (2D array) of pixels, by iterating through so many pixels at a time, getting their positions and gray colors, then drawing circles at those positions with diameters proportional to the gray colors. In practice, pixels need to be accessed throught Photoshop and the above requires at least one back-and-forth between Illustrator and Photoshop through BridgeTalk. My Photoshop and BridgeTalk experience is limited.
... View more
‎Aug 15, 2023
01:17 PM
I don't know why, but changing colorType to PROCESS throws a PARM error if the color mode (read as spotKind) is Lab. The only way I could proceed was by changing the color/color mode. if (checkbox.value) {
// alert(checkbox.spotColor.spotKind);
try {
checkbox.spotColor.color = checkbox.spotColor.color;
checkbox.spotColor.colorType = ColorModel.PROCESS;
} catch (e) {
alert(e);
}
}
... View more
‎Aug 11, 2023
03:06 PM
1 Upvote
If all you want is to convert an array of strings to an array of objects: var array1 = ["a,b,c", "a1,b1,c1", "a2,b2,c2", "a3,b3,c3"];
var array2 = [];
for (var i = 1; i < array1.length; i++) {
var temp1 = array1[0].split(",");
var temp2 = array1[i].split(",");
var o = {};
for (var j = 0; j < temp2.length; j++) {
o[temp1[j]] = temp2[j];
}
array2.push(o);
}
// array2 = [
// {
// a: "a1",
// b: "b1",
// c: "c1"
// },
// {
// a: "a2",
// b: "b2",
// c: "c2"
// },
// {
// a: "a3",
// b: "b3",
// c: "c3"
// }
// ]
... View more
‎Aug 11, 2023
10:56 AM
Do you mean something like this? var path1;
var w = new Window("dialog");
var checkbox = w.add("checkbox");
checkbox.onClick = function() {
if (checkbox.value == true) {
main();
app.redraw();
}
if (checkbox.value == false) {
path1.remove();
app.redraw();
}
}
var button = w.add("button", undefined, "Done");
button.onClick = function() {
w.close();
}
w.show();
// example
function main () {
var doc = app.activeDocument;
path1 = doc.pathItems.rectangle(
- doc.height / 4, doc.width / 4, doc.width / 2, doc.height / 2
);
}
... View more
‎Aug 10, 2023
01:53 PM
Just to define the problem more clearly, is this what you want to do (notwithstanding "selecting" the layer)? Test if a layer named "xyz" exists. (1) If this layer exists: (a) If this layer is empty (no pageItems and no sublayers), move this layer to the top. (b) If this layer is not empty, do nothing. (2) If this layer doesn't exist, add this layer to the top.
... View more
‎Aug 05, 2023
12:28 PM
1 Upvote
var doc = app.activeDocument;
doc.layers.add().name = "Images";
doc.layers.add().name = "Linked Files";
doc.layers.add().name = "Other";
for (var i = 0; i < doc.pageItems.length; i++) {
if (doc.pageItems[i].typename == "RasterItem") {
move(doc.pageItems[i], doc.layers["Images"]);
} else if (doc.pageItems[i].typename == "PlacedItem") {
move(doc.pageItems[i], doc.layers["Linked Files"]);
} else {
move(doc.pageItems[i], doc.layers["Other"]);
}
}
function move(what, where) {
what.move(where, ElementPlacement.PLACEATEND);
}
... View more
‎Aug 03, 2023
12:53 PM
2 Upvotes
Mouse events are limited in Illustrator scripting. You could try the up and down arrow keys: var width = 100;
var mm = new UnitValue(1 + " " + "mm").as("pt");
var doc = app.activeDocument;
var rec = doc.pathItems.rectangle(0, 0, width * mm, 100 * mm);
app.redraw();
var w = new Window("dialog");
var g = w.add("group");
var st = g.add("statictext", undefined, "W");
st.preferredSize.width = 100;
st.justify = "center";
var et = g.add("edittext", undefined, width);
et.preferredSize.width = 100;
et.justify = "center";
et.active = true;
et.addEventListener("keydown", function (e) {
f(e, et);
});
var b = w.add("button", undefined, "OK");
w.show();
function f(e, et) {
if (e.keyName == "Up") {
et.text = Number(et.text) + 1;
rec.width = et.text * mm;
}
if (e.keyName == "Down") {
et.text = Number(et.text) - 1;
rec.width = et.text * mm;
}
redraw();
}
... View more
‎Jul 27, 2023
09:49 AM
I copied a compound shape from Photoshop CS4 to Illustrator, and it still worked as expected for me. The only thing I can think of is if Illustrator is not reading it directly as a pluginItem, may be it will read it as a pageItem with a tracing object (pluginItems should be the only pageItems with such a property): for (var i = 0; i < app.activeDocument.pageItems.length; i++) {
if (app.activeDocument.pageItems[i].tracing) {
app.activeDocument.pageItems[i].selected = true;
}
}
... View more
‎Jul 27, 2023
08:37 AM
1 Upvote
The first two lines above work as expected for me, in that they select the first pluginItem in the doc. So the immediate question is, are you really dealing with pluginItems? If you select the items in question and run var a = "";
for (var i = 0; i < app.activeDocument.selection.length; i++) {
a += app.activeDocument.selection[i].typename + "\n";
}
alert(a); what does the alert say?
... View more