I am trying to convert text to svg in my React web app, but the resulted svg code which i am getting is not right, t's not showing svg.
Code:
import opentype from "opentype.js"
async function textToPath(){
const text = "Hello"
const size = {x: 50, y: 25}
const fontFile = "https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf"
let params = {
string: text,
font: fontFile,
fontSize: size.x,
decimals: 1,
singleGylyphs: false
}
const font = await opentype.load(params.font);
let options = params.options;
let unitsPerEm = font.unitsPerEm;
let ratio = params.fontSize / unitsPerEm;
let ascender = font.ascender;
let descender = Math.abs(font.descender);
let ratAsc = ascender / unitsPerEm;
let ratDesc = descender / unitsPerEm;
let yOffset = params.fontSize * ratAsc;
let lineHeight = params.fontSize + params.fontSize * ratDesc;
let singleGylyphs = params.singleGylyphs;
let teststring = params.string.split("");
let glyphs = font.stringToGlyphs(params.string);
let leftSB = glyphs[0].leftSideBearing * ratio;
let textPath = "";
//individual paths for each glyph
if (singleGylyphs) {
let paths = font.getPaths(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
paths.forEach(function (path, i) {
let pathEl = path.toSVG(params.decimals);
textPath += pathEl.replaceAll(
"d=",
'class="glyph glyph-' + teststring[i] + '" d='
);
});
}
//word (all glyphs) merged to one path
else {
let path = font.getPath(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
textPath += path
.toSVG(params.decimals)
.replaceAll("d=", 'class="glyph" d=');
}
// render
let fontSvgWrp = document.createElement("div");
fontSvgWrp.classList.add("fontSvgWrp");
let fontSvg = document.createElementNS(
"http://www.w3.org/2000/svg",
"svg"
);
fontSvg.classList.add("svgText");
fontSvg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
fontSvg.innerHTML = textPath;
fontSvgWrp.appendChild(fontSvg);
// adjust bbox
let bb = fontSvg.getBBox();
let stringWidth = Math.ceil(bb.width + bb.x);
fontSvg.setAttribute("viewBox", "0 0 " + stringWidth + " " + lineHeight);
fontSvg.setAttribute("width", size.x);
fontSvg.setAttribute("data-asc", ratAsc);
console.log(fontSvg); // getting svg code
let textPathSvg = fontSvg.querySelector(".glyph");
let textPathLength = textPathSvg.getTotalLength();
return textPathLength
}
It's generating this svg which is not working:
<svg class="svgText" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 5013.25" width="50" data-asc="0.935"><path class="glyph" d="M24 46.8L19.3 46.8L19.3 30.6L4.8 30.6L4.8 46.8L0 46.8L0 12.3L4.8 12.3L4.8 26.7L19.3 26.7L19.3 12.3L24 12.3L24 46.8ZM53.7 32.8Q53.7 34.0 53.5 35.1L53.5 35.1L36.8 35.1Q37.0 39.5 39.0 41.5Q40.9 43.6 43.9 43.6L43.9 43.6Q45.8 43.6 47.4 43.0Q49.0 42.5 50.7 41.3L50.7 41.3L52.7 44.0Q48.5 47.4 43.5 47.4L43.5 47.4Q38 47.4 34.9 43.8Q31.9 40.1 31.9 33.9L31.9 33.9Q31.9 29.8 33.2 26.6Q34.5 23.4 37.0 21.6Q39.5 19.8 42.8 19.8L42.8 19.8Q48.0 19.8 50.9 23.3Q53.7 26.7 53.7 32.8L53.7 32.8ZM49.1 31.8L49.1 31.4Q49.1 27.5 47.5 25.5Q46 23.4 42.9 23.4L42.9 23.4Q37.3 23.4 36.8 31.8L36.8 31.8L49.1 31.8ZM66.3 47.4Q63.7 47.4 62.2 45.8Q60.8 44.3 60.8 41.5L60.8 41.5L60.8 9.8L65.3 9.3L65.3 41.5Q65.3 42.5 65.7 43.0Q66.1 43.5 67 43.5L67 43.5Q68.0 43.5 68.7 43.3L68.7 43.3L69.9 46.5Q68.3 47.4 66.3 47.4L66.3 47.4ZM80.9 47.4Q78.4 47.4 76.9 45.8Q75.4 44.3 75.4 41.5L75.4 41.5L75.4 9.8L80 9.3L80 41.5Q80 42.5 80.4 43.0Q80.8 43.5 81.7 43.5L81.7 43.5Q82.6 43.5 83.4 43.3L83.4 43.3L84.6 46.5Q82.9 47.4 80.9 47.4L80.9 47.4ZM100.2 19.8Q105.8 19.8 108.8 23.5Q111.9 27.2 111.9 33.5L111.9 33.5Q111.9 37.6 110.5 40.8Q109.1 43.9 106.5 45.6Q103.8 47.4 100.2 47.4L100.2 47.4Q94.6 47.4 91.5 43.6Q88.4 40.0 88.4 33.6L88.4 33.6Q88.4 29.5 89.8 26.4Q91.2 23.3 93.9 21.5Q96.5 19.8 100.2 19.8L100.2 19.8ZM100.2 23.5Q93.4 23.5 93.4 33.6L93.4 33.6Q93.4 43.6 100.2 43.6L100.2 43.6Q107.0 43.6 107.0 33.5L107.0 33.5Q107.0 23.5 100.2 23.5L100.2 23.5Z"></path></svg>
I tried & searched a lot but i didn't get anything to fix this thing and why the converted svg is not working. Can someone help?
The svg output is actually OK but your
viewBoxisn't calculated correctly.The viewBox width value is 0 – so your path is completely cropped/invisible.
The main problem in your script: you need to append the svg to your DOM otherwise
getBBox()will return an empty object (or width:0, height:0).It should rather look like this:
Example: appending svg before getBBox()
Alternative: calculate total width from glyph data
If you don't want to append the svg you could also calculate the viewBox width using the
getAdvanceWidth()(for seperate glyph paths) or getBoundingBox() method: