31 Replies Latest reply on Jan 15, 2018 1:54 PM by pixxxel schubser

# A script for measuring the distance between two elements?

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.

• ###### 1. Re: A script for measuring the distance between two elements?

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.

• ###### 2. Re: A script for measuring the distance between two elements?

Also do not forget about the property boundsNoEffects )

• ###### 3. Re: A script for measuring the distance between two elements?

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.

• ###### 4. Re: A script for measuring the distance between two elements?

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

• ###### 5. Re: A script for measuring the distance between two elements?
How would the script know which elements you are interested in measuring.
Layers should be selected by shift.
• ###### 6. Re: A script for measuring the distance between two elements?

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?

• ###### 7. Re: A script for measuring the distance between two elements?

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?

• ###### 8. Re: A script for measuring the distance between two elements?

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
}
else

}
else

/////////////////////////////////////////////////////////////////////////////////////////////////
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)
{

return null;
}
}

return selected_bounds;
}

catch (e) { alert(e); return null; }
}
```
• ###### 9. Re: A script for measuring the distance between two elements?

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

• ###### 10. Re: A script for measuring the distance between two elements?

"It's a kind of Magic"!

Thanks a lot!

One thing... Could I put output numeric value right in clipboard too?

Other thing)... The ultimate goal was to get CSS margin/padding. You can see the discussion, but I do not recommend - too many words . The point is that distance in CSS is NOT equal to the distance in Photoshop for text layers. There is a very approximate formula:

border-line <> border-line (two shapes, e.g.)

``distance_CSS = distance_PS``

text <> border-line

``distance_CSS = distance_PS - (line-height - 0.7 * font-size) / 2``

text 1 <> text 2

``distance_CSS = distance_PS - (line-height_1 - 0.7 * font-size_1) / 2 - (line-height_2 - 0.7 * font-size_2) / 2``

How to put this formula in the script? Help here or there, if U pls.

• ###### 11. Re: A script for measuring the distance between two elements?

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!!!

• ###### 12. Re: A script for measuring the distance between two elements?

It's not entirely clear how to apply your formula. You mean by the height of the text, what you get with Ctrl-T text, ie. bounding box during the transformation?

You can get its FontSize for each layer. But there can be several for one layer. We can take the maximum. But still it is not clear how to know the height of the text, especially if there are several lines.

The simplest option. Temporarily replace all the symbols with the █ (SolidBlock symbol).
It has the maximum height for a given font.
After measuring the distance between the texts and return (undo) all in place.

The task is not very difficult but now there is no time for it. Later I'll try. )

• ###### 13. Re: A script for measuring the distance between two elements?

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?

• ###### 14. Re: A script for measuring the distance between two elements?

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
}
else

}
else

/////////////////////////////////////////////////////////////////////////////////////////////////
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);

{
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)
{

return null;
}
}

return selected_bounds;
}

catch (e) { alert(e); return null; }
}
```
• ###### 15. Re: A script for measuring the distance between two elements?

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!

• ###### 16. Re: A script for measuring the distance between two elements?
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

• ###### 17. Re: A script for measuring the distance between two elements?

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

• ###### 18. Re: A script for measuring the distance between two elements?

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!

• ###### 19. Re: A script for measuring the distance between two elements?

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

• ###### 20. Re: A script for measuring the distance between two elements?

(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

• ###### 21. Re: A script for measuring the distance between two elements?

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

• ###### 22. Re: A script for measuring the distance between two elements?

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?

• ###### 23. Re: A script for measuring the distance between two elements?

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) ?

• ###### 24. Re: A script for measuring the distance between two elements?

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:

• ###### 25. Re: A script for measuring the distance between two elements?

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.

• ###### 26. Re: A script for measuring the distance between two elements?

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.

• ###### 27. Re: A script for measuring the distance between two elements?

So, to correct this difference, I need to make calculations for this 2 layers.

``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;``

For above example it will be:

``distance_in_css = 50px - (120px - 1.2 * 100px) / 2 - (200px - 1.2 * 100px) / 2 = 50px - 0 - 40px = 10px;``

And now if we apply this 10px for CSS margin, the visual distance between text layers will be the same as in Photoshop - 50px

I just do not know how to add them to the script.(((

• ###### 28. Re: A script for measuring the distance between two elements?

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;

if (bounds)
{
if (bounds.length == 2)
{
var distance = 0;

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

var distance_in_css = distance - (bounds[0].leading - 1.2*bounds[0].size)/2 - (bounds[1].leading - 1.2*bounds[1].size)/2;

alert("distance = " + distance + "\ndistance_in_css = " + distance_in_css);
}
else

}
else

/////////////////////////////////////////////////////////////////////////////////////////////////
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);

var size    = 0;

{
var textStyleRangeList = ret.getObjectValue(stringIDToTypeID("textKey")).getList(charIDToTypeID("Txtt" ));

if (textStyleRangeList.count > 1) { alert("More than one textStyleRange in layer", "Oops!!"); }

var textStyle = textStyleRangeList.getObjectValue(0).getObjectValue(charIDToTypeID("TxtS" ));

size = textStyle.getUnitDoubleValue(stringIDToTypeID("size"));

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")),
size   : size,
};

selected_bounds.push(obj);
}
catch (e)
{

return null;
}
}

return selected_bounds;
}

catch (e) { alert(e); return null; }
}
```
• ###### 29. Re: A script for measuring the distance between two elements?

I'm sorry that this looks completely nonsense to you, but it works great! ;)) Thank you!

The only thing I used was the previous version of bounds:

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

Cause I don't want to take into account the effects - shadows, glows etc. I want to take into account stroke, but I do not think it's possible to do this separately.

So, we can consider the issue resolved . Thanks again!

Hmm.. Could I put the numeric value of distance_in_css right in clipboard?

• ###### 30. Re: A script for measuring the distance between two elements?

yeah.not  написал(а)

Hmm.. Could I put the numeric value of distance_in_css right in clipboard?

You can try like this )

```text_to_clip("1234567890");

function text_to_clip(txt)
{
app.system("echo " + txt + "|clip");
}
```
• ###### 31. Re: A script for measuring the distance between two elements?

Hmmh?

You want to get the line height?

Why not simply use text property?

```var aLay= app.activeDocument.activeLayer;
if(aLay.textItem) {