Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

- Home
- Illustrator
- Discussions
- Creating a rectangle around multiple objects with ...

- Creating a rectangle around multiple objects with ...

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/td-p/13300468
Oct 27, 2022
Oct 27, 2022

Copy link to clipboard

Copied

Hi folks,

I'm struggling a bit with a script. Here in the forum I saw a script which creates a rectangle around a single object with a certain offset and so on. This script doesn't work unfortunately, once you select multiple objects and want to create a rectangle along those.

My workflow by hand currently looks like this. I'm having those objects on the artboard, then I'm creating a rectangle exacly along the borders of all objects (basically recreating the bounding-box with an actual rectangle if you'd like to say so) and then I'm giving the newly created rectangle a black contour with 0.25pts and finally I'm ofsetting the path by 1mm and delete the inner rectangle.

So basically starting point on the left, and the end result to the right when I'm doing it by hand.

Pretty time consuming and tedious to do, especially because I find it really hard to place the initial rectangle on the first try, without the need to gently fondle it into the right place afterwards.

So heres the script I find which would possibly do the work for me, if it was for only one object:

```
function makeRect() {
if (selection.length == 0) {
alert("No object …");
return;
}else{
if (selection.length > 1) {
alert("Too many objects …");
return;
}else{
var myDoc = app.activeDocument;
var Sel = myDoc.selection
var SelVB = Sel[0].visibleBounds;
var dMarg = 28.3464567;
var Links = SelVB[0];
var Oben = SelVB[1];
var SelBreite = (SelVB[2] - SelVB[0]);
var SelHoehe = (SelVB[1] - SelVB[3]);
var newCMYK = new CMYKColor();
newCMYK.cyan = 100;
newCMYK.magenta = 0;
newCMYK.yellow = 0;
newCMYK.black = 0;
var myGroup =myDoc.groupItems.add();
Sel[0].move(myGroup, ElementPlacement.PLACEATBEGINNING);
var MargBox = myDoc.pathItems.rectangle(Oben+dMarg, Links-dMarg, SelBreite+2*dMarg, SelHoehe+2*dMarg);
MargBox.stroked = true;
MargBox.strokeWidth = 10;
//MargBox.filled = false;
MargBox.fillColor = newCMYK;
MargBox.move(myGroup, ElementPlacement.PLACEATEND);
}
}
}
makeRect();
```

The script makes a rectangle, with stroke of 10, cyan fill and an offset of... 28,something - whatever that exactly means - is it px?

However, this doesn't work when it comes down to multiple objects that need to be rectangle-outlined. I mean there's obviously right at the beginning an alert if you select more than one object.

So, could someone help me out on this one? You'd really make my day.

Best regards,

Thomas

TOPICS

Scripting

Community guidelines

Be kind and respectful, give credit to the original source of content, and search for duplicates before posting.
Learn more

Community Expert
,
Oct 27, 2022
Oct 27, 2022

Hi @TW-22341, I spent a lot of time some while ago trying to work out a good way to get an item's bounds, even if it was clipped or whatever, and I made a function that has a good try at doing so, although it won't be perfect in strange case, eg. where effects like drop shadows are added.

I've thrown together a quick script that uses those functions I already wrote and I think it should do what you ask for. Let me know how it goes for you. You can adjust the "settings" object.

- Mark

Edit 1: i

...
13
Replies
13

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13300523#M340980
Oct 27, 2022
Oct 27, 2022

Copy link to clipboard

Copied

Not a script solution, but you can achieve what you've been doing by hand by grouping the objects, adding a stroke to the group and using Effect > Convert to Shape > Rectangle on the stroke:

You could save that as a graphic style.

Community guidelines

Be kind and respectful, give credit to the original source of content, and search for duplicates before posting.
Learn more

TW-22341
AUTHOR

Community Beginner
,

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13300829#M340997
Oct 27, 2022
Oct 27, 2022

Copy link to clipboard

Copied

Community guidelines

Be kind and respectful, give credit to the original source of content, and search for duplicates before posting.
Learn more

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13300840#M340998
Oct 27, 2022
Oct 27, 2022

Copy link to clipboard

Copied

Object > Expand Appearance

Community guidelines

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13305879#M341359
Oct 28, 2022
Oct 28, 2022

Copy link to clipboard

Copied

Perfectly match to my requirement, Thanks lot :), you make my day

Community guidelines

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13300574#M340981
Oct 27, 2022
Oct 27, 2022

