• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
1

A script for measuring the distance between two elements?

Community Beginner ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

Anyone can help me with the script for measuring the distance between two elements (layers) in Photoshop.

I know that there are smart guides . I need this funcionality as a script to apply correct margins/paddings in CSS

Layers should be selected by shift. It's works very similar in Adobe Dreamweaver Extract and Assets Extract.

2017-12-23_174748.jpg

TOPICS
Actions and scripting

Views

4.6K

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
community guidelines

correct answers 1 Correct answer

People's Champ , Jan 15, 2018 Jan 15, 2018

OK.

The following script gives you this result. But it seems to me this is complete nonsense. ))

// version no CS6 or no effects

var old_units = app.preferences.rulerUnits;   

app.preferences.rulerUnits = Units.PIXELS;   

 

try { app.activeDocument.suspendHistory("Get Text Bounds", "var bounds = get_selected_layers_bounds()") } catch(e) { alert(e); } 

 

try { executeAction( charIDToTypeID( "undo" ), undefined, DialogModes.NO ); } catch(e) { alert(e); } 

 

app.preferences.rulerUnits = old_units;   

...

Votes

Translate

Translate
Adobe
Community Expert ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

I'm not sure if it's accurate with text, but you can use bounds to find the location of various layers, then do some math using the bounds:

var doc = activeDocument;

var layerBounds doc.activeLayer.bounds

//layerBounds[0] = left edge

//layerBounds[1] = top edge

//layerBounds[2] = right edge

//layerBounds[3] = bottom edge

I've found that it's best to convert these results to a number using parseFloat(), as sometime if you do math without converting, you get odd results.

Votes

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
community guidelines
People's Champ ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

Also do not forget about the property boundsNoEffects )

Votes

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
community guidelines
Community Beginner ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

Chuck, can I get an array of active layers? Seems like if I select two layers with shift, Photoshop treats them as a single layer for defining bounds.

And... Where can I see all properties, subelements of doc, actieveLayer briefly - I'm newbie in PS scripting

Votes

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
community guidelines
Community Expert ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

A Photoshop document can have many element in different layer kinds and layers can be masked and effect added which effects layers visibility and effects can extend outside  the layer with the effects.  How would the script know which elements you are interested in measuring.

You show text layers. They can be mask and have effects all of the a layer's content may not be visible and effect can be rendered outside a layers bounds for the layer's composite view.

JJMack

Votes

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
community guidelines
Community Beginner ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

How would the script know which elements you are interested in measuring.
Layers should be selected by shift.

Votes

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
community guidelines
People's Champ ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

The active layer can be only one. If the layers are selected with Shift - this is called targetLayers. This is a list of indexes of the layer. Using it you can get any information about each of the selected layers. Just do not understand what and with what you are going to compare to determine the distance. What do you think is the distance between layers and which ones?

Votes

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
community guidelines
Community Beginner ,
Dec 24, 2017 Dec 24, 2017

Copy link to clipboard

Copied

Two layers should be selected with shift key.

The distance is the distance   - veritcal distance - between bottom border of top layer and top border of bottom layer.

30px on screenshot (from Adobe Assets Extract).... Could U provide script example with targetLayers?

2017-12-23_174748.jpg

Votes

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
community guidelines
People's Champ ,
Dec 25, 2017 Dec 25, 2017

Copy link to clipboard

Copied

OK. A simple example )

var old_units = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var bounds = get_selected_layers_bounds();

app.preferences.rulerUnits = old_units;

if (bounds)

    {

    if (bounds.length == 2)

        {

        if (bounds[0].bottom <= bounds[1].top)

            alert("verilal distance: " + (bounds[1].top - bounds[0].bottom))

        else if (bounds[1].bottom <= bounds[0].top)

            alert("verilal distance: " + (bounds[0].top - bounds[1].bottom))

        else

            alert("intersected layers")

        }

    else

        alert("More then 2 selected layers")

   

    }

else

    alert("There is no selected layers")

/////////////////////////////////////////////////////////////////////////////////////////////////

