Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG lengthAdjust only for shrinking but not for stretching

Tags:

text

svg

resize

Is there a nice and easy way to to have the functionality of lengthAdjust (together with textLength) for shrinking text if necessary (if too wide) but never attempting to stretch it?

Two possible solutions for a SVG generated through JS come to my mind:

  • Count characters (or rather grapheme clusters) and based on that (together with some heuristics unless a fixed-width size font is used) determine whether to set textLength or not.
  • First do it without textLength set and then determine using getBBox() whether the text needs some shrinking in which case textLength will be set.

Both solutions are IMHO quite ugly (and possibly buggy from my recollections of past encounters with getBBox()). Is there maybe some nicer solution I missed?

like image 305
phk Avatar asked Nov 08 '22 18:11

phk


1 Answers

Have a look at this: https://stackoverflow.com/a/39886640/1925631 Essentially, make a path which spans the exact coordinates where you want to spread your text on a path. Measure this path. Then, measure how many pixels your text requires, with a font-size of 1px (and other desired font-features). Now adjust the font-size to fill your desired percentage of the available path advance width. Adjust start-offset and text-anchor. Now finally calculate your author specified textLength and choose a lengthAdjust value to get exact alignment on low precision / non-conformant renderers.

Finally, if you need to support viewers without text on a path rendering support, you can use a conformant viewer with javascript support to create a backwards compatible/fallback version. Render the content and use the SVG DOM api to fetch the x, y and rotate values for each character/glyph, now create a new SVG DOM representation with those attributes specified. You might need javascript to calculate absolute width and height for the root svg element as well, and a correctly specified viewBox, and cascade/resolve/convert all css selectors/rules/properties to inline attributes. But this way you can get cross-platform, cross-browser/viewer rendering of text, with a single compilation step per immutable source file version.

I've also made a gist to ease the last step, of resolving the css and removing all classNames, while preserving the rendered end-result: https://gist.github.com/msand/4b37d3ce04246f83cb28fdbfe4716ecc

This is for the purpose of a single universal svg + javascript codebase, and web+ios+android software development (based on react + react-native + react-native-svg)

like image 167
msand Avatar answered Dec 08 '22 05:12

msand