We need to render SVG images on canvas with Firefox, but Firefox doesn't render SVG images without explicit values for the width and height attributes.
Our users upload SVG images like the ones below without width and height attributes.
How can we use Javascript to dynamically add width and height attributes? The approach below fails.
We read the SVG image as a data URL using FileReader
and convert this data URL into a SVG doc with the function below.
Finally, we turn the modified SVG doc into a data URL for rendering on canvas. But the modified SVG doc has the same zero width/height issue as the original.
Codepen: https://codepen.io/Crashalot/pen/vYGJzdN
$('#file').on('change', function() {
didPickFile($(this));
});
function didPickFile(fileElement) {
// Get image file.
let imageFile = fileElement[0].files[0];
// Get image data.
didImageUpload(imageFile);
// Clear filepath so user can reupload same file.
fileElement.val('');
}
function didImageUpload(file) {
let reader = new FileReader();
// Process image when picked.
reader.onload = async function(e) {
// Get data URL for image.
let dataUrl = reader.result;
let svgSize = {
width: 512,
height: 500
}
let svgDoc = dataURLToSVGDoc(dataUrl);
let unit = 'px';
$(svgDoc).attr('width', svgSize.width + unit);
$(svgDoc).attr('height', svgSize.height + unit);
let newDataURL = svgDocToDataURL(svgDoc);
}
// Read image from hard disk.
reader.readAsDataURL(file);
}
function dataURLToSVGDoc(dataURI) {
// Set default result.
let svgDoc = null;
// Set RegEx vars.
let svgURIRegEx = /data:image\/svg\+xml;(base64|charset=utf8),(.*)/;
// Read data URI.
let uriMatch = svgURIRegEx.exec(dataURI);
if (uriMatch) {
// Set default SVG string.
let svgStr = '';
// Base64? Convert Base64 -> SVG.
if (uriMatch[1] === 'base64') {
svgStr = atob(uriMatch[2]);
// Not Base64, ensure no URL-encoded characters.
} else {
svgStr = decodeURI(uriMatch[2]);
}
// Convert SVG string -> SVG doc.
let parser = new DOMParser();
svgDoc = parser.parseFromString(svgStr, 'image/svg+xml');
}
// Return result.
return svgDoc;
}
function svgDocToDataURL(svgDoc, base64) {
// Set SVG prefix.
const svgPrefix = "data:image/svg+xml;";
// Serialize SVG doc.
var svgData = new XMLSerializer().serializeToString(svgDoc);
// Base64? Return Base64-encoding for data URL.
if (base64) {
var base64Data = btoa(svgData);
return svgPrefix + "base64," + base64Data;
// Nope, not Base64. Return URL-encoding for data URL.
} else {
var urlData = encodeURIComponent(svgData);
return svgPrefix + "charset=utf8," + urlData;
}
}
Sample SVG Icon
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 502.2" style="enable-background:new 0 0 512 502.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#7C7A7D;}
</style>
<path class="st0" d="M25.1,178.7L0.5,40.9C-2.8,22,9.8,3.9,28.7,0.5l0,0c18.9-3.4,37,9.2,40.4,28.2l24.5,137.8
c3.4,18.9-9.2,37-28.2,40.4l0,0C46.5,210.2,28.5,197.6,25.1,178.7z"/>
<path class="st0" d="M55.2,137.9l138.9-17.3c19.1-2.4,36.5,11.2,38.8,30.2l0,0c2.4,19.1-11.2,36.5-30.2,38.8L63.8,206.9
c-19.1,2.4-36.5-11.2-38.8-30.2l0,0C22.6,157.7,36.2,140.3,55.2,137.9z"/>
<path class="st0" d="M506.6,304.6c0-0.2,0.1-0.5,0.1-0.7c6-27.2,7.5-55.7,3.8-84.7c-2.1-16.3-5.8-32.1-10.8-47.2c0,0,0,0,0-0.1
c-0.5-1.5-1-3-1.6-4.6c-0.3-0.8-0.5-1.5-0.8-2.3c-0.3-0.8-0.6-1.5-0.9-2.3c-0.6-1.5-1.1-3-1.7-4.5c0,0,0,0,0-0.1
c-5.9-14.8-13.3-29.2-22.2-43C456.5,90.7,437,69.9,414.9,53c-0.2-0.1-0.4-0.3-0.6-0.4c-0.8-0.6-1.6-1.2-2.3-1.8
C361.4,12.7,296.6-6.6,229.5,2C176.8,8.7,128,32,89.7,67.8c-1.7,1.6-3.2,3.3-4.4,5.1c-25.2,24.8-44.8,54.7-57.7,87.7
c-7.7,19.8,4.3,41.8,25,46.3l0,0c16.7,3.6,33.3-5.6,39.6-21.5C124.1,104.2,211.9,55,299.7,73.8c62.4,13.4,110.8,58.1,132,114.2
c0.1,0.3,0.2,0.6,0.4,1c0.1,0.3,0.2,0.6,0.3,1c20,56.5,12,121.9-27.1,172.4c-61,78.9-176.2,93.7-255.1,32.7
c-30.5-23.6-52.5-56-63.2-92.5c-4.8-16.2-20.7-26.4-37.5-24.2h0c-21.2,2.7-34.9,23.7-28.8,44.2c10.3,34.5,27.8,65.7,50.6,92
c1.2,2,2.5,3.8,4.1,5.6c81,89.3,218.5,109.8,322.7,42.4c56.8-36.8,93.8-93.3,107.9-155C506.1,306.5,506.3,305.5,506.6,304.6z"/>
</svg>