function get_selected_layers_bounds()

    {

    try {

        var ref = new ActionReference();

        ref.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID( "targetLayers" ) );

        ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

        var desc = executeActionGet(ref);

   

        if (!desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ) return null;

   

        var selectedLayers = new Array;

   

        var n = 0;

        try { activeDocument.backgroundLayer } catch (e) { n = 1; }

   

        desc = desc.getList( stringIDToTypeID( 'targetLayers' ));

   

        var len = desc.count;

   

        var selected_bounds = new Array();

   

        var d = new ActionDescriptor();

   

        for (var i = 0; i < len; i++)

            {

            try

                {

                d.clear();

   

                var r = new ActionReference();

                r.putIndex( charIDToTypeID( "Lyr " ), desc.getReference(i).getIndex() + n);

                d.putReference( charIDToTypeID( "null" ), r );

               

                var ret = executeAction( charIDToTypeID( "getd" ), d, DialogModes.NO );

   

                //var bounds = ret.getObjectValue(stringIDToTypeID("bounds"));  // use this in CS6 or when you want to take into account the effects

                var bounds = ret.getObjectValue(stringIDToTypeID("boundsNoEffects")); // in CS6 does not work

                var obj = { left: bounds.getUnitDoubleValue(stringIDToTypeID("left")),

                            top: bounds.getUnitDoubleValue(stringIDToTypeID("top")),

                            right: bounds.getUnitDoubleValue(stringIDToTypeID("right")),

                            bottom: bounds.getUnitDoubleValue(stringIDToTypeID("bottom"))};

   

                selected_bounds.push(obj);

                }

            catch (e)

                {

                alert(e);

   

                return null;

                }

            }

   

        return selected_bounds;

        }

    catch (e) { alert(e); return null; }

    }

Votes

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
community guidelines
Advocate ,
Dec 25, 2017 Dec 25, 2017

Copy link to clipboard

Copied

Didn't yeah.not want to measure from baseline of the top text-layer to the cap-line of the bottom-layer?

https://font.is/wallpaper/FontAnatomyWallpaper1920x1200.jpg

Votes

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
community guidelines
Community Beginner ,
Dec 25, 2017 Dec 25, 2017

Copy link to clipboard

Copied

If you use Point text plus without letters protruding down, for example "Foobar", then this will be the required distance. I think, it is not possible to calculate the distance from the baseline (of the bottom line of the top text), although ...

r-bin, Tom If it will be possible to calculate this way - it will be excellent!!!

Votes

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
community guidelines
People's Champ ,
Dec 25, 2017 Dec 25, 2017

Copy link to clipboard

Copied

If you want to measure the distance between the baselines of the text, then it's very simple. The position of the baseline is specified in Layer.textItem.position or, in our case, in textClickPoint. If this is what you need, then it's easy. The truth is still no time. I'll do it later.

P.S. Just specify, is this what you need?

Votes

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
community guidelines
Community Beginner ,
Dec 26, 2017 Dec 26, 2017

Copy link to clipboard

Copied

Temporarily replace all the symbols with the â–ˆ (SolidBlock symbol).

It was really cool idea! Full (solid) block covers 120% of font-size = PS leading auto or CSS line-height 120%. So the last thing.. really))... Should be applied updated and simplified formula

CSS = PS - (line-height_1 - 1.2 * font-size_1) / 2
        
- (line-height_2 - 1.2 * font-size_2) / 2

or in Photoshop Script syntax it should look something like this:

distance_in_css = distance - (Layer1.textItem.leading - 1.2 * Layer1.textItem.size) / 2
                           - (Layer2.textItem.leading - 1.2 * Layer2.textItem.size) / 2;

But I still do not understand how exactly this can be applied in the script. It's too hard for me

Votes

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
community guidelines
People's Champ ,
Dec 25, 2017 Dec 25, 2017

Copy link to clipboard

Copied

Here is the version with the text replaced with a symbol with the maximum height.

Check the distance that gives out the scrit with what you expect to get.

You can also get the position of the baseline, and for the paragraph text you can get the size of the bounding box.

But I do not know what to do with this, since I do not know what font parameters mean and I do not even understand CSS.

