highcharts和canvg扩展问题

时间:2013-03-26 16:19:40

标签: highcharts scaling canvg

这是一个特定的问题,但我想如果我能找到解决方案,它可能会在某些方面对其他人有用。

我需要在浏览器端将一些Highcharts图转换为PNG。我们的想法是,当我们的作者创建图形时,它将自动转换为PNG,并且PNG将与给定图形的JS代码一起保存。然后我们可以在JS不可选的情况下提供PNG版本。我已经通过canvg库完成了所有工作并且它非常完美。

好吧,差不多。由于所有高dpi屏幕都在那里,我们希望PNG的放大倍数是通常显示的图形的两倍。因此,PNG版本可以在iPhone / iPad等上看起来很好......

canvg有一些缩放选项,所以我尝试使用它们。但那就是它开始崩溃的地方。图形是正确缩放的,但Highcharts对象中的某个框不会与其他所有内容一起缩放,结果缩放图只显示精美缩放图的左上角。

我查看了canvg代码并很快意识到我的JS能力不足以确定正在发生的事情,对于Highcharts结束也是如此。

如果有人有想法或知道一个简单的解决方案,我将非常感激。

要复制该问题,您可以查看我放在一起的这个JSFIDDLE示例:

http://jsfiddle.net/UVNvh/3/

这是代码,如果JSFIDDLE页面搞砸了或以某种方式消失。

<script src="http://code.highcharts.com/highcharts.js">http://code.highcharts.com/highcharts.js</script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js"></script> 
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/canvg.js"></script> 
<p>Highcharts</p>
<div id="container" style="height: 400px; margin-top: 1em"></div>
<p>Canvas</p>
<canvas id="canvas"></canvas>
<p>Image</p>
<div id="image"><div>

<script type="text/javascript">
$(function () {
    var chart = new Highcharts.Chart({

        chart: {
            renderTo: 'container'
        },

        credits: {
            enabled: false
        },

        xAxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },

        series: [{
            data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]        
        }],

        navigation: {
            buttonOptions: {
                enabled: false
            }
        },
        exporting: {
            type: 'image/jpeg'
        }

    });

    var chart_svg = chart.getSVG();                    
    var chart_canvas = document.getElementById('canvas');

    canvg(chart_canvas, chart_svg, {scaleWidth: 1280, scaleHeight: 860});

    var chart_img = chart_canvas.toDataURL('image/png');

    jQuery('#image').append('<img src="' + chart_img + '" />');
});
</script>

3 个答案:

答案 0 :(得分:7)

我在没有黑客的情况下改进了Scott Gearhart :) http://jsfiddle.net/marcalj/EsPud/7/

最重要的部分:

// Get chart aspect ratio
var c_ar = chart.chartHeight / chart.chartWidth;

// Set canvas size
chart_canvas.width = 1280;
chart_canvas.height = chart_canvas.width * c_ar;

canvg(chart_canvas, chart_svg, {
    ignoreDimensions: true,
    scaleWidth: chart_canvas.width,
    scaleHeight: chart_canvas.height
});

确保在图表元素上设置固定的宽度和高度。

答案 1 :(得分:5)

听起来您正在使用某种管理工具,因此更改图表的大小可能不是问题。在调用getSVG()之前,您应该使用chart.setSize(width,height)。

如果你不能走这条路,你也可以直接编辑SVG文本,但在我看来这不是最好的做法。

似乎canvg工作的方式是它需要scaleWidth / scaleHeight并根据您传递的选项和svg的现有高度/宽度向svg添加transform =“scale()”。问题是它不会改变svg和结果图像的现有高度/宽度。我把一个jsfiddle放在一起,做了我认为你想要的东西,但它可能不是最好的解决方案。 http://jsfiddle.net/sgearhart2/EsPud/1/

var chart_svg = chart.getSVG();                    
chart_svg = chart_svg.replace('width="600"', 'width="1280"');   
chart_svg = chart_svg.replace('height="400"', 'height="860"'); 

// If i had to guess, canvg does the next part but not the prior part  
var dWidth = 1280/600, dHeight = 860/400;
chart_svg = chart_svg.replace(
    '<svg ', 
    '<svg transform="scale(' + dWidth + ' ' + dHeight + ')" '
); 

答案 2 :(得分:2)

就像今天(2016年)一样,我可以通过将参数传递到getSVG()函数来使画布使用正确的图表大小。

例如:

var chartSVG = chart.highcharts().getSVG({
        exporting: {
            sourceHeight: chart.highcharts().chartHeight,
            sourceWidth: chart.highcharts().chartWidth,
        }
    });