0

I am trying to convert an svg graph to a png image. To do so, I am first converting my svg graph to a canvas using the library 'canvg', and then I use the method canvas.toDataURL('image/png') to finally convert my graph into a png image. The reason why I am using the library 'canvg' is because I needed my code to work on ie9 and I couldn't find another way around, although I haven't tested on it yet.

All seems to work perfectly until I get the result, when I have noticed that all my paths are thicker than in the initial svg graph. So, trying to find out what I was doing wrong, I start doing small tests on http://canvg.github.io/canvg/examples/index.htm. It is then when I noticed that if I do not set the attribute fill to none either inline or in a css file then the path is thicker than one pixel. As my svg graph have some of the styles in a separate css file, I tried to flatten them (I took the idea from Convert embedded SVG to PNG in-place):

function flatten_svg_element_css(target){
    if (target.nodeType != Node.TEXT_NODE) {
        var cssStyle = window.getComputedStyle(target);
        if (cssStyle) {
            var fillStyle = '';
            if( cssStyle.getPropertyValue('fill') == 'none' && cssTyle.getPropertyValue('stroke') == 'rgb(0, 0, 0)'){
                fillStyle = 'fill:none; stroke:rgb(0, 0, 0);';
            }
            target.style.cssText = fillStyle + cssStyle.cssText;
        }
    }
}

function flatten_svg_css(target) {
    for (var i = 0; i < target.childNodes.length; i++) {
        var child = target.childNodes[i];
        if (child.childNodes != null && child.childNodes.length > 0) {
            flatten_svg_css(child);
        }
        else{
            flatten_svg_element_css(child);
        }
    }
}

But it seems that it never gets into the condition cssStyle.getPropertyValue('fill') == 'none' && cssTyle.getPropertyValue('stroke') == 'rgb(0, 0, 0).

When the target is a path, the function getPropertyValue('fill') returns rgb(0, 0, 0) instead of none. But if I test directly the element with Firebug window.getComputedStyle(d3.select('.domain').node()).getPropertyValue('fill'), I got the value to none.

This is the svg graph that I am trying to convert to a png image. The graph has been generated using the library 'dc.js':

<svg width="1166" height="317">
    <g>
        <g class="grid-line horizontal" transform="translate(50,10)">
            <line x1="1" y1="265" x2="1066" y2="265" opacity="0" />
            <line x1="1" y1="239" x2="1066" y2="239" opacity="0" />
            <line x1="1" y1="212" x2="1066" y2="212" opacity="0" />
            <line x1="1" y1="186" x2="1066" y2="186" opacity="0" />
            <line x1="1" y1="159" x2="1066" y2="159" opacity="0" />
            <line x1="1" y1="133" x2="1066" y2="133" opacity="0" />
            <line x1="1" y1="106" x2="1066" y2="106" opacity="0" />
            <line x1="1" y1="80" x2="1066" y2="80" opacity="0" />
            <line x1="1" y1="53" x2="1066" y2="53" opacity="0" />
            <line x1="1" y1="27" x2="1066" y2="27" opacity="0" />
            <line x1="1" y1="0" x2="1066" y2="0" opacity="0" />
        </g>
        <g class="chart-body" transform="translate(50, 10)"
            clip-path="url(http://127.0.0.1:1234/index.jsp?gwt.codesvr=127.0.0.1:9997#analysis_charts_first_chart-clip)">
            <g class="stack _0">
                <rect class="bar" fill="#1f77b4" y="133" height="132" width="532"
                    x="1">
                    <title>ds1 - missing: 50%</title>
                </rect>
                <rect class="bar" fill="#1f77b4" y="133" height="132" width="532"
                    x="534">
                    <title>ds3 - missing: 50%</title>
                </rect>
            </g>
            <g class="stack _1">
                <rect class="bar" fill="#ffbb78" y="87" height="46" width="532"
                    x="1">
                    <title>ds1 - something else: 17%</title>
                </rect>
                <rect class="bar" fill="#ffbb78" y="133" height="0" width="532"
                    x="534">
                    <title>ds3 - something else: 0%</title>
                </rect>
            </g>
            <g class="stack _2">
                <rect class="bar" fill="#aec7e8" y="0" height="87" width="532"
                    x="1">
                    <title>ds1 - total: 33%</title>
                </rect>
                <rect class="bar" fill="#aec7e8" y="0" height="133" width="532"
                    x="534">
                    <title>ds3 - total: 50%</title>
                </rect>
            </g>
        </g>
        <g class="axis x" transform="translate(50,275)">
            <g class="tick" style="opacity: 1;" transform="translate(266.5,0)">
                <line y2="6" x2="0" />
                <text dy=".71em" style="text-anchor: middle;" y="9" x="0">ds1
                </text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(799.5,0)">
                <line y2="6" x2="0" />
                <text dy=".71em" style="text-anchor: middle;" y="9" x="0">ds3
                </text>
            </g>
            <path class="domain" d="M0,6V0H1066V6" />
        </g>
        <text class="x-axis-label" transform="translate(583,305)"
            text-anchor="middle">Datasets</text>
        <g class="axis y" transform="translate(50,10)">
            <g class="tick" style="opacity: 1;" transform="translate(0,265)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">0%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,239)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">10%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,212)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">20%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,186)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">30%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,159)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">40%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,133)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">50%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,106)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">60%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,80)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">70%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,53)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">80%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,27)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">90%</text>
            </g>
            <g class="tick" style="opacity: 1;" transform="translate(0,0)">
                <line x2="-6" y2="0" />
                <text dy=".32em" style="text-anchor: end;" x="-9" y="0">100%</text>
            </g>
            <path class="domain" d="M-6,0H0V265H-6" />
        </g>
        <text transform="translate(12,142.5),rotate(-90)" class="y-axis-label y-label"
            text-anchor="middle">Data Quality</text>
    </g>
    <defs>
        <clipPath id="analysis_charts_first_chart-clip">
            <rect width="1066" height="265" transform="translate(-0, -0)" />
        </clipPath>
    </defs>
</svg>

So I guess I am doing something wrong when trying to flatten the styles recursively.

Community
  • 1
  • 1
Antonia
  • 13
  • 3
  • You have do it inline for it to be visible by canvg. http://stackoverflow.com/questions/34121022/canvg-not-supporting-css There are many more examples online to help – thatOneGuy Nov 03 '16 at 11:38
  • Thats why I am using the two methods that I have posted, I was trying to add the the styles inline. – Antonia Nov 03 '16 at 11:45

0 Answers0