0

My SVG has two text elements. After a certain amount of chars entered in one of them, I apply textLength attribute to make the text shrink to fit the container. I am looking for a way to automatically resize the other text element so the characters look the same size.

Basically, I want the two lines of text to automatically resize to the size of the smaller among them.

The attached code is an example. Please type 5 chars in the first line and one char in the second - at this point I want the second line char be the same size as the chars of the first one ( which has shrinked by now )

I tried Inspecting the page to understand which attribute of the shrink line I can interrogate to apply to the other line but to no prevail

function fit_text_horizontal( obj, text)
{
// how many chars can be here before the text starts to shrink
  // in the future this should be on per-font basis
  // i will need an interface, for each font specify :
  // maxi_line1_max_length_before_resize, 
  // maxi_line2_max_lenght_before_resize,
  // spot_line2_max_length_before_resize
  // etc
  // this is all because in SVG there is no way
  // to limit text resizing to shrink-only and I 
  // dont want it to grow, only shrink when too long
  var chars_threshold = obj.getAttribute("text_length_before_resizing");
  
  // when the text starts resizing(shrinking) - into what length
  // should it fit
  var custom_text_length = obj.getAttribute("custom_text_length");
  

  // if the text in l1 is long enough
  if (text.length >= chars_threshold)
   {
     // add all resizing properties
     obj.setAttribute("textLength",custom_text_length);
     obj.setAttribute("preserveAspectRatio","xMidYMid meet");
     obj.setAttribute("lengthAdjust","spacingAndGlyphs");
   }
  else
   {
     // if the text is small enough, make sure there are no
     // resizing attributes
     obj.removeAttribute("textLength");
     obj.removeAttribute("preserveAspectRatio");
     obj.removeAttribute("lengthAdjust");

   }
  obj.textContent = text;
  
}

function fit_lines_vertical(l1obj,l1text,l2text)
{
  var origin_y = l1obj.getAttribute("origin_y");
  
  if (l2text.length)
  {
      var move_y = l1obj.getAttribute("move_line1_y_when_line2_empty");
     // l2 is not empty, need to move line 1 up
    l1obj.setAttribute("y",origin_y - move_y);
  }
  else
   {
     l1obj.setAttribute("y",origin_y); 
   }
}
function line_Change(obj)
{

  var l1obj = document.getElementsByClassName('tag_line1')[0];
  var l1entry = document.getElementById('input1');
 
  var l2obj = document.getElementsByClassName('tag_line2')[0];
  var l2entry = document.getElementById('input2');
 
  fit_text_horizontal(l1obj,l1entry.value);
  fit_text_horizontal(l2obj,l2entry.value);
  
  fit_lines_vertical(l1obj,l1entry.value,l2entry.value);
}
html,body,svg { height:70% }
<svg id="maxi" version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
     y="0px" width="240" height="60" xml:space="preserve">

 <g class="Guides">
  <g class="tag_center_area">
   <text class="tag_line1" stroke="#000000" x="107" y="35.8" origin_y="35.8" fill="#FFFFFF"  text-anchor="middle" font-family="'BNMiriBold'" font-size="25px" move_line1_y_when_line2_empty="7" text_length_before_resizing="5" custom_text_length="40">Line 1</text>
   <text class="tag_line2" stroke="#000000" text-anchor="middle"    text_length_before_resizing="5" custom_text_length="40" x="107" y="50.8" orig_y = "50.8" fill="#FFFFFF" font-family="'BNMiriBold'" font-size="25px" ></text>
  </g>
 
</svg>


  <input type="text" id="input1" onkeyup = "line_Change(this)" placeholder="Try typing something in here!">
  <label for="input1">Line 1</label>
   <input type="text" id="input2" onkeyup = "line_Change(this)" placeholder="Try typing something in here!">
  <label for="input2">Line 2</label>

Updates:

  1. Tried to have two tspans instead of two text elements. But textLength is not a style attribute and so is not inherited by the tspans. So it does not help.
  2. As per @Dennis suggestion from comments considered using manual text shrinking ( as per this ) but then saw concerns here and this path sounds less desirable due to font metrics calculation and getBBox browsers bugs ...
Louis Shraga
  • 773
  • 1
  • 7
  • 26
  • your [mcve] should be in the question itself, you shouldn't be trying to work around the restrictions that Stack Overflow has about not posting links to code without actual code in the question. – Robert Longson Jul 25 '18 at 20:26
  • oh, I wasnt, just did not understand the restriction. Editing. Thanks for the hint – Louis Shraga Jul 25 '18 at 20:29
  • I am trying to figure out how to sove it. But I thing it is not possible since the font-size is calculated on the count of the characters, – Dennis Jul 25 '18 at 20:36
  • @Dennis: can I (by means of JS) get the current font-size of the shrink line and apply it to the other one ? I tried to getAttribute("font-size") but it does not change when the text shrinks – Louis Shraga Jul 25 '18 at 20:40
  • @LouisShraga I just did that what you want, but because the font-size is not actually changing, you get the default value `var fontSize = window.getComputedStyle(l1obj).fontSize;` `console.log(fontSize);` – Dennis Jul 25 '18 at 20:42
  • @Dennis: can think of any other attribute which will reflect the actual size ? – Louis Shraga Jul 25 '18 at 20:44
  • Maybe you can use something from this post, https://stackoverflow.com/a/22580176/6385459 – Dennis Jul 25 '18 at 20:57

0 Answers0