Copy link to clipboard
Copied
How to automatically move and align objects with scripts as below shown? Any help would be greatly appreciated, Thanks in advance!
Final effect:
Given simple line-art you can simply loop the items to correct their .top and .left properties. As these objects are the same dimensions with the example they will by definition already be aligned centrally to the targets.
Assuming that your layers are just as you have them:
var targetObjects = doc.layers.getByName("Target Position").pathItems;
var objectsToMove = [
doc.layers.getByName("To move aligned objects").layers[0].pathItems[0],
doc.layers.getByName("To move aligned objects").layers[1].
...As @Silly-V noted, if the objects are simple it's the script can be simple. When I tackled this a while back, I found the objects I needed to align are rarely simple so I wrote MatchObjects.jsx. Basically, you pick a source object (either the top or bottom object of your selection) and choose how to "match" all of the other objects in your selection to it. It does more than just aligning, but it may get you headed in the right direction. @Disposition_Dev helped with some edge cases for the `getV
...I actually created some alignment utilities for public use a while back. Given a "key object" and an array of objects you want to align, it handles all the positioning quirks (including the visible bounds thing that @jduncan mentioned).
The initial implementation was pretty clunky and awfully repetitive. So I just took some time and simpilified it. It used to be discreet functions for each different alignment option... silly. So i condensed it all down to one function called align() which take
...Copy link to clipboard
Copied
Given simple line-art you can simply loop the items to correct their .top and .left properties. As these objects are the same dimensions with the example they will by definition already be aligned centrally to the targets.
Assuming that your layers are just as you have them:
var targetObjects = doc.layers.getByName("Target Position").pathItems;
var objectsToMove = [
doc.layers.getByName("To move aligned objects").layers[0].pathItems[0],
doc.layers.getByName("To move aligned objects").layers[1].pathItems[0],
doc.layers.getByName("To move aligned objects").layers[2].pathItems[0]
];
for (var i = 0; i < objectsToMove.length; i++) {
objectsToMove[i].top = targetObjects[i].top;
objectsToMove[i].left = targetObjects[i].left;
}
This is a very rudimentary example and it can work with your specific situation because of the object dimensions and the order of target and source items is the same. The order actually does not have to be the same in the layers, as long as you ensure to put them into the same order within your code so when the loop runs, it will be directed to match the proper target and source items.
Copy link to clipboard
Copied
As @Silly-V noted, if the objects are simple it's the script can be simple. When I tackled this a while back, I found the objects I needed to align are rarely simple so I wrote MatchObjects.jsx. Basically, you pick a source object (either the top or bottom object of your selection) and choose how to "match" all of the other objects in your selection to it. It does more than just aligning, but it may get you headed in the right direction. @Disposition_Dev helped with some edge cases for the `getVisibleBounds()` that help with matching complex objects.
Copy link to clipboard
Copied
Thank you @jduncan very much for your explanation! I also found many useful scripts on your GitHub project, especially the rename layers JSX, it may solve a problem that has troubled me for a long time, in the following post. I need some time to learn how to use your script. Thank you again for sharing this.👍👍
Copy link to clipboard
Copied
😮 Sorry forgot to attach the link of my post:
Copy link to clipboard
Copied
Unfortunately, after my simple test, for rename layers JSX,its search range is only the parent layer and cannot include all the sublayers. Is it like this? Or do I not set it correctly? Do you perhaps have an idea what I may be overlooking? Thanks @jduncan .
Copy link to clipboard
Copied
So, I tried to piece together what you are looking to accomplish from the few different posts you have going right now. If you can get the layer duplication method (using actions) working that @Silly-V explained here, then with a slight tweak to my rename script will work for you.
After following @Silly-V's advice, you should have a bunch of duplicate layers in your layers palette (like left side in pic). The script below renames all of your base layers from 1 to however many layers you have. Then it recursively goes through every sublayer within each base layer and removes the "copy" text that gets added when you duplicate a layer.
Hope this helps!
// Do all of the layer duplications first as explained by Silly-V
// grab the current document and its layers
var doc = app.activeDocument;
var layers = doc.layers;
// iterate through all layers from bottom to top
for (var i = doc.layers.length - 1; i > -1; i--) {
doc.layers[i].name = Math.abs(i - doc.layers.length);
// recursively remove "copy" every sublayer
recursiveRename(doc.layers[i]);
}
function recursiveRename(parent) {
for (var i = 0; i < parent.layers.length; i++) {
parent.layers[i].name = parent.layers[i].name.replace(/\scopy.*$/, "");
recursiveRename(parent.layers[i]);
}
}
Copy link to clipboard
Copied
This works perfectly!!! Thank you very much for solving the problem that has troubled me for a long time! You are really excellent and admirable, not only "Ai Command Palette" @jduncan 👍👍
Copy link to clipboard
Copied
Thank you @Silly-V for pointing me in the right direction!
I have just started to learn JavaScript, and I have been using VBA before (thanks to the advice and help of @Disposition_Dev and @CarlosCanto , let me enter the world of JS). This forum is a good place to start!
I want to ask you a question about the following method of declaring variables:
var objectsToMove = [
doc.layers.getByName("To move aligned objects").layers[0].pathItems[0],
doc.layers.getByName("To move aligned objects").layers[1].pathItems[0],
doc.layers.getByName("To move aligned objects").layers[2].pathItems[0]
];
I'm curious about this declaration method. It seems that this variable is defined with a constant value pathitems [0] ? When it is objectsToMove[i], what value is the objectsToMove ? Is it below?
doc.layers.getByName("To move aligned objects").layers[0].pathItems[i],
doc.layers.getByName("To move aligned objects").layers[1].pathItems[i],
doc.layers.getByName("To move aligned objects").layers[2].pathItems[i]
I really don't understand why it can be like this?
And what value is the objectsToMove.length ?Is it layers [0]. pathitems length? or layers[1].pathItems. length? or layers[2].pathItems. length? Or the sum of them? If the number of pathitems in each layer is different, can it be executed correctly?
Many thanks in advance for your time and advice!
Copy link to clipboard
Copied
Hey, @Silly-V
Can you help me answer this question? Many thanks in advance for your time and advice!
Thank you @Silly-V for pointing me in the right direction!
I have just started to learn JavaScript, and I have been using VBA before (thanks to the advice and help of @Disposition_Dev and @CarlosCanto , let me enter the world of JS). This forum is a good place to start!
I want to ask you a question about the following method of declaring variables:
var objectsToMove = [
doc.layers.getByName("To move aligned objects").layers[0].pathItems[0],
doc.layers.getByName("To move aligned objects").layers[1].pathItems[0],
doc.layers.getByName("To move aligned objects").layers[2].pathItems[0]
];
I'm curious about this declaration method. It seems that this variable is defined with a constant value pathitems [0] ? When it is objectsToMove[i], what value is the objectsToMove ? Is it below?
doc.layers.getByName("To move aligned objects").layers[0].pathItems[i],
doc.layers.getByName("To move aligned objects").layers[1].pathItems[i],
doc.layers.getByName("To move aligned objects").layers[2].pathItems[i]
I really don't understand why it can be like this?
And what value is the objectsToMove.length ?Is it layers [0]. pathitems length? or layers[1].pathItems. length? or layers[2].pathItems. length? Or the sum of them? If the number of pathitems in each layer is different, can it be executed correctly?
Many thanks in advance for your time and advice!
By @Raymond ZJH
Copy link to clipboard
Copied
I actually created some alignment utilities for public use a while back. Given a "key object" and an array of objects you want to align, it handles all the positioning quirks (including the visible bounds thing that @jduncan mentioned).
The initial implementation was pretty clunky and awfully repetitive. So I just took some time and simpilified it. It used to be discreet functions for each different alignment option... silly. So i condensed it all down to one function called align() which takes 3 required arguments: align(key:any pageItem or artboard, otherObjects: array of pageItems you want to align, alignType: string representing the alignment option(s).
Key objects can be an artboard, pageItem, pathItem, groupItem, compoundPathItem, placedItem, linkedItem, etc. any item that falls under the umbrella of Document.pageItems.
The array of otherObjects can contain one or more pageItems. (no support for artboards yet.. i don't know if it's necessary?).
The alignType string can be one of the following: "center", "vcenter", "vtop", "vbottom", "hcenter", "hleft", "hright", "botleft", "botright", "topleft", "topright", "leftcenter", "rightcenter", "topcenter", "botcenter"
source code located here:
https://github.com/wdjsdev/public_illustrator_scripts/blob/master/alignment_functions.js
and the dependency code here:
https://github.com/wdjsdev/public_illustrator_scripts/blob/master/object_bounds_data.js
This is the code that handles the visible bounds quirks that vasily and josh mentioned.
Copy link to clipboard
Copied
Thank you @Disposition_Dev very much for your explanation! You are my idol! 😊
Copy link to clipboard
Copied
I don't know anything about Java and scripting. Does this work on below sample?
Your help would be greratly appreciated.
Copy link to clipboard
Copied
Can we introduce more than one key object with this code? something like below example :