I have nothing more to offer you.(

var old_units = app.preferences.rulerUnits; 

app.preferences.rulerUnits = Units.PIXELS; 

try { app.activeDocument.suspendHistory("Get Text Bounds", "var bounds = get_selected_layers_bounds()") } catch(e) { alert(e); }

try { executeAction( charIDToTypeID( "undo" ), undefined, DialogModes.NO ); } catch(e) { alert(e); }

app.preferences.rulerUnits = old_units; 

 

if (bounds) 

    { 

    if (bounds.length == 2) 

        { 

        if (bounds[0].bottom <= bounds[1].top) 

            alert("Vertical distance: " + (bounds[1].top - bounds[0].bottom)) 

        else if (bounds[1].bottom <= bounds[0].top) 

            alert("Vertical distance: " + (bounds[0].top - bounds[1].bottom)) 

        else  

            alert("Intersecting layers") 

        } 

    else 

        alert("More then 2 selected layers")  

     

    } 

else  

    alert("There is no selected layers")  

 

///////////////////////////////////////////////////////////////////////////////////////////////// 

function get_selected_layers_bounds() 

    { 

    try { 

        var ref = new ActionReference(); 

 

        ref.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID( "targetLayers" ) ); 

        ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 

        var desc = executeActionGet(ref); 

     

        if (!desc.hasKey( stringIDToTypeID("targetLayers") ) ) return null; 

     

        var n = 0; 

        try { activeDocument.backgroundLayer } catch (e) { n = 1; } 

     

        desc = desc.getList( stringIDToTypeID("targetLayers")); 

     

        var len = desc.count; 

     

        var selected_bounds = new Array(); 

     

        for (var i = 0; i < len; i++) 

            { 

            try  

                { 

                var r = new ActionReference(); 

                r.putIndex( charIDToTypeID( "Lyr " ), desc.getReference(i).getIndex() + n); 

                var ret = executeActionGet(r); 

                if (ret.hasKey(stringIDToTypeID("textKey")))

                    {

                    var s = ret.getObjectValue(stringIDToTypeID("textKey")).getString(charIDToTypeID("Txt " ));

                    s = s.replace(/^./gm, String.fromCharCode(0x2588));

                    var d1 = new ActionDescriptor();

                    d1.putReference( charIDToTypeID( "null" ), r );

           

                    var d2 = new ActionDescriptor();

                    d2.putString( charIDToTypeID( "Txt " ), s);

                    d1.putObject( charIDToTypeID( "T   " ), charIDToTypeID( "TxLr" ), d2 );

                    executeAction( charIDToTypeID( "setd" ), d1, DialogModes.NO );

                    ret = executeActionGet(r); 

                    }

                   

                //var bounds = ret.getObjectValue(stringIDToTypeID("bounds"));  // use this in CS6 or when you want to take into account the effects 

                var bounds = ret.getObjectValue(stringIDToTypeID("boundsNoEffects")); // in CS6 does not work 

 

                var obj = { left  : bounds.getUnitDoubleValue(stringIDToTypeID("left")), 

                            top   : bounds.getUnitDoubleValue(stringIDToTypeID("top")), 

                            right : bounds.getUnitDoubleValue(stringIDToTypeID("right")), 

                            bottom: bounds.getUnitDoubleValue(stringIDToTypeID("bottom"))}; 

     

                selected_bounds.push(obj); 

                } 

            catch (e) 

                { 

                alert(e); 

     

                return null; 

                } 

            } 

     

        return selected_bounds; 

        } 

 

    catch (e) { alert(e); return null; } 

    } 

Votes

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
community guidelines
Community Beginner ,
Dec 26, 2017 Dec 26, 2017

Copy link to clipboard

Copied

You have done a great job! It seems this is what I need and I will only have to take into account the line-height. Not the height of the text, as you might think, but what is called "leading" in Photoshop.

I'll try your script and to update the code. Let me do something by myself!)) Given that I forgot the mouse, this may take some time))).

Thank you again and Happy New Year!

Votes

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
community guidelines
Community Beginner ,
Jan 04, 2018 Jan 04, 2018

Copy link to clipboard

Copied

r-bin​,

Hi, happy New Year!

Сan we finish the script? It remains to do a little bit.

Sorry if I'm distracting you from the holidays

Votes

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
community guidelines
People's Champ ,
Jan 05, 2018 Jan 05, 2018

Copy link to clipboard

Copied

It's not quite clear what's wrong with the script and what do not you get? Could you more precisely formulate the problem?

P.S. Happy New Year, too!

Votes

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
community guidelines
Community Beginner ,
Jan 08, 2018 Jan 08, 2018

Copy link to clipboard

Copied

Hi there! The script is good, but not complete .

In CSS, the height of a single-line text block is equal to the line-height (leading), for a multi-line block the height = line-height * n, where n - number of lines.

In Photoshop, the height of a single-line text layer (pointed text) is determined by the boundaries of the letters in the line. Leading affects only the distance between lines in a multi-line text layer, but not the height of a single-line layer. The height will be determined by the letter boundaries - the upper bound of the first line and the lower bound of the last line.

I noticed that the height of a single-line text layer using a solid block in Photoshop corresponds to a line height 120% (auto). And the script, if I understand correctly, calculates the distance between two such lines. But what happens if the line height, for example, is 200% or 100%?

I hope I explained it normally...

So we obtain the formula (where distance is distance calculated by script):

distance_in_css = distance - (line-height_1 - 1.2 * font-size_1) / 2
                          
