Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add static image charts #138

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Add static image charts #138

wants to merge 2 commits into from

Conversation

jdorn
Copy link
Owner

@jdorn jdorn commented Apr 23, 2014

Google Charts must be generated client side, which stops them from being embedded in e-maiils, pdfs, etc.

This pull request uses phantomjs and imagemagick to render the charts, take a screenshot, and return a PNG image on the server.

Done:

  • imagechart report format /report/imagechart/?report=...
  • attach/embed chart images in email

TODO:

  • detect if phantomjs is installed on the system and throw an error if it's not
  • create PDF format with embedded chart images
  • add download as option for image charts
  • update documentation

@PuffTealerS
Copy link

It's working perfectly, but for a geochart (with a specific region or not) the cities don't appear in the picture.
Example :
In Php-Reports : http://www.zupmage.eu/i/dbCzQCn9u5.png
In the mail-report : http://www.zupmage.eu/i/FXVBRADKrX.png

@l00p0
Copy link

l00p0 commented Apr 6, 2020

I found it easier to include an option to use google to render the chart, which will also work on GeoCharts.

specify CHART { type: ..., columns: ..., options: { png: true}, ... }

and modify templates/default/html/chart_report.twig as below, additional {% if chart.options['png'] ... statement right at the end of the file @line ~100

sorry ... indentation got a bit screwed up

chart_report.twig

  {% extends "html/chart_page.twig" %}
      {% block content %}
        {% for chart in Charts %}
          <div id='chart_div_{{chart.num}}' style='{% if chart.width %}width:{{chart.width}};{% endif %}{% if chart.height %}height:{{chart.height}};{% endif %}'></div>
        {% endfor %}

     <script type="text/javascript">
	function drawCharts() {
    {% for chart in Charts %}
      var data_{{chart.num}} = new google.visualization.DataTable();
      {% for key,value in chart.Rows[0].values %}
        {% if chart.roles[key] %}
         data_{{chart.num}}.addColumn({{chart.roles[key]|json_encode|raw}});
        {% else %}
          data_{{chart.num}}.addColumn("{{chart.datatypes[key]}}","{{chart.Rows[0].values[key].key}}");
        {% endif %}
      {% endfor %}
      var rows = [
        {% for row in chart.Rows %}[
          {% for value in row.values %}
            {%- if value.datatype == "date" or value.datatype == "datetime" -%}
              new Date("{{ value.getValue()|replace({'\\':'\\\\','"':'\\"' })|raw }}")
            {%- elseif value.datatype == "timeofday" -%}
              [{{ (value.getValue()|slice(0,2))*1 }}, {{ (value.getValue()|slice(3,2))*1 }}, {{ (value.getValue()|slice(6,2))*1 }}, 0]
              {%- elseif value.datatype == "null" -%}
		null
		{%- elseif value.datatype == "number" -%}
		{{ value.getValue() }}
		{%- else -%}
		"{{ value.getValue()|replace({'\\':'\\\\','"':'\\"' })|raw }}"
		{%- endif %}
		{%- if not loop.last %},{% endif -%}
        {% endfor %}
      ]{% if not loop.last %},{% endif %}
      {% endfor %}];

      data_{{chart.num}}.addRows(rows);
      // create columns array
            var columns_{{chart.num}} = [];
            var series_{{chart.num}} = {};
            for (var i = 0; i < data_{{chart.num}}.getNumberOfColumns(); i++) {
                columns_{{chart.num}}.push(i);
                if (i > 0) {
                    series_{{chart.num}}[i - 1] = {};
                }
            }

            var options_{{chart.num}} = {
				title: '{{chart.title}}',
				{% if chart.markers %}
					displayMode: 'markers',
					colorAxis: {colors: ['blue', 'red']},
					sizeAxis: {minValue: 1,  maxSize:  10},
				{% endif %}
				displayAnnotations: true,
                series: series_{{chart.num}},
				colors: [],
				wmode: 'transparent'
			};

        {% if chart.options %}
        {% for k,v in chart.options %}
            options_{{ chart.num}}["{{ k }}"] = {{ v|json_encode|raw }};
        {% endfor %}
        {% endif %}

	{% for color in chart.colors %}
		options_{{chart.num}}.colors.push('{{color}}');
	{% endfor %}

	if(!options_{{chart.num}}.colors.length) {
		delete options_{{chart.num}}.colors;
        }

        if(Array.isArray(options_{{ chart.num }}.series)) {
		var t = options_{{ chart.num }}.series;
		var n = {};
		for(var i=0;i<t.length;i++) {
	    n[i+''] = t[i];
	}
	options_{{ chart.num }}.series = n;
	}


        {% if chart.type == "Timeline" %}
            var chart_{{chart.num}} = new links.Timeline(document.getElementById('chart_div_{{chart.num}}'));
        {% elseif chart.type == "Bar" or chart.type == "Line" %}
          var chart_{{chart.num}} = new google.charts.{{chart.type}}(document.getElementById('chart_div_{{chart.num}}'));
          options_{{chart.num}} = google.charts.{{chart.type}}.convertOptions(options_{{chart.num}});
        {% else %}
          var chart_{{chart.num}} = new google.visualization.{{chart.type}}(document.getElementById('chart_div_{{chart.num}}'));
     {% endif %}
      {% if chart.options['as_png'] %}
	  // console.debug('rendering chart {{chart.num}} as png');
	  // Wait for the chart to finish drawing before calling the getImageURI() method.
          google.visualization.events.addListener(chart_{{chart.num}}, 'ready', function () {
	    chart_div_{{chart.num}}.innerHTML = '<img src="' + chart_{{chart.num}}.getImageURI() + '">';
            console.log(chart_div_{{chart.num}}.innerHTML);
          });
        {% endif %}
        chart_{{chart.num}}.draw(data_{{chart.num}}, options_{{chart.num}});
          {% endfor %}
	}

      google.charts.setOnLoadCallback(drawCharts);
  </script>
{% endblock %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants