Mistakes in design when transforming inline SVG to PNG format

One of my main objectives is to convert a <div> element that contains multiple inline svg images into a png file. The entire process must be carried out within the client's browser using JavaScript. I have experimented with various techniques:

  1. Utilizing the canvg library and following the guidelines outlined in this post: https://github.com/niklasvh/html2canvas/issues/95#issuecomment-34439223

    original svg:

    result:

  2. Compacting the css styles into the <svg> tag and then invoking canvg, based on the instructions from this post: Convert embedded SVG to PNG in-place

    result: an empty image.

  3. Condensing the css styles into the <svg> tag and manually sketching the svg on a canvas, following the steps provided in this post: how to save/ export inline SVG styled with css from browser to image file

    result: an empty image.

  4. Streamlining the css styles into an inline style sheet using this code:

    result: an empty image.

  5. employing svg crowbar to manually save the <div> element as an .svg file.

    result:

    afterwards, when comparing the computed css of the original svg with the downloaded svg, it was discovered that the downloaded svg contained the correct svg xml but the wrong inline stylesheet (<style type="text/css">) For example, the numbers 200, 300 on the extreme right of the graph were rendered as

    <text x="214" dy=".32em" y="0" style="text-anchor: start;">200</text>
    whereas in my external css, I had:

    .scatterChart .axisGraphicsContext text { font-size: 8px; fill: #777; }

    Nevertheless, the font-size and fill properties were absent from the inline stylesheet of the downloaded svg.

Answer №1

After much searching, I finally stumbled upon a solution for exporting CSS-created PNGs through Rickshaw (which is based on D3). The only workaround I could find involved:

  • treating the DIVs separately from the SVGs, and handling each one individually
  • converting the DIVs (and any non-SVG content) to canvas using html2canvas
  • Inlining the CSS to the SVG; @thirdcreed has shared the JavaScript code and D3 selectors for this at: Rickshaw CSS/Axes in JSDOM - you'll need to adjust it to fit your custom CSS.
  • Converting the SVGs to canvas with code like this:

    var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html2);
    var img = '<img src="'+imgsrc+'">';      
    var canvas = document.querySelector("canvas"),
    context = canvas.getContext("2d");      
    var image = new Image;
    image.src = imgsrc;
    image.onload = function() {
      context.drawImage(image, 0, 0);
    }
    
  • merging all the different canvases into one
  • Converting into an image with code similar to this:

    var canvasdata = canvas.toDataURL("image/png");
    var pngimg = '<img src="'+canvasdata+'">'; 
    d3.select("#pngdataurl").html(pngimg); // adjust if not using D3
    var a = document.getElementById("some_anchor"); // Fix for Firefox: include a hidden anchor tag here for download to work
    a.download = "sample.png";
    a.href = canvasdata;
    a.click();
    

Keep in mind that all browsers, except for Internet Explorer, require SVGs to have the xmlns attribute.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble with your Ajax request to Google App Engine?

I've developed a GAE application that handles JSON requests and provides JSON responses. It's been tested successfully with an Android app, but now I'm attempting to create a JavaScript-based interface for web browsers. My goal is to send a ...

Are you experiencing issues with your Ajax request?

I've been struggling to retrieve json data from an API. Despite my efforts, the GET request seems to be executing successfully and returning the correct data when I check the Net tab in Firebug. Can anyone offer advice on what could be going wrong or ...

Is it possible to use Jade for server-side Node.js development?

Is there a way to include server-side Node.js code (like the example below) in a Jade file or other template engines (or without using template engines)? extends layout block content p Welcome to #{title} <!-- Here is some Node.js program that r ...

Retrieving the class name using jQuery

In my HTML code, there is a div with three classes defined as: <div class = "a b c"> .. </div> My goal is to access only the class b using the .attr() method. Is this achievable? ...

Attempting to utilize the JavascriptExecutor for button testing, however encountering an error message stating 'Unexpected keyword or identifier'

When I look at my code, I see this line: JavascriptExecutor js = (JavascriptExecutor) driver; A red line appears underneath it with the error message Unexpected keyword or identifier I attempted to resolve this by importing org.openqa.selenium.Javascrip ...