- (line-height_2 - 1.2 * font-size_2) / 2

or in Photoshop Script syntax it should look something like this:

distance_in_css = distance - (Layer1.textItem.leading - 1.2 * Layer1.textItem.size) / 2
                           - (Layer2.textItem.leading - 1.2 * Layer2.textItem.size) / 2;

But I still do not understand how exactly this can be applied in the script. It's too hard for me

Votes

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
community guidelines
LEGEND ,
Jan 09, 2018 Jan 09, 2018

Copy link to clipboard

Copied

(Auto-)Leading is changable by script / user. There is no need to use 1.2 value as you can read current percent of autoleading by activeDocument.activeLayer.textItem.autoLeadingAmount / 100 on the condition auto leading was enabled by command activeDocument.activeLayer.textItem.useAutoLeading = true. That means you can change it to any other  available value, so to not doing complex calculation set it back to 100 by activeDocument.activeLayer.textItem.autoLeadingAmount = 100

Votes

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
community guidelines
Community Beginner ,
Jan 09, 2018 Jan 09, 2018

Copy link to clipboard

Copied

Ok, but leading still doesn't affect single-line text height - that is the problem.

Votes

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
community guidelines
LEGEND ,
Jan 10, 2018 Jan 10, 2018

Copy link to clipboard

Copied

In your image example what would be border of bottom layer if there was "y" letter in "Welcome" word like "Welcomey". Was that still actual bottom line (like it's now), or the line on the level of lowest "y" letter pixel?

If there was polish letter "Ó" (what is higher than any english letter in your second text layer) what should be top border of that layer, current one for regular letters or for the highest pixel in "Ó" letter?.

Or other example (Arial Regular, 12, leading 100%, 72 px/in resolution):

Welcome to...

(27 pixels)

ÓÓÓÓÓÓÓÓÓ

Welcome to...

(28 pixels)

jjjjjjjjjjjj

Welcome to...

(30 pixels)

AAAAAAAAA

Welcome to...

(32 pixels)

aaaaaaaaa

Would you like the distance between 'Welcome to' and another text layer was physical distance so like in example above, or 'text' distance where it measures height to letter top (of next layer) what gives always 30px (incl some pixels of empty space unfilled for certain letter, which are over that letter) ?

Votes

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
community guidelines
People's Champ ,
Jan 09, 2018 Jan 09, 2018

Copy link to clipboard

Copied

Honestly, I did not understand anything ). For me, the font parameters are similar to the Chinese grammar.

Could you draw two different text strings with a designation, roughly like in this figure, and indicate from which point and to what point do you want to measure the distance?

aaaa.png

Votes

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
community guidelines
Community Beginner ,
Jan 13, 2018 Jan 13, 2018

Copy link to clipboard

Copied

r-bin​, sorry for the delay - I was sick.

I still need a vertical distance between the two text layers, but given the line-height (leading). The script calculates the distance correctly for text with a line height of 120% (auto) - the â–ˆ (SolidBlock symbol) takes exactly this height. If it is less than or greater than 120% - in CSS the height will change, therefore the distance needs to be changed. Look at the screenshot, how it works in the browser (css) at different line-heights:

2018-01-13_183406.png

Votes

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
community guidelines
People's Champ ,
Jan 14, 2018 Jan 14, 2018

Copy link to clipboard

Copied

I do not know how to help you, because I do not understand where you get the line height of 70%, 120%, etc. and call it still leading. I do not find this in photoshop. There the concept of leading sets, as I understand it, the distance between the baselines of the lines.

In addition, it depends on the resolution of the document. See the screenshot.

a1.pnga2.png

Votes

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
community guidelines
Community Beginner ,
Jan 15, 2018 Jan 15, 2018

Copy link to clipboard

Copied

You can not find it in Photoshop, because it's in the CSS . This was a screenshot from Chrome. In CSS there is a line-height and it can be set as a percentage of the font size or in pixels. In Photoshop, there is leading and it can be set to AUTO (corresponds to the line height of 120% of the font size) or in pixels, points, etc.

The the line-height in CSS determines the actual height of the text block (even 1 line of text!) AND the distance between the lines of text. The leading in PS determines ONLY the distance between lines of text. That's the problem.

Example - 2 single-line text layers.

1st - font size 100px, leading 120px (auto);

2nd - font size 100px, leading 200px.

The vertical distance between the boundaries of the layers is 50px.

The browser shows that the visual vertical distance between the blocks is somewhere around 100px because of the 200px line-height of the 2nd layer.

2018-01-15_103334.png

2018-01-15_104354.png

Votes

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
community guidelines