Skip to main content
rg0401
Participant
August 24, 2022
Answered

How do I scale multiple layers while keeping them anchored in place

  • August 24, 2022
  • 6 replies
  • 4934 views

I'm trying to scale down 32 layers (Smart Objects) down without them all collapsing in on the artboard. I want them to stay where they are in the columns and rows they are in. I know a decade ago, we had the Transform Each tool? Is that gone now?

Correct answer Stephen Marsh

@rg0401 – Select the layers and run this script, first changing the W and H scale value and anchor point as indicated in the script comments:

 

function resizeLayer() {
    /*
    AnchorPosition.BOTTOMCENTER
    AnchorPosition.BOTTOMLEFT
    AnchorPosition.BOTTOMRIGHT
    AnchorPosition.MIDDLECENTER
    AnchorPosition.MIDDLELEFT
    AnchorPosition.MIDDLERIGHT
    AnchorPosition.TOPCENTER
    AnchorPosition.TOPLEFT
    AnchorPosition.TOPRIGHT
    */
    
    // W%, H%, Anchor/Reference point location
    // Change as required:
    activeDocument.activeLayer.resize(50, 50, AnchorPosition.BOTTOMLEFT);
}

var s2t = stringIDToTypeID;
(r = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var lrs = executeActionGet(r).getList(p),
    sel = new ActionReference();

for (var i = 0; i < lrs.count; i++) {
    sel.putIdentifier(s2t('layer'), p = lrs.getReference(i).getIdentifier(s2t('layerID')));
    (r = new ActionReference).putIdentifier(s2t('layer'), p);
    (d = new ActionDescriptor()).putReference(s2t("target"), r);
    executeAction(s2t('select'), d, DialogModes.NO);

    resizeLayer();

}

 

  1. Copy the code text to the clipboard
  2. Open a new blank file in a plain-text editor (not in a word processor)
  3. Paste the code in
  4. Save the text file as .txt
  5. Rename the file extension from .txt to .jsx
  6. Install or browse to the .jsx file to run:

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html#Photoshop

 

6 replies

Stephen Marsh
Community Expert
Community Expert
September 22, 2022

The following script goes one step further, it also scales styles as well!

 

https://www.mightyplugins.cc/magic-scripts#bgLayers_comp-klpkbgoa1

 

Stephen Marsh
Community Expert
Community Expert
August 26, 2022

@rg0401 – Here is a version with a GUI:

/*
Scale Selected Layers Independently v1-2.jsx
26th August 2022, Stephen Marsh
14th April 2024, v1.1 - Code added to correctly handle the GUI cancel button, thanks to Patrick Hennessey
15th April 2024, v1.2 - Added tool tips to the radio button abbreviations
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-do-i-scale-multiple-layers-while-keeping-them-anchored-in-place/td-p/13157052
*/

#target photoshop

////////// SCRIPT UI START //////////

/*
With thanks - https://scriptui.joonas.me
*/

// DIALOG
var theGUI = new Window("dialog");
    theGUI.text = "Scale Selected Layers Independently - v1.2";
    theGUI.orientation = "row";
    theGUI.alignChildren = ["center","top"];
    theGUI.spacing = 10;
    theGUI.margins = 20;

var scaleLabel = theGUI.add("statictext", undefined, undefined, {name: "scaleLabel"});
    scaleLabel.text = "Scale %";

// SCALE GROUP
var scaleGroup = theGUI.add("group", undefined, {name: "scaleGroup"});
    scaleGroup.orientation = "row";
    scaleGroup.alignChildren = ["left","center"];
    scaleGroup.spacing = 10;
    scaleGroup.margins = 0;

// SCALE WIDTH GROUP
var scaleWidthGroup = scaleGroup.add("group", undefined, {name: "scaleWidthGroup"});
    scaleWidthGroup.orientation = "column";
    scaleWidthGroup.alignChildren = ["left","center"];
    scaleWidthGroup.spacing = 10;
    scaleWidthGroup.margins = 0;

    var widthLabel = scaleWidthGroup.add("statictext", undefined, undefined, {name: "widthLabel"});
    widthLabel.text = "Width:";

    ////////// Use editnumber instead of edittext for numerical fields! //////////
    var widthField = scaleWidthGroup.add('editnumber {properties: {name: "widthField"}}');
        widthField.text = "100";
    widthField.preferredSize.width = 50;
   
    ////////// Preset the width field as active - Peter Kahrel, scriptUI for dummies //////////
    widthField.active = true;
    ////////// Initially use the width value for the height value //////////
    ////////// Callback: onChange - Peter Kahrel, scriptUI for dummies //////////
    widthField.onChange = function () {heightField.text = widthField.text}
    //////////

// SCALE HEIGHT GROUP
var scaleHeightGroup = scaleGroup.add("group", undefined, {name: "scaleHeightGroup"});
    scaleHeightGroup.orientation = "column";
    scaleHeightGroup.alignChildren = ["left","center"];
    scaleHeightGroup.spacing = 10;
    scaleHeightGroup.margins = 0;

var heightLabel = scaleHeightGroup.add("statictext", undefined, undefined, {name: "heightLabel"});
    heightLabel.text = "Height:";

////////// Use editnumber instead of edittext for numerical fields! //////////
var heightField = scaleHeightGroup.add('editnumber {properties: {name: "heightField"}}');
    heightField.text = "100";
    heightField.preferredSize.width = 50;

// DIVIDER 1
//var divOne = scaleGroup.add("panel", undefined, undefined, {name: "divOne"});
    //divOne.alignment = "fill";

// RADIO PARENT GROUP
var radioGroup = theGUI.add("group", undefined, {name: "radioGroup"});
    radioGroup.orientation = "row";
    radioGroup.alignChildren = ["left","center"];
    radioGroup.spacing = 10;
    radioGroup.margins = 0;

// RADIO GROUP LEFT
var radioGroupLeft = radioGroup.add("group", undefined, {name: "radioGroupLeft"});
    radioGroupLeft.orientation = "column";
    radioGroupLeft.alignChildren = ["left","center"];
    radioGroupLeft.spacing = 10;
    radioGroupLeft.margins = 0;

var topLeft = radioGroupLeft.add("radiobutton", undefined, undefined, {name: "topLeft"});
    topLeft.text = "TL";
    topLeft.helpTip = "Top Left";

var middleLeft = radioGroupLeft.add("radiobutton", undefined, undefined, {name: "middleLeft"});
    middleLeft.text = "ML";
    middleLeft.helpTip = "Middle Left";

var bottomLeft = radioGroupLeft.add("radiobutton", undefined, undefined, {name: "bottomLeft"});
    bottomLeft.text = "BL";
    bottomLeft.helpTip = "Bottom Left";

// RADIO GROUP CENTER
var radioGroupCenter = radioGroup.add("group", undefined, {name: "radioGroupCenter"});
    radioGroupCenter.orientation = "column";
    radioGroupCenter.alignChildren = ["left","center"];
    radioGroupCenter.spacing = 10;
    radioGroupCenter.margins = 0;

var topCenter = radioGroupCenter.add("radiobutton", undefined, undefined, {name: "topCenter"});
    topCenter.text = "TC";
    topCenter.helpTip = "Top Center";

var middleCenter = radioGroupCenter.add("radiobutton", undefined, undefined, {name: "middleCenter"});
    middleCenter.text = "MC";
    middleCenter.helpTip = "Middle Center";
    ////////// Preset the radio button as active - Peter Kahrel, scriptUI for dummies //////////
    middleCenter.value = true;
    //////////

var bottomCenter = radioGroupCenter.add("radiobutton", undefined, undefined, {name: "bottomCenter"});
    bottomCenter.text = "BC";
    bottomCenter.helpTip = "Bottom Center";

// RADIO GROUP RIGHT
var radioGroupRight = radioGroup.add("group", undefined, {name: "radioGroupRight"});
    radioGroupRight.orientation = "column";
    radioGroupRight.alignChildren = ["left","center"];
    radioGroupRight.spacing = 10;
    radioGroupRight.margins = 0;

    var topRight = radioGroupRight.add("radiobutton", undefined, undefined, {name: "topRight"});
    topRight.text = "TR";
    topRight.helpTip = "Top Right";

    var middleRight = radioGroupRight.add("radiobutton", undefined, undefined, {name: "middleRight"});
    middleRight.text = "MR";
    middleRight.helpTip = "Middle Right";

    var bottomRight = radioGroupRight.add("radiobutton", undefined, undefined, {name: "bottomRight"});
    bottomRight.text = "BR";
    bottomRight.helpTip = "Bottom Right";
   
    ////////// Make multiple groups act as one group - Peter Kahrel, scriptUI for dummies //////////
    radioGroupLeft.addEventListener("click", function () {
        for (var i = 0; i < radioGroupCenter.children.length; i++)
            radioGroupCenter.children[i].value = false;
    });
    radioGroupLeft.addEventListener("click", function () {
        for (var i = 0; i < radioGroupRight.children.length; i++)
            radioGroupRight.children[i].value = false;
    });
    radioGroupCenter.addEventListener("click", function () {
        for (var i = 0; i < radioGroupLeft.children.length; i++)
            radioGroupLeft.children[i].value = false;
    });
    radioGroupCenter.addEventListener("click", function () {
        for (var i = 0; i < radioGroupRight.children.length; i++)
            radioGroupRight.children[i].value = false;
    });
    radioGroupRight.addEventListener("click", function () {
        for (var i = 0; i < radioGroupCenter.children.length; i++)
            radioGroupCenter.children[i].value = false;
    });
    radioGroupRight.addEventListener("click", function () {
        for (var i = 0; i < radioGroupLeft.children.length; i++)
            radioGroupLeft.children[i].value = false;
    });
    //////////

// DIVIDER 2
//var divTwo = theGUI.add("panel", undefined, undefined, {name: "divTwo"});
    //divTwo.alignment = "fill";

// BUTTON GROUP
var buttonGroup = theGUI.add("group", undefined, {name: "buttonGroup"});
    buttonGroup.orientation = "column";
    buttonGroup.alignChildren = ["left","center"];
    buttonGroup.spacing = 10;
    buttonGroup.margins = 0;

var okButton = buttonGroup.add("button", undefined, undefined, {name: "okButton"});
    okButton.text = "OK";
    okButton.alignment = ["fill","center"];

var cancelButton = buttonGroup.add("button", undefined, undefined, {name: "cancelButton"});
    cancelButton.text = "Cancel";
    cancelButton.alignment = ["fill", "center"];

// RENDER THE DIALOG
// OK pressed
if (theGUI.show() === 1) {
    activeDocument.suspendHistory("Scale Selected Layers", "main()");
} else {
    // Cancel pressed
}

////////// SCRIPT UI END //////////


function main() {

            var s2t = stringIDToTypeID;
            (r = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
            r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
            var lrs = executeActionGet(r).getList(p),
                sel = new ActionReference();

            for (var i = 0; i < lrs.count; i++) {
                sel.putIdentifier(s2t('layer'), p = lrs.getReference(i).getIdentifier(s2t('layerID')));
                (r = new ActionReference).putIdentifier(s2t('layer'), p);
                (d = new ActionDescriptor()).putReference(s2t("target"), r);
                executeAction(s2t('select'), d, DialogModes.NO);
               
                ////////// Link the radio buttons to the resize  //////////
                if (topLeft.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.TOPLEFT);
                }
                if (topCenter.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.TOPCENTER);
                }
                if (topRight.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.TOPRIGHT);
                }
                if (middleLeft.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.MIDDLELEFT);
                }
                if (middleCenter.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.MIDDLECENTER);
                }
                if (middleRight.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.MIDDLERIGHT);
                }
                if (bottomLeft.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.BOTTOMLEFT);
                }
                if (bottomCenter.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.BOTTOMCENTER);
                }
                if (bottomRight.value === true) {
                    activeDocument.activeLayer.resize(widthField.text, heightField.text, AnchorPosition.BOTTOMRIGHT);
                }
            }
}

 

 

