ExtendScript to center selected objects to their parent artboards.
Hi all,
Looking for a script again. I have a script from Pixeden that centers everything in every artboard. Unfortunately it's hardcoded to work only with everything and not selected art. I just want a script that will center the selection (or just a single object if there is only one thing selected) to its parent artboard.
Here's the Pixeden script:
#target Illustrator
// script.name = center-in-artboard.js;
// script.description = Loop into each Artboard and center its content;
// script.requirement = one document with at least one artboard;
// script.parent = pixeden;
// script.elegant = false;
if (app.documents.length > 0) {
var doc = app.activeDocument
app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM
centerInArtboard()
} else {
alert ("There is no open document.")
}
function centerInArtboard () {
// Loop into each Artboard
for (var i = 0; i < doc.artboards.length; i++) {
selectArtboardByIndex(i)
// Group content to center as is
var newGroupItem = doc.groupItems.add()
for (var s = 0; s < doc.selection.length; s++) {
doc.selection[s].move(newGroupItem, ElementPlacement.PLACEATEND)
}
centerSelected(newGroupItem, doc.artboards[i].artboardRect)
}
}
function centerSelected (obj, artboardBound) {
obj.position = new Array(
(artboardBound[2] - artboardBound[0]) / 2 - obj.width / 2,
(artboardBound[3] - artboardBound[1]) / 2 + obj.height /2
)
}
function selectArtboardByIndex (index) {
doc.selection = null
doc.artboards.setActiveArtboardIndex(index)
doc.selectObjectsOnActiveArtboard()
}
Anyone have a script or a way to modify this to work only with what's selected?
To clarify:
1. If a selected object has a parent artboard, center it.
2. If a selected object has no parent artboard, do nothing.
3. If only one object is selected, center it.
I'm in the process of trying to hack and slash my way to a script but I don't really have a good grasp on what I'm doing. It's also heavily derivative of Sergey Osokin's work, I basically just copy-pasted some of his functions:
//@target illustrator
function main() {
var CFG = {
units: getUnits(), // Active document units
};
if (!documents.length) {
alert('Error\nOpen a document and try again');
return;
}
if (!selection.length || selection.typename == 'TextRange') {
alert('Error\nPlease select atleast one object');
return;
}
var isRulerTopLeft = preferences.getBooleanPreference('isRulerOriginTopLeft');
var isRulerInFourthQuad = preferences.getBooleanPreference('isRulerIn4thQuad');
CFG.isFlipY = (isRulerTopLeft && isRulerInFourthQuad) ? true : false;
var doc = app.activeDocument,
docAbs = doc.artboards,
abIdx = docAbs.getActiveArtboardIndex(),
abBnds = docAbs[abIdx].artboardRect,
docSel = selection,
item = docSel[0],
coord = app.coordinateSystem;
for (var i = 0, len = selection.length; i < len; i++) {
var item = selection[i];
// I have no idea how to get the artboard bounds
// of the selected item to pass to centerToArtboard
//centerToArtboard(item,abBnds,true);
}
}
// Place the item in the center of the artboard
function centerToArtboard(item, abBnds, isFlipY) {
var bnds = item.geometricBounds,
itemSize = {
left: bnds[0],
top: bnds[1],
inLeft: bnds[0],
inTop: bnds[1],
inRight: bnds[2],
inBottom: bnds[3],
h: 0,
w: 0
};
if (isType(item, 'group') && item.clipped) {
var mask = getMaskPath(item);
bnds = mask.geometricBounds,
itemSize.inLeft = bnds[0];
itemSize.inTop = bnds[1];
itemSize.inRight = bnds[2];
itemSize.inBottom = bnds[3];
}
abWidth = Math.abs(abBnds[2] - abBnds[0]);
abHeight = Math.abs(abBnds[1] - abBnds[3]);
itemSize.h = Math.abs(itemSize.inTop - itemSize.inBottom);
itemSize.w = Math.abs(itemSize.inRight - itemSize.inLeft);
var left = itemSize.left - itemSize.inLeft,
top = itemSize.top - itemSize.inTop,
centerX = left + (abWidth - itemSize.w) / 2,
centerY = top + (itemSize.h + (isFlipY ? -1 : 1) * abHeight) / 2;
item.position = [centerX, centerY];
}
// Get active document ruler units
function getUnits() {
if (!documents.length) return '';
var key = activeDocument.rulerUnits.toString().replace('RulerUnits.', '');
switch (key) {
case 'Pixels':
return 'px';
case 'Points':
return 'pt';
case 'Picas':
return 'pc';
case 'Inches':
return 'in';
case 'Millimeters':
return 'mm';
case 'Centimeters':
return 'cm';
// Added in CC 2023 v27.1.1
case 'Meters':
return 'm';
case 'Feet':
return 'ft';
case 'FeetInches':
return 'ft';
case 'Yards':
return 'yd';
// Parse new units in CC 2020-2023 if a document is saved
case 'Unknown':
var xmp = activeDocument.XMPString;
if (/stDim:unit/i.test(xmp)) {
var units = /<stDim:unit>(.*?)<\/stDim:unit>/g.exec(xmp)[1];
if (units == 'Meters') return 'm';
if (units == 'Feet') return 'ft';
if (units == 'FeetInches') return 'ft';
if (units == 'Yards') return 'yd';
return 'px';
}
break;
default:
return 'px';
}
}
// Check if item is in the active artboard area
function isContains(item, tag) {
var isContains = false;
addTag(item, tag);
selection = null;
redraw();
activeDocument.selectObjectsOnActiveArtboard();
for (var i = 0, len = selection.length; i < len; i++) {
var item = selection[i];
if (isTagExists(item, tag)) {
isContains = true;
break;
}
}
removeTag(item, tag);
return isContains;
}
// Get the clipping mask
function getMaskPath(group) {
for (var i = 0, len = group.pageItems.length; i < len; i++) {
var currItem = group.pageItems[i];
if (isClippingPath(currItem)) {
return currItem;
}
}
}
// Check the clipping mask
function isClippingPath(item) {
var clipText = (isType(item, 'text') &&
item.textRange.characterAttributes.fillColor == '[NoColor]' &&
item.textRange.characterAttributes.strokeColor == '[NoColor]');
return (isType(item, 'compound') && item.pathItems[0].clipping) ||
item.clipping || clipText;
}
// Check the item typename by short name
function isType(item, type) {
var regexp = new RegExp(type, 'i');
return regexp.test(item.typename);
}
try {
main();
} catch (e) {}
Basically, I don't know how to retrieve the artboard bounds for each individual selected object. I was thinking:
1. Store all selected items into an array ("selectedItems").
2. Deselect everything.
3. Loop through the "selectedItems" array. (for loop)
4. Select each item one by one and pass it to the centerToArtboard function
But the centerToArtboard function requires you to pass it the item and the artboard bounds. I know that I can do this:
docAbs = doc.artboards,
abIdx = docAbs.getActiveArtboardIndex(),
abBnds = docAbs[abIdx].artboardRect,
But I'm confused with "docAbs[abIdx].artboardRect" and how it relates to the document "selection" collection. Does this function return the artboard dimensions of the current selection?
How do I get the artboard bounds for the currently selected pageitem?
Sorry for post length.
Any help really appreciated.
