I am generating an svg, with text, using D3.js for a user to download.
Unfortunately, when an svg is downloaded, the font family applied to the text on the svg does not appear to be included when the svg is converted to canvas, then downloaded as a png.
The font styling appears to be missing.
Is there a way to construct the png with this font family applied?
To download the svg as a png, I adapted the answer described here.
Here is my process:
First, I create the svg.
await d3.xml(`img_templates/${template}_${dimensions}.svg`)
.then(data => {
divsvg.append(data.documentElement) //Append svg to DOM
});
Then, I add my text elements to the svg
const quoteText = quoteGroup.append("text")
.attr("class", "quote")
.style("font-size", `15px`)
.style("font-family", 'Merriweather')
Merriweather is a Google font family that I load in the head of a html page like so:
<head>
<link href="https://fonts.googleapis.com/css2?family=Merriweather&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,700;1,400&display=swap" rel="stylesheet"> <!--Another font I use-->
<script src="d3.min.js"></script>
<script src=genImage.js></script> <!--The js code to interact with the svg -->
</head>
On download, I execute the following functions on the svg,
function downloadSVG(svgObj){
var data = (new XMLSerializer()).serializeToString(svgObj);
var DOMURL = window.URL || window.webkitURL || window;
var img = new Image();
var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svgBlob);
img.onload = function () {
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
var imgURI = canvas
.toDataURL('image/png')
.replace('image/png', 'image/octet-stream');
// console.log(imgURI)
triggerDownload(imgURI);
};
img.src = url;
}
function triggerDownload (imgURI) {
var evt = new MouseEvent('click', {
view: window,
bubbles: false,
cancelable: true
});
var a = document.createElement('a');
a.setAttribute('download', 'MY_COOL_IMAGE.png');
a.setAttribute('href', imgURI);
a.setAttribute('target', '_blank');
a.dispatchEvent(evt);
}
When serialized to string the svg appears as such:
<svg xmlns="http://www.w3.org/2000/svg" width="484" height="484" viewBox="0 0 484 484" fill="none">
<g class="quoteGroup" transform="translate(42,100)">
<text class="quote" fill="#FFFFFF" style="font-size: 25px; font-family: Merriweather;"><tspan x="0">"I’m staying alone in Montauk at a</tspan><tspan x="0" dy="40px">friend’s house while he’s in Portugal</tspan><tspan x="0" dy="40px">(something about taxes and quality of</tspan><tspan x="0" dy="40px">life). After my morning coffee and</tspan><tspan x="0" dy="40px">power shake, it’s time to water the</tspan><tspan x="0" dy="40px">plants."</tspan></text>
</g>
<g class="headlineGroup" transform="translate(42,365)">
<text class="headline" font-size="15px" fill="#FFFFFF" style="font-family: Roboto; font-style: italic;"><tspan x="0">Stop Thinking of the Breakup of Big Tech as Punishment</tspan></text>
</g>
<g class="publisherGroup" transform="translate(42,430)">
<text class="publisher" font-size="15px" fill="#FFFFFF" style="font-family: Roboto; font-weight: bold;">Marker</text>
</g>
<g class="dateGroup" transform="translate(353,430)"><text class="date" font-size="15px" fill="#FFFFFF" style="font-family: Roboto; font-weight: bold;">Aug 04, 2020</text></g>
</svg>
From what I can tell, the font family is being correctly specified in the string, yet when the svg is converted to canvas and then png, it is being lost. Why might this happen?
Please let me know if I can provide any additional information. Any assistance is greatly appreciated!