Stephen Marsh
Community Expert
Community Expert
August 29, 2022

@rg0401 - Feedback on the GUI script would be appreciated when you have time.

Known Participant
April 14, 2024

The cancel button does not do anything. The script still runs whether cancel was pressed or not.

Jumpenjax
Community Expert
Community Expert
August 25, 2022

Select all layers, then Go to transform/ scale. All layer should reduce the same.

Lee- Graphic Designer, Print Specialist, Photographer
rg0401
rg0401Author
Participant
August 25, 2022

Yea I know that haha. That's pretty elementary. I mean for them to scale down with the center point of each layer anchored to its exact point on the artboard. But it doesn't look like that's a feature on PS only AI unless you run a script. Thank you though!

jane-e
Community Expert
Community Expert
August 25, 2022

@rg0401 wrote:

... it doesn't look like that's a feature on PS only AI unless you run a script.


 

It would be a great feature request for Photoshop, though, if it can be done similar to the way it works in Illustrator. To make a feature request, start a new post in this forum and tag it as "Ideas" instead of "Discussions".

 

Jane

 

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
August 24, 2022

@rg0401 – Select the layers and run this script, first changing the W and H scale value and anchor point as indicated in the script comments:

 

function resizeLayer() {
    /*
    AnchorPosition.BOTTOMCENTER
    AnchorPosition.BOTTOMLEFT
    AnchorPosition.BOTTOMRIGHT
    AnchorPosition.MIDDLECENTER
    AnchorPosition.MIDDLELEFT
    AnchorPosition.MIDDLERIGHT
    AnchorPosition.TOPCENTER
    AnchorPosition.TOPLEFT
    AnchorPosition.TOPRIGHT
    */
    
    // W%, H%, Anchor/Reference point location
    // Change as required:
    activeDocument.activeLayer.resize(50, 50, AnchorPosition.BOTTOMLEFT);
}

