Home > front end >  How can I embed images in an SVG I'm saving using javascript?
How can I embed images in an SVG I'm saving using javascript?

Time:08-24

I have an SVG on the page that I am saving using code I found in this question, which works well. My problem is that my SVG loads images via links, and these links require the user to be logged in. Generating an SVG for download means these links can't be resolved.

The images should be able to be embedded in the SVG, but I'm not sure how to go about doing this in JavaScript. I have not managed to find any relevant questions on here that help with this.

Is anyone able to help me through this?

My current code (from linked question):

function downloadSVG() {
    var svgData = $("#figureSvg")[0].outerHTML;
    var svgBlob = new Blob([svgData], {type:"image/svg xml;charset=utf-8"});
    var svgUrl = URL.createObjectURL(svgBlob);
    var downloadLink = document.createElement("a");
    downloadLink.href = svgUrl;
    downloadLink.download = "newesttree.svg";
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
}

CodePudding user response:

I've worked out a system that works. My main problem is that I need to replace many images in the SVG, and this happens asynchronously so I needed a way to continue when all were complete. I ended up with a working solution and wanted to post what I have, though I'm confident that others could improve on it. I basically created a recursive function that takes one image URL, creates an element to load it, then add a function to replace the URL with the data URL once it's loaded, then trigger a repeat call of the function. Once no more image URLs are found, we trigger the download. This is sequential so likely could be improved upon, but most images are already loaded or in the process of being loaded on my page so it's pretty much instant for me.

I used various other questions to put this together. In particular:

How to Download and SVG element as an SVG file

Convert image from url to Base64

How do I save/export an SVG file after creating an SVG with D3.js (IE, safari and chrome)?

Here's my code:

// Download SVG file - call this function
function downloadSVG() {
    const svg = document.getElementsByTagName('svg')[0].cloneNode(true);
    // Replace image URLs with embedded data  for SVG also triggers download
    replaceImageURLs(svgData, "svg", null);
}

// Find image URLs and replace with embedded versions
function replaceImageURLs(svg, type, img) {
    let protocol = "http";
    let start = '<image xlink:href="' protocol;
    let startPos, len, url;
    if (svg.indexOf(start) !== -1) {
        startPos = svg.indexOf(start) start.length-protocol.length;
        len = svg.substring(startPos).indexOf("\"");
        url = svg.substring(startPos,startPos len);
        const img2 = document.createElement("img");
        img2.onload = function() {
            let base64 = getBase64Image(img2);
            svg = svg.replace(url,base64);
            replaceImageURLs(svg, type, img);
            img2.remove();
        }
        img2.src = url;
    } else {
        const svgBlob = new Blob([svg], {type: "image/svg xml;charset=utf-8"});
        const svgUrl = URL.createObjectURL(svgBlob);
        downloadLink(svgUrl, "gvexport." type);
    }
}

// Convert image URL to base64 data - we use for embedding images in SVG
// From https://stackoverflow.com/questions/22172604/convert-image-from-url-to-base64
function getBase64Image(img) {
    const canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    const ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
    return canvas.toDataURL("image/png");
}

// Trigger a download via javascript
function downloadLink(URL, filename) {
    const downloadLink = document.createElement("a");
    downloadLink.href = URL;
    downloadLink.download = filename;
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
}
  • Related