Copy link to clipboard

Copied

Hi @TW-22341, I spent a lot of time some while ago trying to work out a good way to get an item's bounds, even if it was clipped or whatever, and I made a function that has a good try at doing so, although it won't be perfect in strange case, eg. where effects like drop shadows are added.

I've thrown together a quick script that uses those functions I already wrote and I think it should do what you ask for. Let me know how it goes for you. You can adjust the "settings" object.

- Mark

Edit 1: improved handling of text.

Edit 2: simplified code, changed getItemBounds to handle multiple items as parameter, moved rect behind objects as per OP's code.

```
(function () {
var mm = 2.834645;
// the colors of the rectangle
var black = new GrayColor(),
cyan = new CMYKColor();
black.gray = 100
cyan.cyan = 100;
cyan.magenta = 0;
cyan.yellow = 0;
cyan.black = 0;;
// user settings:
var settings = {
margin: 1 * mm,
strokeColor: black,
strokeWidth: 1
};
var doc = app.activeDocument,
items = doc.selection;
if (items.length == 0) {
alert('Please make a selection and try again.');
return;
}
var lastItem = items[items.length - 1],
bounds = getItemBounds(items);
if (bounds == undefined)
return;
// add margin
bounds[0] -= settings.margin;
bounds[1] += settings.margin;
bounds[2] += settings.margin;
bounds[3] -= settings.margin;
// draw the rectangle
var rect = doc.pathItems.rectangle(bounds[1], bounds[0], bounds[2] - bounds[0], bounds[1] - bounds[3]);
rect.filled = true;
rect.fillColor = cyan;
rect.stroked = true;
rect.strokeWidth = settings.strokeWidth;
rect.strokeColor = settings.strokeColor;
// put the rectangle behind all the items
rect.move(lastItem, ElementPlacement.PLACEAFTER);
// leave just the rectangle selected
app.selection = null;
rect.selected = true;
// finished
/**
* Returns bounds of item.
* @author m1b
* @version 2022-10-28
* Attempts to get correct bounds
* of clipped groups.
* @param {PageItem|Array<PageItem>} item - an Illustrator PageItem or array of PageItems.
* @param {Boolean} [geometric] - if false, returns visible bounds.
* @param {Array} [bounds] - @private parameter, used when recursing.
* @returns {Array} - the calculated bounds.
*/
function getItemBounds(item, geometric, bounds) {
var newBounds = [];
if (
item.typename == 'GroupItem'
|| item.constructor.name == 'Array'
) {
var children = item.typename == 'GroupItem' ? item.pageItems : item,
contentBounds = [];
if (
item.hasOwnProperty('clipped')
&& item.clipped == true
) {
// item is clipping group
var clipBounds;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (
child.hasOwnProperty('clipping')
&& child.clipping == true
)
// the clipping item
clipBounds = child.geometricBounds;
else
// a clipped content item
var b = expandBounds(getItemBounds(child, geometric, bounds), contentBounds);
}
newBounds = intersectionOfBounds([clipBounds, contentBounds]);
}
else {
// item is a normal group
for (var i = 0; i < children.length; i++) {
var child = children[i];
var b = expandBounds(getItemBounds(child, geometric, bounds), contentBounds);
}
newBounds = contentBounds;
}
}
else if (item.typename == 'TextFrame') {
// item is a text frame
var dup = item.duplicate().createOutline();
newBounds = geometric ? dup.geometricBounds : dup.visibleBounds;
dup.remove();
}
else {
// item is not clipping group
newBounds = geometric ? item.geometricBounds : item.visibleBounds;
}
bounds = (bounds == undefined)
? bounds = newBounds
: bounds = expandBounds(newBounds, bounds);
return bounds;
};
/**
* Returns bounds that encompass both bounds.
* @author m1b
* @version 2022-07-24
**
* @param {Array} b1 - bounds array [l, t, r, b].
* @param {Array} b2 - bounds array [l, t, r, b].
* @returns {Array} - the encompassing bounds.
*/
function expandBounds(b1, b2) {
var expanded = b2;
for (var i = 0; i < 4; i++) {
if (b1[i] != undefined && b2[i] == undefined) expanded[i] = b1[i];
if (b1[i] == undefined && b2[i] != undefined) expanded[i] = b2[i];
if (b1[i] == undefined && b2[i] == undefined) return;
}
if (b1[0] < b2[0]) expanded[0] = b1[0];
if (b1[1] > b2[1]) expanded[1] = b1[1];
if (b1[2] > b2[2]) expanded[2] = b1[2];
if (b1[3] < b2[3]) expanded[3] = b1[3];
return expanded;
};
/**
* Returns the overlapping rectangle
* of two or more rectangles.
* @author m1b
* @version 2022-07-24
* NOTE: Returns undefined if ANY
* rectangles do not intersect.
* @param {Array} arrayOfBounds - an array of bounds arrays [l, t, r, b].
* @returns {Array} - bounds array [l, t, r, b] of overlap.
*/
function intersectionOfBounds(arrayOfBounds) {
// sort a copy of array
var bounds = arrayOfBounds
.slice(0)
.sort(function (a, b) { return b[0] - a[0] || a[1] - b[1] });
// start with first bounds
var intersection = bounds.shift(),
b;
// compare each bounds, getting smaller
while (b = bounds.shift()) {
// if doesn't intersect, bail out
if (!boundsDoIntersect(intersection, b))
return;
var l = Math.max(intersection[0], b[0]),
t = Math.min(intersection[1], b[1]),
r = Math.min(intersection[2], b[2]),
b = Math.max(intersection[3], b[3]);
intersection = [l, t, r, b];
}
return intersection;
};
/**
* Returns true if the two bounds intersect.
* @author m1b
* @version 2022-10-04
* @param {Array} bounds1 - bounds array [l, t, r, b].
* @param {Array} bounds2 - bounds array [l, t, r, b].
* @param {Boolean} TLBR - whether bounds arrays are interpreted as [t, l, b, r].
* @returns {Boolean}
*/
function boundsDoIntersect(bounds1, bounds2, TLBR) {
if (TLBR === true)
// TLBR
return !(
bounds2[0] > bounds1[2]
|| bounds2[1] > bounds1[3]
|| bounds2[2] < bounds1[0]
|| bounds2[3] < bounds1[1]
);
else
// LTRB
return !(
bounds2[0] > bounds1[2]
|| bounds2[1] < bounds1[3]
|| bounds2[2] < bounds1[0]
|| bounds2[3] > bounds1[1]
);
};
})();
```

