If you need your svg files to be self contained,
you should consider embedding the font-files as base64 resource (using a tool like transfonter):
1. Example: font embedded as base64
This svg would display the custom font as long as your application supports CSS (inlined svg, referenced in img element, opened directly in browser).
<p>(Letter "a" is not contained in the reduced character subset)</p>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
<style>
@font-face {
font-family: 'easyPrint';
src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
font-weight: normal;
}
</style>
<text
x="10"
y="30"
class="word"
font-family="easyPrint"
font-size="25"
>
TESTa
</text>
</svg>
You can significantly reduce file size by subsetting your font:
Only selected characters will be available.
If you're deploying google fonts you may also try vecta's nano optimizer which has a pretty need auto-embedding feature for publically available google fonts.
2. Example: Svg2Png
This approach requires the font to be inlined as dataURL.
Otherwise the png output will render a default font like Times.
function svg2Png(selector) {
const svgEl = document.querySelector(selector);
let svgVB = svgEl.getAttribute('viewBox');
let svgVBArr = svgVB ? svgVB.split(' ') : '';
let svgVBW = svgVBArr ? svgVBArr[2] : '';
let svgVBH = svgVBArr ? svgVBArr[3] : '';
let svgClientBB = svgEl.getBoundingClientRect();
let svgClientW = svgClientBB.width;
let svgClientH = svgClientBB.height;
let svgBB = svgEl.getBBox();
let svgW = svgVBW? svgVBW : svgBB.width;
svgW = svgClientW > svgW ? svgClientW : svgW;
let svgH = svgVBH? svgVBH : svgBB.height;
svgH = svgClientH > svgH ? svgClientH : svgH;
let blob = new Blob([svgEl.outerHTML], {type: 'image/svg+xml'});
let URL = window.URL;
let blobURL = URL.createObjectURL(blob);
let tmpImg = new Image();
tmpImg.src = blobURL;
tmpImg.width = svgClientW > svgW ? svgClientW : svgW;
tmpImg.height = svgClientH > svgH ? svgClientH : svgH;
tmpImg.onload = () => {
let canvas = document.createElement("canvas");
canvas.width = svgW;
canvas.height = svgH;
let context = canvas.getContext("2d");
// draw blob img to canvas with some delay
setTimeout(function () {
context.drawImage(tmpImg, 0, 0, svgW, svgH);
let pngDataUrl = canvas.toDataURL();
let svgImg = document.createElement("img");
svgImg.width = svgW;
svgImg.height = svgH;
svgImg.class = "svgImg";
svgImg.src = pngDataUrl;
// just additional wrapping for example usage
let imgWrp = document.createElement("div");
imgWrp.setAttribute("class", "img-wrp");
imgWrp.appendChild(svgImg);
document.body.appendChild(imgWrp);
}, 300);
};
}
svg,
img{
border:1px solid #ccc
}
.svg-wrp{
position:relative;
overflow:auto;
resize:both;
width:50%;
}
<div class="btn-wrp">
<button type="button" onclick="svg2Png('svg')">svg2Png</button>
</div>
<div class="svg-wrp">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
<style>
@font-face {
font-family: 'easyPrint';
src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
font-weight: normal;
}
</style>
<text
x="10"
y="30"
class="word"
font-family="easyPrint"
font-size="25"
>
TEST
</text>
</svg>
</div>
3. Example: create svg with text rendered as path
This example deploys the opentype.js library.
Opentype.js has a handy function font.getPath()
allowing you to render string as a svg <path>
element based on the before loaded font file.
let svgcontainer = document.querySelector('#svgcontainer');
let inputText = document.querySelector('#inputText');
// opentype.js accepts only ttf and otf
let fontFile = 'https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf';
inputText.addEventListener('change', function(e) {
let testString = e.currentTarget.value;
let params = {
string: testString,
font: fontFile,
fontSize: 100,
x: 0,
y: 0,
decimals: 3
}
text2Path(params)
})
//default
let params = {
string: inputText.value,
font: fontFile,
fontSize: 100,
x: 0,
y: 0,
decimals: 3
}
text2Path(params)
function text2Path(params) {
opentype.load(params.font, function(err, font) {
if (!err) {
let options = params.options;
let path = font.getPath(params.string, params.x, params.fontSize, params.fontSize, options);
let textPath = path.toSVG(params.decimals);
let newSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
newSvg.classList.add('svgText');
newSvg.setAttribute('xmlns', "http://www.w3.org/2000/svg");
newSvg.insertAdjacentHTML('beforeend', textPath);
svgcontainer.appendChild(newSvg);
// adjust bbox
let bb = newSvg.getBBox();
newSvg.setAttribute('viewBox', '0 0 ' + (bb.width + bb.x) + ' ' + (params.fontSize * 1.5));
//add downloadbtn
let btnDownload = document.createElement("a");
btnDownload.setAttribute('download', 'font-' + params.string + '.svg');
btnDownload.textContent = 'Download';
let dataURl = getDataUrl(newSvg.outerHTML, 'image/svg+xml');
btnDownload.href = dataURl;
svgcontainer.appendChild(btnDownload)
} else {
console.log('Font could not be loaded: ' + err);
}
});
}
function getDataUrl(str, mime) {
let dataUrl = 'data:' + mime + ';base64,' + btoa(unescape(encodeURIComponent(str)))
return dataUrl;
}
.svgText {
height: 10em;
display: inline-block;
border: 1px solid #ccc;
}
a {
display: block
}
<script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>
<div class="layout">
<div class="frm-wrp">
<input id="inputText" type="text" value="Test">
</div>
<div class="svgcontainer" id="svgcontainer"></div>
</div>
Alternative: convert text to path in graphic editor
This is probably the most convenient solution.
- Make sure the desired font is installed locally (in you OS).
- Open your svg in an graphic editor like inkscape.
- select you
<text>
elements and convert them to paths:
inkscape: Path / Object to path
Adobe Illustrator: Type / Create Outlines
Font embedding in SVG
SVG won't automatically include/embed all used fonts!
As mentioned before: Whether an application can handle embedded fonts heavily depends on its CSS support.
Most image viewers will fail.
Editing SVGs with embedded fonts
Usually, this won't work at all even if your using advanced editors like inkscape. Usually desktop applications rely on the system based font management so they can't access embedded font subsets in an editable mode.
You may also try to convert your svg to pdf within the browser and convert all fonts to path outlines when opening.
Inkskape (free and open source) has an option for this "Draw all text". (see also this post).
./easy-print-regular.ttf
instead of./easy-print.regular.ttf
? – Richela