将画布导出为SVG文件

3
我试图将一个包含使用Chart.js创建的图表的画布转换为SVG,以便能够从包含图表的页面下载SVG文件。我已经搜索了5个小时,尝试了多个脚本,最好的一个是这个,但问题是转换后的SVG仅包含图表的四分之一,我认为这与Chart.js的响应选项有关(应该为false才能转换为SVG)。
这是HTML文件。
<html>
<body>
<div class="chartContainer">
    <canvas id="radarCanvas" style="height: 600px;width: 600px;"></canvas>
</div>
<a id="down">
<button type="button" onclick="download()">Download</button>
</a>
</body>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
<script type="text/javascript" src="canvas2svg.js"></script>
<script type="text/javascript">
   var graphData = {
        type: 'pie',
        data: {
            labels: ["Africa", "Asia", "Europe", "Latin America", "North America"],
            datasets: [{
                label: "Population (millions)",
                backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
                data: [2478,5267,734,784,433]
            }]
        },
        options: {
            title: {
                display: true,
                text: 'Predicted world population (millions) in 2050'
            },
            animation: false,
            responsive:false,
            maintainAspectRatio: false
        }
    }


    function tweakLib(){
        C2S.prototype.getContext = function (contextId) {
            if (contextId=="2d" || contextId=="2D") {
                return this;
            }
            return null;
        }

        C2S.prototype.style = function () {
            return this.__canvas.style
        }

        C2S.prototype.getAttribute = function (name) {
            return this[name];
        }

        C2S.prototype.addEventListener =  function(type, listener, eventListenerOptions) {
            console.log("canvas2svg.addEventListener() not implemented.")
        }
    }


    var context = document.getElementById("radarCanvas").getContext("2d");

    var radarChart = new Chart(context, graphData); // Works fine

    tweakLib();
    // deactivate responsiveness and animation

    // canvas2svg 'mock' context
    var svgContext = C2S(600,600);

    // new chart on 'mock' context fails:
    var mySvg = new Chart(svgContext, graphData);
    console.log(svgContext.getSvg());
    function download() {
        var dl = document.createElement("a");
        document.body.appendChild(dl); // This line makes it work in Firefox.
        var svg= svgContext.getSvg();
        if (window.ActiveXObject) {
            svgString = svg.xml;
        } else {
            var oSerializer = new XMLSerializer();
            svgString = oSerializer.serializeToString(svg);
        }
        dl.download = "Chart.svg";
        //   return "data:image/svg+xml," + encodeURIComponent(svgAsXML);
        dl.href='data:image/svg+xml;utf8,' + encodeURIComponent(svgString);
        dl.click();
    }

</script>

</html>

我不熟悉canvas2svg,但似乎自定义的canvas实现与Chart.js不兼容。Chart.js将像素绘制到画布上,因此无法从中获取矢量图。像d3Vega-Lite这样的工具可能更适合您要尝试的内容。 - Jimmy Affatigato
@Jimmy,感谢你的建议,我终于搞定了。一杯咖啡总能让你头脑清醒。 - ciuz99best
你使用的canvas2svg版本是哪个? - user551113
1
@user551113 作者 Kerry Liu 的 v1.0.19 版本 - ciuz99best
感谢您分享您的解决方案!实际上,用户发布了一个PR来解决您这种问题,请参见: https://github.com/gliffy/canvas2svg/pull/46 以及他在 https://github.com/gliffy/canvas2svg/blob/eaab317a36a57421711a297d996bc80318185e44/test/playground_wrapped_Context2D.html#L85 的上下文示例 var c2s = new C2S({ctx:wrappedCtx, width:500, height:500}); - phm
1个回答

1
愚蠢的我......只需要添加的是...
mySvg.width=600;
mySvg.height=600; 
//or any size

这些行需要放在图表创建于C2S对象之后。
...
// deactivate responsiveness and animation

// canvas2svg 'mock' context
var svgContext = C2S(600,600);

// new chart on 'mock' context fails:

var mySvg = new Chart(svgContext, graphData);
//  insert here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接