简体   繁体   中英

javascript, d3 save svg as png loses color and font

I have svg-png almost working perfectly client side, just in javascript/d3 it all works, but it loses large amounts of detail. Can anyone shed light on why this might be?: The original image is:

originalimage

var svg = document.querySelector( "svg" );
var svgData = new XMLSerializer().serializeToString( svg );

var canvas = document.createElement("canvas");
canvas.width = d3.select("svg").attr("width");
canvas.height = d3.select("svg").attr("height");
ctx = canvas.getContext("2d");

var img = document.createElement( "img" );
img.setAttribute( "src", "data:image/svg+xml;base64," + btoa( svgData ) );

img.onload = function() {
    ctx.drawImage( img, 0, 0 );

    var canvasdata = canvas.toDataURL("image/png");

    console.log(canvasdata)
    var pngimg = '<img src="'+canvasdata+'">'; 
    d3.select("#pngdataurl").html(pngimg);

    var a = document.createElement("a");

    a.download = "name"+".png";
    a.href = canvasdata;
    console.log(a.click())
};

The output of that is:

SVG-PNG

I also tried:

  var html = d3.select("svg")
    .attr("version", 1.1)
    .attr("xmlns", "http://www.w3.org/2000/svg")
    .node().parentNode.innerHTML;
var width = d3.select("svg").attr("width");
var height = d3.select("svg").attr("height");
image.src = 'data:image/svg+xml;base64,'+    btoa(unescape(encodeURIComponent(html))); 

but that fails - on the image.onload() I get "HTMLImageElement provided is in the 'broken' state"

Saving an SVG to PNG in the browser will ignore all linked CSS styles applied to the SVG elements. If you are using d3.js you can add the styles directly to the elements of a particular class using:

d3.selectAll(".mg-main-area").style("color","red");

For more details see this article, which I wrote about rasterising SVG in the browser.

From the comments it seems you have library applying the CSS, so if you don't want to override the styles manually using d3, you could use jQuery code like the below to pull all CSS elements from a class and apply them as inline styles:

$('.mg-main-area').each(function(i, e) {
    var st = e.style;
    var props = [];
    for(var prop in st) { 
        if($(this).css(prop)) {
            props.push(prop + ':' + $(this).css(prop));
        }
    }
    this.style.cssText = props.join(';');
    $(this).children().makeCssInline();
}); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM