Highlighted

Scripting the "zoom to layers bounds" feature...

Participant ,
Jul 11, 2020

Copy link to clipboard

Copied

It's not a well-known feature, but alt-clicking on a layer in the layers panel will actually zoom the document to the bounds of this particular layer.

 

I am now trying to implement something similar...  ScriptListenner isn't returning anything, so I'm kinda lost...

 

I'm guessing I'd have to get the actual layers bounds...but where do I go from there ?

 

Any thoughts ?  thanks.

Most Valuable Participant
Correct answer by JJMack | Most Valuable Participant

I can not type so 

 

app.runMenuItem(stringIDToTypeID("fitLayersOnScreen"));

 

 

is less work for me.

 

I wrote this to also toggle the  document layers view. Had the scriptlistener and Cleans SL type most of the code.

 

 

FitLayerOnScreen(); // PS 2020
function FitLayerOnScreen() { // documents active Layer toggle all other visible Layers off and on 
	var descriptor = new ActionDescriptor();
	var list = new ActionList();
	var reference = new ActionReference();
	reference.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ));
	list.putReference( reference );
	descriptor.putList( charIDToTypeID( "null" ), list );
	descriptor.putBoolean( charIDToTypeID( "TglO" ), true );
	executeAction( stringIDToTypeID( "show" ), descriptor, DialogModes.NO );
    app.runMenuItem(stringIDToTypeID("fitLayersOnScreen"));
}

 

 

Topics

Actions and scripting, SDK

Views

144

Likes

Translate

Translate

Report

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

Scripting the "zoom to layers bounds" feature...

Participant ,
Jul 11, 2020

Copy link to clipboard

Copied

It's not a well-known feature, but alt-clicking on a layer in the layers panel will actually zoom the document to the bounds of this particular layer.

 

I am now trying to implement something similar...  ScriptListenner isn't returning anything, so I'm kinda lost...

 

I'm guessing I'd have to get the actual layers bounds...but where do I go from there ?

 

Any thoughts ?  thanks.

Most Valuable Participant
Correct answer by JJMack | Most Valuable Participant

I can not type so 

 

app.runMenuItem(stringIDToTypeID("fitLayersOnScreen"));

 

 

is less work for me.

 

I wrote this to also toggle the  document layers view. Had the scriptlistener and Cleans SL type most of the code.

 

 

FitLayerOnScreen(); // PS 2020
function FitLayerOnScreen() { // documents active Layer toggle all other visible Layers off and on 
	var descriptor = new ActionDescriptor();
	var list = new ActionList();
	var reference = new ActionReference();
	reference.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ));
	list.putReference( reference );
	descriptor.putList( charIDToTypeID( "null" ), list );
	descriptor.putBoolean( charIDToTypeID( "TglO" ), true );
	executeAction( stringIDToTypeID( "show" ), descriptor, DialogModes.NO );
    app.runMenuItem(stringIDToTypeID("fitLayersOnScreen"));
}

 

 

Topics

Actions and scripting, SDK

Views

145

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Most Valuable Participant ,
Jul 11, 2020

Copy link to clipboard

Copied

There are many things in Photoshop that do not record and Alt+Click+cursor Position.  Is most likely one of there.  When I tried all that was recorder  was the select layer part.  Script have limited options when it come to Photoshop UI.  You have no access to cursor position that photoshop see and you can not move it.  You can use menu item some may have shortcut like Zoom Ctrt++ and Ctrl+- other view options Zoom Layer Alt+Click can not be a menu item or have a shortcut other then one associated with the cursor position for the cursor position is need to identify the layer.   If a script could position the cursor how would the script know if the layers pallet is open on any display..     If the Scriptlistener had recorded additional Zoom information   it more then likely need to record the Layer ID  not the layer name many layer can t have the same  name Such is life.   What you want to do may be possible. It not possible using Photoshop DOM code and I would thingk if it were possible with Action Manager code the scriptlistener would have recorded it.

JJMack

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Participant ,
Jul 11, 2020

Copy link to clipboard

Copied

Hey there, thanks for taking the time, but this isn't what I meant.

 

I'm not trying to "emulate" an alt-click with code... I want to build a function that does the same thing than what the alt-click does, which is : Zoom precisely on the current layer, so it fits in the screen.  Try alt-clicking on a layer (one that doesn't cover the whole image) to see what it does.

 

I am pretty confident I could get the desired zoom level by looking at the layer's bounds values...  Comparing those to the actual document size, I'd get the zoom ratio I need... That's should be fairly easy.

 

