首页 > 解决方案 > 带有两个文本元素的 SVG。当一个因 textLength 而调整大小时 - 如何将另一个调整为相同的字符大小

问题描述

我的 SVG 有两个文本元素。在其中一个字符中输入一定数量的字符后,我应用 textLength 属性使文本缩小以适合容器。我正在寻找一种方法来自动调整其他文本元素的大小,使字符看起来大小相同。

基本上,我希望两行文本自动调整为其中较小的大小。

附上的代码是一个例子。请在第一行键入 5 个字符,在第二行键入一个字符 - 此时我希望第二行字符的大小与第一行字符的大小相同(现在已经缩小)

我尝试检查页面以了解我可以询问收缩线的哪个属性以应用于另一条线但没有占上风

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>

更新:

  1. 试图有两个 tspan 而不是两个文本元素。但是 textLength 不是样式属性,因此不会被 tspan 继承。所以它没有帮助。
  2. 根据@Dennis 的建议,考虑使用手动文本缩小(根据),但随后在这里看到了问题,并且由于字体度量计算和 getBBox 浏览器错误,这条路径听起来不太理想......

标签: svgresize

解决方案


推荐阅读