Community guidelines

TW-22341
AUTHOR

Community Beginner
,

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13300787#M340991
Oct 27, 2022
Oct 27, 2022

Copy link to clipboard

Copied

Community guidelines

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13300890#M341007
Oct 27, 2022
Oct 27, 2022

Copy link to clipboard

Copied

Community guidelines

TW-22341
AUTHOR

Community Beginner
,

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13303303#M341191
Oct 28, 2022
Oct 28, 2022

Copy link to clipboard

Copied

This version seems to work flawlessly - very impressive. Ghank you for your help. I just adjusted the settings a bit, since I need a white stroke with 0.25 and no fill. Heres my result:

```
(function () {
var mm = 2.834645;
// the colors of the rectangle
var black = new GrayColor(),
cyan = new CMYKColor();
white = new CMYKColor();
black.gray = 100
white.cyan = 0;
white.magenta = 0;
white.yellow = 0;
white.black = 0;
cyan.cyan = 100;
cyan.magenta = 0;
cyan.yellow = 0;
cyan.black = 0;;
// user settings:
var settings = {
margin: 1 * mm,
strokeColor: white,
strokeWidth: 0.25
};
var doc = app.activeDocument,
items = doc.selection;
if (items.length == 0) {
alert('Please make a selection and try again.');
return;
}
var lastItem = items[items.length - 1],
bounds = getItemBounds(items);
if (bounds == undefined)
return;
// add margin
bounds[0] -= settings.margin;
bounds[1] += settings.margin;
bounds[2] += settings.margin;
bounds[3] -= settings.margin;
// draw the rectangle
var rect = doc.pathItems.rectangle(bounds[1], bounds[0], bounds[2] - bounds[0], bounds[1] - bounds[3]);
rect.filled = false;
//rect.fillColor = cyan;
rect.stroked = true;
rect.strokeWidth = settings.strokeWidth;
rect.strokeColor = settings.strokeColor;
// put the rectangle behind all the items
rect.move(lastItem, ElementPlacement.PLACEAFTER);
// leave just the rectangle selected
app.selection = null;
rect.selected = true;
// finished
/**
* Returns bounds of item.
* @author m1b
* @version 2022-10-28
* Attempts to get correct bounds
* of clipped groups.
* @Param {PageItem|Array<PageItem>} item - an Illustrator PageItem or array of PageItems.
* @Param {Boolean} [geometric] - if false, returns visible bounds.
* @Param {Array} [bounds] - @private parameter, used when recursing.
* @Returns {Array} - the calculated bounds.
*/
function getItemBounds(item, geometric, bounds) {
var newBounds = [];
if (
item.typename == 'GroupItem'
|| item.constructor.name == 'Array'
) {
var children = item.typename == 'GroupItem' ? item.pageItems : item,
contentBounds = [];
if (
item.hasOwnProperty('clipped')
&& item.clipped == true
) {
// item is clipping group
var clipBounds;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (
child.hasOwnProperty('clipping')
&& child.clipping == true
)
// the clipping item
clipBounds = child.geometricBounds;
else
// a clipped content item
var b = expandBounds(getItemBounds(child, geometric, bounds), contentBounds);
}
newBounds = intersectionOfBounds([clipBounds, contentBounds]);
}
else {
// item is a normal group
for (var i = 0; i < children.length; i++) {
var child = children[i];
var b = expandBounds(getItemBounds(child, geometric, bounds), contentBounds);
}
newBounds = contentBounds;
}
}
else if (item.typename == 'TextFrame') {
// item is a text frame
var dup = item.duplicate().createOutline();
newBounds = geometric ? dup.geometricBounds : dup.visibleBounds;
dup.remove();
}
else {
// item is not clipping group
newBounds = geometric ? item.geometricBounds : item.visibleBounds;
}
bounds = (bounds == undefined)
? bounds = newBounds
: bounds = expandBounds(newBounds, bounds);
return bounds;
};
/**
* Returns bounds that encompass both bounds.
* @author m1b
* @version 2022-07-24
**
* @Param {Array} b1 - bounds array [l, t, r, b].
* @Param {Array} b2 - bounds array [l, t, r, b].
* @Returns {Array} - the encompassing bounds.
*/
function expandBounds(b1, b2) {
var expanded = b2;
for (var i = 0; i < 4; i++) {
if (b1[i] != undefined && b2[i] == undefined) expanded[i] = b1[i];
if (b1[i] == undefined && b2[i] != undefined) expanded[i] = b2[i];
if (b1[i] == undefined && b2[i] == undefined) return;
}
if (b1[0] < b2[0]) expanded[0] = b1[0];
if (b1[1] > b2[1]) expanded[1] = b1[1];
if (b1[2] > b2[2]) expanded[2] = b1[2];
if (b1[3] < b2[3]) expanded[3] = b1[3];
return expanded;
};
/**
* Returns the overlapping rectangle
* of two or more rectangles.
* @author m1b
* @version 2022-07-24
* NOTE: Returns undefined if ANY
* rectangles do not intersect.
* @Param {Array} arrayOfBounds - an array of bounds arrays [l, t, r, b].
* @Returns {Array} - bounds array [l, t, r, b] of overlap.
*/
function intersectionOfBounds(arrayOfBounds) {
// sort a copy of array
var bounds = arrayOfBounds
.slice(0)
.sort(function (a, b) { return b[0] - a[0] || a[1] - b[1] });
// start with first bounds
var intersection = bounds.shift(),
b;
// compare each bounds, getting smaller
while (b = bounds.shift()) {
// if doesn't intersect, bail out
if (!boundsDoIntersect(intersection, b))
return;
var l = Math.max(intersection[0], b[0]),
t = Math.min(intersection[1], b[1]),
r = Math.min(intersection[2], b[2]),
b = Math.max(intersection[3], b[3]);
intersection = [l, t, r, b];
}
return intersection;
};
/**
* Returns true if the two bounds intersect.
* @author m1b
* @version 2022-10-04
* @Param {Array} bounds1 - bounds array [l, t, r, b].
* @Param {Array} bounds2 - bounds array [l, t, r, b].
* @Param {Boolean} TLBR - whether bounds arrays are interpreted as [t, l, b, r].
* @Returns {Boolean}
*/
function boundsDoIntersect(bounds1, bounds2, TLBR) {
if (TLBR === true)
// TLBR
return !(
bounds2[0] > bounds1[2]
|| bounds2[1] > bounds1[3]
|| bounds2[2] < bounds1[0]
|| bounds2[3] < bounds1[1]
);
else
// LTRB
return !(
bounds2[0] > bounds1[2]
|| bounds2[1] < bounds1[3]
|| bounds2[2] < bounds1[0]
|| bounds2[3] > bounds1[1]
);
};
})();
```

