2013-03-26 4 views
4

Это своего рода конкретная проблема, но я предполагаю, что она может оказаться полезной в какой-то момент для кого-то еще, если я смогу найти решение.highcharts и canvg scaling issue

Мне нужно преобразовать некоторые из моих графиков Highcharts в PNG в конец браузера. Идея заключается в том, что когда наши авторы создают график, он автоматически преобразуется в PNG и что PNG будет сохранен вместе с JS-кодом для данного графика. Затем мы можем использовать эту версию PNG в ситуациях, когда JS не является вариантом. У меня все работает через библиотеку canvg, и это прекрасно.

Ну, почти. Из-за всех экранов с высоким разрешением на дюйм мы хотим, чтобы 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> 

ответ

5

Звучит так, будто вы работаете над каким-то административным инструментом, поэтому изменение размера диаграммы может и не быть проблемой. Вероятно, вы должны использовать chart.setSize (ширина, высота) перед вызовом getSVG().

Если вы не можете пойти по этому маршруту, вы также можете редактировать текст SVG напрямую, но это не было бы лучшей практикой, на мой взгляд.

Похоже, что путь canvg работает, он принимает scaleWidth/scaleHeight и добавляет transform = "scale()" в svg на основе параметров, которые вы передаете, и существующей высоты/ширины svg. Проблема заключается в том, что он не изменяет существующую высоту/ширину 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 + ')" ' 
); 
+0

Скотт, это именно то, что я хотел сделать. Лучшее решение или нет, это работает. :) По какой-то причине я не думал о явной высоте/ширине объекта svg, вызывающего проблему. –

+0

И просто быть понятным. СПАСИБО! –

7

я улучшил Скотт 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

Как и сегодня (год 2016), я могу использовать холст, используя правильные размеры диаграммы, передавая параметры в функцию getSVG().

В качестве примера:

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