var s2t = stringIDToTypeID;
(r = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var lrs = executeActionGet(r).getList(p),
    sel = new ActionReference();

for (var i = 0; i < lrs.count; i++) {
    sel.putIdentifier(s2t('layer'), p = lrs.getReference(i).getIdentifier(s2t('layerID')));
    (r = new ActionReference).putIdentifier(s2t('layer'), p);
    (d = new ActionDescriptor()).putReference(s2t("target"), r);
    executeAction(s2t('select'), d, DialogModes.NO);

    resizeLayer();

}

 

  1. Copy the code text to the clipboard
  2. Open a new blank file in a plain-text editor (not in a word processor)
  3. Paste the code in
  4. Save the text file as .txt
  5. Rename the file extension from .txt to .jsx
  6. Install or browse to the .jsx file to run:

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html#Photoshop

 

rg0401
rg0401Author
Participant
August 25, 2022

Thank you! I'll give this a try!

Stephen Marsh
Community Expert
Community Expert
August 25, 2022

I'll add a GUI when I have time if this is something that you find useful and would frequently use (the GUI takes a lot more work than the base script).

jane-e
Community Expert
Community Expert
August 24, 2022

@rg0401 wrote:

I know a decade ago, we had the Transform Each tool? Is that gone now?


 

Object menu > Transform > Transform Each is in Illustrator — I don't remember it ever being in Photoshop.

 

Jane

 

Stephen Marsh
Community Expert
Community Expert
August 24, 2022

For 32 layers, my first thought is a script, as a keyboard shortcut on an Action would semi-automate the transform and selection of the next layer, but would require 32 manual repetitions (or duping the steps to create 32 reps).

 

What is the scale % and anchor point?

rg0401
rg0401Author
Participant
August 25, 2022

Seems like the script is the only way to do it after digging deeper and seeing more resoponses on here. Thanks for your help!