I've also found this function to zoom at the desired zoom level.  It does feel strange since it uses the "resizeImage" method (but without resampling).  I tried it real fast and it seems to work...

 

Now... what feels like the tricky part is how do I center the viewport to the center of the layer.  Again, finding the layer's center shouldn't be a problem, since we have access to the layer's bounds, but I just don't see how I can "move" the viewport around and have it sits where I need to.

 

Again, many thanks to anyone giving it a try 🙂

 

J

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Most Valuable Participant ,
Jul 11, 2020

Copy link to clipboard

Copied

You wrote "It's not a well-known feature, but alt-clicking on a layer in the layers panel will actually zoom the document to the bounds of this particular layer."

 

You are right it not well known for that only seems to be available in Photoshop 2020. It also does not do what you wrote if that is what is advertised. If it did the image window would  have the aspect ratio of the layers and the layer would be in it.  Its more  a Fit Layer to display or Photoshop image area.  And there is a menu item more or less for that function in PS 2020. However, you have to target the layer first. 

 

So you can script that in Photoshop 2020. The script will not work in other versions.  I also found out I could get the script listener to record the Show Layer Toggle. So in a script you can make the layer the active layer use the Show layer toggle to toggle all other visible layer off and use the fit layers on screen menu item. So it would be very easy the script in PS 2020. And may be better than the Alt+Click layer for that does not toggle the other layer off.

 

 

So here  is the script code for the new 2020 feature Fit Layers(s) to Screen.  In Photoshop 2020 you cans assign a Shortcut to the menu View menu item "Fit Layer(s) to Screen"  You do not  need to script that.  If you want to use it in a script to  Zoom to Document Layer you would need to Make the layer you want to Zoom to the Active Layer.  You may want to toggle other visible layers off so only that layer will be visible not covered by upper layers. But the would also turn off any upper adjustment layers that adjust  the  Zoom to layer which you may want  to be visible.  You need to decide how to want to handle the other layers in the documents. The case sensitive JavaScript code is: app.runMenuItem(stringIDToTypeID("fitLayersOnScreen"));

 

Remember PS 2020 or newer is required.

JJMack

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Most Valuable Participant ,
Jul 14, 2020

Copy link to clipboard

Copied

If  you create a script to zoom to the Active layer content fitted on screen and also through in the Alt+Click on the Active Layer visibility eyeball.  The script would be like  an Alt+Click on the Layer content thumbnail and an Alt+Click on the layers visibility eyeball.  Combine two Shortcut in a single script with a shortcut. Repeated use of this will just toggle between the two views the Active Layer view and the view with all the layers you had visible, toggled back on.  Again the PS 2020 abs above is required.

JJMack

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Enthusiast ,
Jul 14, 2020

Copy link to clipboard

Copied

zoom to active layer:

#target photoshop;

var s2t = stringIDToTypeID;
(r = new ActionReference()).putEnumerated(s2t('menuItemClass'), s2t('menuItemType'), s2t("fitLayersOnScreen"));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Most Valuable Participant ,
Jul 14, 2020

Copy link to clipboard

Copied

I can not type so 

 

app.runMenuItem(stringIDToTypeID("fitLayersOnScreen"));

 

 

is less work for me.

 

I wrote this to also toggle the  document layers view. Had the scriptlistener and Cleans SL type most of the code.

 

 

FitLayerOnScreen(); // PS 2020
function FitLayerOnScreen() { // documents active Layer toggle all other visible Layers off and on 
	var descriptor = new ActionDescriptor();
	var list = new ActionList();
	var reference = new ActionReference();
	reference.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ));
	list.putReference( reference );
	descriptor.putList( charIDToTypeID( "null" ), list );
	descriptor.putBoolean( charIDToTypeID( "TglO" ), true );
	executeAction( stringIDToTypeID( "show" ), descriptor, DialogModes.NO );
    app.runMenuItem(stringIDToTypeID("fitLayersOnScreen"));
}

 

 

JJMack

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Enthusiast ,
Jul 14, 2020

Copy link to clipboard

Copied

I apologize. I was so interested in whether it is possible to manually control the zoom and position of the center of the document that I did not read what was written above 🙂 

I managed to repeat the fitLayersOnScreen algorithm with the ability to manually set parameters (the center of the desired layer, the degree of zoom). I will try to solve a couple of problems and publish the code. Maybe someone will come in handy.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Participant ,
Jul 14, 2020

Copy link to clipboard

Copied

app.runMenuItem(stringIDToTypeID("fitLayersOnScreen")); works just fine.

 

Many thanks !

 

J.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Adobe Community Professional ,
Jul 14, 2020

