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:
- 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.
- 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 ...