So I basically added white as CMYK color, couldn't find an easier way, but thats ok I guess, set the stroke Color to the newly defined white, changed rect.filled to false and out-commented the rect.fillColor. The result is now just as I wanted it. If you got any further improvements or if I did something wrong with my changes, feel free to correct me. Unfortunately I'm only able to read and understand code, but writing it myself is a thing I haven't managed to truly learn for years... But right now I'm pretty happy that you helped me out on this one, so I don't have to do this dull task over and over again by hand 🙂 You really saved my day, thank you very, very much!

Community guidelines

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13304125#M341237
Oct 28, 2022
Oct 28, 2022

Copy link to clipboard

Copied

You're welcome! The changes you made look good to me.

Community guidelines

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13305861#M341357
Oct 28, 2022
Oct 28, 2022

Copy link to clipboard

Copied

Community guidelines

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13305875#M341358
Oct 28, 2022
Oct 28, 2022

Copy link to clipboard

Copied

Thank you Doug A Roberts

I got what I was looking

Community guidelines

/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13305896#M341360
Oct 28, 2022
Oct 28, 2022

Copy link to clipboard

Copied

Here's a modified version that asks for margin value and puts rectangle behind each item. - Mark

```
/**
* Draws bounding rectangle behind each item.
* @discussion https://community.adobe.com/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13300468
*/
(function () {
// the colors of the rectangle
var black = new GrayColor(),
cyan = new CMYKColor();
black.gray = 100
cyan.cyan = 100;
cyan.magenta = 0;
cyan.yellow = 0;
cyan.black = 0;
var defaultMargin = '1 mm',
margin = prompt('Draw Rectangles Around Items\nEnter Margin:', defaultMargin);
if (margin == undefined)
return;
// user settings:
var settings = {
margin: stringToPoints(margin) || stringToPoints(defaultMargin),
strokeColor: black,
strokeWidth: 1
};
var doc = app.activeDocument,
items = doc.selection;
if (items.length == 0) {
alert('Please make a selection and try again.');
return;
}
for (var i = 0; i < items.length; i++) {
var bounds = getItemBounds(items[i]);
if (bounds == undefined)
return;
// add margin
bounds[0] -= settings.margin;
bounds[1] += settings.margin;
bounds[2] += settings.margin;
bounds[3] -= settings.margin;
// draw the rectangle
var rect = doc.pathItems.rectangle(bounds[1], bounds[0], bounds[2] - bounds[0], bounds[1] - bounds[3]);
rect.filled = true;
rect.fillColor = cyan;
rect.stroked = true;
rect.strokeWidth = settings.strokeWidth;
rect.strokeColor = settings.strokeColor;
// put the rectangle behind all the items
rect.move(items[i], ElementPlacement.PLACEAFTER);
}
// leave just the rectangle selected
app.selection = null;
rect.selected = true;
// finished
/**
* Converts a string measurement value,
* to a value in points, for example:
* '1.5 mm' --> 4.2519675.
* @author m1b
* @version 2022-10-29
* @Param {String} str - the string to convert, eg. '1mm'.
* @Returns {Number} - the value in points.
*/
function stringToPoints(str) {
var n;
if (/\s*[\d\.]+\s*(mm|millimeters)/.test(str))
n = parseFloat(str) * 2.834645;
else if (/\s*[\d\.]+\s*(cm|centimeters)/.test(str))
n = parseFloat(str) * mm * 28.34645;
else if (/\s*[\d\.]+\s*("|in)/.test(str))
n = parseFloat(str) * 72;
else
n = parseFloat(str);
if (n === n)
return n;
};
/**
* Returns bounds of item(s).
* @author m1b
* @version 2022-10-28
* Attempts to get correct bounds
* of clipped groups.
* @Param {PageItem|Array<PageItem>} item - an Illustrator PageItem or array of PageItems.
* @Param {Boolean} [geometric] - if false, returns visible bounds.
* @Param {Array} [bounds] - @private parameter, used when recursing.
* @Returns {Array} - the calculated bounds.
*/
function getItemBounds(item, geometric, bounds) {
var newBounds = [];
if (
item.typename == 'GroupItem'
|| item.constructor.name == 'Array'
) {
var children = item.typename == 'GroupItem' ? item.pageItems : item,
contentBounds = [];
if (
item.hasOwnProperty('clipped')
&& item.clipped == true
) {
// item is clipping group
var clipBounds;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (
child.hasOwnProperty('clipping')
&& child.clipping == true
)
// the clipping item
clipBounds = child.geometricBounds;
else
// a clipped content item
var b = expandBounds(getItemBounds(child, geometric, bounds), contentBounds);
}
newBounds = intersectionOfBounds([clipBounds, contentBounds]);
}
else {
// item is a normal group
for (var i = 0; i < children.length; i++) {
var child = children[i];
var b = expandBounds(getItemBounds(child, geometric, bounds), contentBounds);
}
newBounds = contentBounds;
}
}
else if (item.typename == 'TextFrame') {
// item is a text frame
var dup = item.duplicate().createOutline();
newBounds = geometric ? dup.geometricBounds : dup.visibleBounds;
dup.remove();
}
else {
// item is not clipping group
newBounds = geometric ? item.geometricBounds : item.visibleBounds;
}
bounds = (bounds == undefined)
? bounds = newBounds
: bounds = expandBounds(newBounds, bounds);
return bounds;
};
/**
* Returns bounds that encompass both bounds.
* @author m1b
* @version 2022-07-24
**
* @Param {Array} b1 - bounds array [l, t, r, b].
* @Param {Array} b2 - bounds array [l, t, r, b].
* @Returns {Array} - the encompassing bounds.
*/
function expandBounds(b1, b2) {
var expanded = b2;
for (var i = 0; i < 4; i++) {
if (b1[i] != undefined && b2[i] == undefined) expanded[i] = b1[i];
if (b1[i] == undefined && b2[i] != undefined) expanded[i] = b2[i];
if (b1[i] == undefined && b2[i] == undefined) return;
}
if (b1[0] < b2[0]) expanded[0] = b1[0];
if (b1[1] > b2[1]) expanded[1] = b1[1];
if (b1[2] > b2[2]) expanded[2] = b1[2];
if (b1[3] < b2[3]) expanded[3] = b1[3];
return expanded;
};
/**
* Returns the overlapping rectangle
* of two or more rectangles.
* @author m1b
* @version 2022-07-24
* NOTE: Returns undefined if ANY
* rectangles do not intersect.
* @Param {Array} arrayOfBounds - an array of bounds arrays [l, t, r, b].
* @Returns {Array} - bounds array [l, t, r, b] of overlap.
*/
function intersectionOfBounds(arrayOfBounds) {
// sort a copy of array
var bounds = arrayOfBounds
.slice(0)
.sort(function (a, b) { return b[0] - a[0] || a[1] - b[1] });
// start with first bounds
var intersection = bounds.shift(),
b;
// compare each bounds, getting smaller
while (b = bounds.shift()) {
// if doesn't intersect, bail out
if (!boundsDoIntersect(intersection, b))
return;
var l = Math.max(intersection[0], b[0]),
t = Math.min(intersection[1], b[1]),
r = Math.min(intersection[2], b[2]),
b = Math.max(intersection[3], b[3]);
intersection = [l, t, r, b];
}
return intersection;
};
/**
* Returns true if the two bounds intersect.
* @author m1b
* @version 2022-10-04
* @Param {Array} bounds1 - bounds array [l, t, r, b].
* @Param {Array} bounds2 - bounds array [l, t, r, b].
* @Param {Boolean} TLBR - whether bounds arrays are interpreted as [t, l, b, r].
* @Returns {Boolean}
*/
function boundsDoIntersect(bounds1, bounds2, TLBR) {
if (TLBR === true)
// TLBR
return !(
bounds2[0] > bounds1[2]
|| bounds2[1] > bounds1[3]
|| bounds2[2] < bounds1[0]
|| bounds2[3] < bounds1[1]
);
else
// LTRB
return !(
bounds2[0] > bounds1[2]
|| bounds2[1] < bounds1[3]
|| bounds2[2] < bounds1[0]
|| bounds2[3] > bounds1[1]
);
};
})();
```

Community guidelines

Community Expert
,

LATEST
/t5/illustrator-discussions/creating-a-rectangle-around-multiple-objects-with-a-script/m-p/13306235#M341374
Oct 29, 2022
Oct 29, 2022

Copy link to clipboard

Copied

Community guidelines

Resources

Learning Resources for Illustrator

Crash on launch and known issues

Fonts and Typography in Illustrator

Copyright © 2022 Adobe. All rights reserved.