Skip to main content
Known Participant
March 13, 2023
Question

Photoshop relative asset alignment.

  • March 13, 2023
  • 2 replies
  • 884 views

Hi All,

 

I am wondering if there is a way to auto align assets in photoshop like you might do with the stack feature in Adobe XD? Either in the interface or with scripting?

 

So that if a text box increases its contents it pushes a text box below down or to the right?

 

Many thanks,

 

Nick

This topic has been closed for replies.

2 replies

c.pfaffenbichler
Community Expert
Community Expert
March 14, 2023

// 2023, use it at your own risk;
#target photoshop
if (app.documents.length > 0) {
    var theLayers = collectSelectedLayersBounds ();
    if (theLayers.length == 2) {
// set to pixels;
        var originalRulerUnits = app.preferences.rulerUnits;
        app.preferences.rulerUnits = Units.POINTS;
        moveLayer (theLayers[1][1], 0, theLayers[0][2][3] - theLayers[1][2][1]);
// reset;
        app.preferences.rulerUnits = originalRulerUnits;
    };
};
////// collect bounds of selected layers //////
function collectSelectedLayersBounds () {
// set to pixels;
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.POINTS;
// get selected layers;
    var selectedLayers = new Array;
    var ref = new ActionReference();
    ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var desc = executeActionGet(ref);
    if (desc.getBoolean(stringIDToTypeID("hasBackgroundLayer")) == true) {var theAdd =0}
    else {var theAdd = 1};
    if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){
    desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
    var c = desc.count;
    var selectedLayers = new Array();
    // run through selected layers;
    for(var i=0;i<c;i++){
    var theIndex = desc.getReference( i ).getIndex()+theAdd;
    // get id for solid color layers;
    try {
    var ref = new ActionReference();
    ref.putIndex( charIDToTypeID("Lyr "), theIndex ); 
    var layerDesc = executeActionGet(ref);
    var theName = layerDesc.getString(stringIDToTypeID('name'));
    var theIdentifier = layerDesc.getInteger(stringIDToTypeID ("layerID"));
    var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
    var theseBounds = [theBounds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
    selectedLayers.push([theName, theIdentifier, theseBounds]);
    } catch (e) {};
    };
    // if only one:
    }else{
    var ref = new ActionReference();
    ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var layerDesc = executeActionGet(ref);
    try {
    var theName = layerDesc.getString(stringIDToTypeID('name'));
    var theIdentifier = layerDesc.getInteger(stringIDToTypeID ("layerID"));
    var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
    var theseBounds = [theBounds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
    selectedLayers = [[theName, theIdentifier, theseBounds]]
    } catch (e) {};
    };
// reset;
    app.preferences.rulerUnits = originalRulerUnits;
    return selectedLayers;
};
////// based on code by mike hale and paul riggott //////
function selectLayerByID(index,add){ 
    add = undefined ? add = false:add 
    var ref = new ActionReference();
        ref.putIdentifier(charIDToTypeID("Lyr "), index);
        var desc = new ActionDescriptor();
        desc.putReference(charIDToTypeID("null"), ref );
            if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) ); 
            desc.putBoolean( charIDToTypeID( "MkVs" ), false ); 
        try{
        executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
    }catch(e){
    alert(e.message); 
    }
};
////// move layer //////
function moveLayer (theID, hor, ver) {
	selectLayerByID(theID, false);
		var desc77 = new ActionDescriptor();
		var ref38 = new ActionReference();
		var idlayer = stringIDToTypeID( "layer" );
		ref38.putEnumerated( idlayer, stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ));
	desc77.putReference( stringIDToTypeID( "null" ), ref38 );
	var idto = stringIDToTypeID( "to" );
		var desc78 = new ActionDescriptor();
		var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
		desc78.putUnitDouble( stringIDToTypeID( "horizontal" ), idpixelsUnit, hor );
		desc78.putUnitDouble( stringIDToTypeID( "vertical" ), idpixelsUnit, ver );
	desc77.putObject( idto, stringIDToTypeID( "offset" ), desc78 );
	executeAction( stringIDToTypeID( "move" ), desc77, DialogModes.NO );
	};
c.pfaffenbichler
Community Expert
Community Expert
March 14, 2023

A Script could evaluate the position and bounds of the existing Layers but how would you define the relationships that determine which Layers should not overlap (and therefore be moved)? 

 

Why do you want to recreate functionality in Photoshop that apparently already exists in another application? 

Nick5FF2Author
Known Participant
March 14, 2023

Hi,

 

Thanks for a reply.

 

I was hoping that I could write a script to take the width or height of a layer (image or text box) and offeset the position of another layer in relation to it. So if the text box is 300px or 200px a layer beneath it willl move acording to the height. like text box height = 300px. layer 2 Y position += text box height.

 

Is that sort of thing possible in Photoshop scripting? Getting element heights. setting element positions.

 

Thanks,

 

Nick

c.pfaffenbichler
Community Expert
Community Expert
March 14, 2023

Yes. 

 

If the two Layers are the selected ones that almost clears up the identification. 

Do you want to move the top Layer or bottom Layer? Or is only one of the two Layers a Type Layer anyway? 

Do you want to move the »other« Layer by the Type Layer’s height anyway or only if they overlap? 

 

Could you post screenshots (including the Layers Panel) to illustrate the start- and end-situation?