Manipulate classes based on scrolling (Wordpress)

Trying to manipulate a widget by adding and removing classes based on user scroll behavior has proven to be quite challenging. Specifically, I aim to add one class when the user scrolls down by 50px and remove it when they scroll back up. Website: Check o ...

Solving the issue of .css being blocked due to MIME type while building tailwind is a common problem faced by

https://i.stack.imgur.com/nrDgJ.png While working on my tailwind CSS project, I ran npm run build. However, upon opening the built index.html file, I noticed that the CSS file was not loading properly. How can I resolve this issue? I am unsure of what st ...

Choose an XPath formula that will target every single element, text node, and comment node in the original sequence

How can we write an XPath expression that selects all elements, text nodes, and comment nodes in the order they appear in the document? The code below selects all elements but not text nodes and comment nodes: let result = document.evaluate('//*&apo ...

"Choosing multiple options in Select2 causes it to constrict within a Bootstrap 4 inline

I am facing an issue where the field shrinks drastically when I type in it. Here's a code snippet that showcases this problem: $(function() { $("select").select2({ placeholder: "Select a word", width: "100%" }); }); <link rel ...

Need a place to keep your data safe while using nodejs?

I have taken on the task of developing a lastfm plugin for a chat bot that my friend created. One feature I want to include is the ability for users to register their hostmask/nick with their lastfm username (for example, using the command !reg lastfmuser ...

What are some ways to implement drop-down functionality using CSS?

I've been working on tweaking the CSS of this website for what feels like an eternity. I just can't seem to figure out how to make the "medical" menu item drop down to display the rest of the hidden menu items. I've managed to unhide and exp ...

How can we incorporate a Material-UI skeleton to display API response data effectively?

I have incorporated the material-ui skeleton (Shimmer effect) to display data fetched from an API. { accountData.usersAccountData.map((userData, index) => ( // ...UI code ) ) } The output is shown below : https://i.sstatic.net/MEVhA.png It can be o ...

Function starting too slow due to rapid Loading Spinner Image display

I am struggling with a function that is supposed to display the contents of posts when clicked on. My goal is to have a loading spinner appear for a few seconds before the post content shows up. However, I am facing an issue where the spinner only appears ...

Troubleshooting problems with image display following jQuery animation

Check out this awesome page I found: where you can see a neat list of blog posts displayed in rows of 4. I've added a cool jQuery animation to the 'cards' so that they fade in one by one: jQuery('.fade-in-post-container .elementor-po ...

Are there any alternative methods to avoid duplication of Navbar link margin classes in Tailwind CSS?

It feels really repetitive to have to add margin classes to each LI manually on a non-dynamically generated menu. It almost seems as messy as using inline style attributes... Is there a more efficient way to handle this? While it may not be a big deal fo ...

State change shows the previous and current values simultaneously

I've been working on updating the values of initUsers on the DOM. The initial state values work fine, but when I try to update initUsers, it displays different values than expected. Essentially, entriesNum receives a number as an event and changes th ...

Is there a way to use AJAX to call only a specific PHP function without reloading the entire page

I am trying to retrieve data only from the php function instead of the entire page data. Here is the content of my demo.php file: <? echo "Whole Page data"; $name = $_POST['name']; if ($name == "demo"){ demo(); } ...

Selecting options using AngularJS to parse through a list

I am faced with a challenge involving a collection of strings representing years. Here is an example: $scope.years = ["2001", "2002", "2003", ...]; My goal is to display these values in a select tag within a web page. However, whenever I attempt this usi ...

"An error message stating 'Express: The body is not defined when

I'm encountering an issue while trying to extract data from a post request using express. Despite creating the request in Postman, the req.body appears empty (console.log displays 'req {}'). I have attempted various solutions and consulted s ...

The perplexing configuration of a webpack/ES6 project

I am currently in the process of setting up my very first ES6 and webpack "application" where I aim to utilize classes and modules. However, each time I attempt to transpile the application using the webpack command, I encounter the following error: $ web ...