Copy link to clipboard

Copied

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Enthusiast ,
Jul 15, 2020

Copy link to clipboard

Copied

r-bin, thanks for viewInfo!

 

function zoomToLayer (layerID, zoom) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID,
        lrBounds = getProperty('layer', 'bounds', layerID),
        x = lrBounds.getUnitDoubleValue(s2t('left')) + lrBounds.getUnitDoubleValue(s2t('width')) / 2,
        y = lrBounds.getUnitDoubleValue(s2t('top')) + lrBounds.getUnitDoubleValue(s2t('height')) / 2,
        w = lrBounds.getUnitDoubleValue(s2t('width')),
        h = lrBounds.getUnitDoubleValue(s2t('height'));

    var activeView = getProperty('document', 'viewInfo').getObjectValue(s2t('activeView')).getObjectValue(s2t('globalBounds')),
        docW = activeView.getDouble(s2t('right')) - activeView.getDouble(s2t('left')),
        docH = activeView.getDouble(s2t('bottom')) - activeView.getDouble(s2t('top')),
        k = Math.min(docW / w, docH / h) * (zoom ? zoom : 1);

    (d = new ActionDescriptor()).putUnitDouble(s2t('zoom'), s2t('percentUnit'), k);
    setProperty('document', 'zoom', d);

    (d = new ActionDescriptor()).putUnitDouble(s2t('horizontal'), s2t('distanceUnit'), x * k);
    d.putUnitDouble(s2t('vertical'), s2t('distanceUnit'), y * k);
    setProperty('document', 'center', d);

    function getProperty(object, property, id) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t(property));
        id ? r.putIdentifier(s2t(object), id) : r.putEnumerated(s2t(object), s2t('ordinal'), s2t('targetEnum'));
        return getValue(executeActionGet(r), p)

        function getValue(d, id) {
            switch (d.getType(id)) {
                case DescValueType.OBJECTTYPE: return d.getObjectValue(id);
                case DescValueType.LISTTYPE: return d.getList(id);
                case DescValueType.REFERENCETYPE: return d.getReference(id);
                case DescValueType.BOOLEANTYPE: return d.getBoolean(id);
                case DescValueType.STRINGTYPE: return d.getString(id);
                case DescValueType.INTEGERTYPE: return d.getInteger(id);
                case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(id);
                case DescValueType.DOUBLETYPE: return d.getDouble(id);
                case DescValueType.ALIASTYPE: return d.getPath(id);
                case DescValueType.CLASSTYPE: return d.getClass(id);
                case DescValueType.UNITDOUBLE: return { value: d.getUnitDoubleValue(id), type: t2s(d.getUnitDoubleType(id)) };
                case DescValueType.ENUMERATEDTYPE: return { value: t2s(d.getEnumerationValue(id)), type: t2s(d.getEnumerationType(id)) };
            }
        }
    }

    function setProperty(target, property, desc) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t(property));
        r.putEnumerated(s2t(target), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor).putReference(s2t('null'), r);
        d.putObject(s2t('to'), p, desc);
        executeAction(s2t('set'), d, DialogModes.NO);
    }
}

 

 

This function allows not only to increase the selected layer, but also to set the scaling factor:

zoomToLayer() 

2020-07-15_12-23-52.png

zoomToLayer (app.activeDocument.activeLayer.id0.5)

2020-07-15_12-26-46.png

 

zoomToLayer (undefined0.9) in window mode

2020-07-15_12-28-46.png

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
JJMack LATEST
Most Valuable Participant ,
Jul 15, 2020

Copy link to clipboard

Copied

Thank you I edit in floating windows the function works well in CC 2018 and 2019 for the active layer.  The other proior versions of Photoshop I have installed don't seem seem the have  all the support your  getProperty function requires.  Before using your  zoomToLayer function  I used fitOnScreen to fit the image window to the display it on and also toggled the other visible layers.

 

app.runMenuItem(stringIDToTypeID("fitOnScreen"));

// Toggle layers
var descriptor = new ActionDescriptor();
var list = new ActionList();
var reference = new ActionReference();
reference.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ));
list.putReference( reference );
descriptor.putList( charIDToTypeID( "null" ), list );
descriptor.putBoolean( charIDToTypeID( "TglO" ), true );
executeAction( stringIDToTypeID( "show" ), descriptor, DialogModes.NO );
zoomToLayer (activeDocument.activeLayer.id,10);

zoomToLayer (undefined, 0.95);  //  zoom layer in Image window
JJMack

Likes

Translate

Translate

Report

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