Solved

save Google Visualization chart as image

Posted on 2013-12-05
5
636 Views
Last Modified: 2013-12-06
I am building an application that needs to capture Google Visualization Charts and save them as images to a server so they can be used in a report. I was able to find a solution at http://www.battlehorse.net/page/topics/charts/save_google_charts_as_image.html which uses javascript and canvas to extract image data. This solution worked fine on localhost but as soon as I put the page on the Web Server it comes up with an error "canvg is undefined". I have searched quite a bit and have not been able to find any resolutions to this error. I would prefer to do something server side if possible to capture the chart as an image but I have not seen any samples where this is possible. Can anyone recommend a solution to the "canvg" error I am receiving or offer a .Net solution to capturing the Visualization Charts?

javascript catch error
<%@ Page Language="VB" ContentType="text/html" ResponseEncoding="iso-8859-1" %>

<script runat="server">           
Sub Page_Load(Src As Object, E As EventArgs)
	Dim loggedIn As Integer=0	
	IF NOT IsPostBack THEN						
            If loggedIn = 1 Then
                                
                Try
                   
                Catch exc As Exception
                    lblError.Text = exc.ToString() & "<br />"				                
                   
                End Try
            Else
                lblError.Text = ""
            End If
        End If
	
    End Sub                                         
    
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test</title>
<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>
    <script type="text/javascript">
        function getImgData(chartContainer) {
            var chartArea = chartContainer.getElementsByTagName('svg')[0].parentNode;
            var svg = chartArea.innerHTML;
            var doc = chartContainer.ownerDocument;
            var canvas = doc.createElement('canvas');
            canvas.setAttribute('width', chartArea.offsetWidth);
            canvas.setAttribute('height', chartArea.offsetHeight);


            canvas.setAttribute(
            'style',
            'position: absolute; ' +
            'top: ' + (-chartArea.offsetHeight * 2) + 'px;' +
            'left: ' + (-chartArea.offsetWidth * 2) + 'px;');
            doc.body.appendChild(canvas);
            canvg(canvas, svg);
            var imgData = canvas.toDataURL("image/png");
            canvas.parentNode.removeChild(canvas);
            return imgData;
        }                               

        function alert10() {
            try {
                textbox1 = document.getElementById('textbox1');
                textbox1.innerHTML = getImgData(document.getElementById('chart1_div'));
            }
            catch (err) {
                alert(err.message);
            }            
        }                        
    </script>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
        google.load("visualization", "1", { packages: ["corechart", "treemap", "geochart"] });
        google.setOnLoadCallback(drawChart);
        function drawChart() {

            var data;
            var chart;


            document.getElementById('chart1_div').scrollIntoView();

            chartTitle = 'Regular & REO Average Sold Price';

            xColumn = 'Quarter';
            yColumn = 'Avg Sold Price';
            zColumn = 'Smoothed';
            yTitle = 'Price in Thousands';
            chart = new google.visualization.LineChart(document.getElementById('chart1_div'));
            legendType = 'none';

            data = new google.visualization.DataTable();

            data.addColumn('string', xColumn);
            data.addColumn('number', yColumn);
            data.addColumn('number', zColumn);

            data.addRows(35);

            data.setValue(0, 0, '2005-Q1');
            data.setValue(0, 1, 288 + 0);

            data.setValue(1, 0, '2005-Q2');
            data.setValue(1, 1, 285 + 0);

            data.setValue(2, 0, '2005-Q3');
            data.setValue(2, 1, 315 + 0);

            data.setValue(3, 0, '2005-Q4');
            data.setValue(3, 1, 318 + 0);

            data.setValue(4, 0, '2006-Q1');
            data.setValue(4, 1, 310 + 0);

            data.setValue(5, 0, '2006-Q2');
            data.setValue(5, 1, 286 + 0);

            data.setValue(6, 0, '2006-Q3');
            data.setValue(6, 1, 299 + 0);

            data.setValue(7, 0, '2006-Q4');
            data.setValue(7, 1, 278 + 0);

            data.setValue(8, 0, '2007-Q1');
            data.setValue(8, 1, 283 + 0);

            data.setValue(9, 0, '2007-Q2');
            data.setValue(9, 1, 278 + 0);

            data.setValue(10, 0, '2007-Q3');
            data.setValue(10, 1, 287 + 0);

            data.setValue(11, 0, '2007-Q4');
            data.setValue(11, 1, 260 + 0);

            data.setValue(12, 0, '2008-Q1');
            data.setValue(12, 1, 299 + 0);

            data.setValue(13, 0, '2008-Q2');
            data.setValue(13, 1, 273 + 0);

            data.setValue(14, 0, '2008-Q3');
            data.setValue(14, 1, 259 + 0);

            data.setValue(15, 0, '2008-Q4');
            data.setValue(15, 1, 231 + 0);

            data.setValue(16, 0, '2009-Q1');
            data.setValue(16, 1, 233 + 0);

            data.setValue(17, 0, '2009-Q2');
            data.setValue(17, 1, 244 + 0);

            data.setValue(18, 0, '2009-Q3');
            data.setValue(18, 1, 234 + 0);

            data.setValue(19, 0, '2009-Q4');
            data.setValue(19, 1, 219 + 0);

            data.setValue(20, 0, '2010-Q1');
            data.setValue(20, 1, 235 + 0);

            data.setValue(21, 0, '2010-Q2');
            data.setValue(21, 1, 236 + 0);

            data.setValue(22, 0, '2010-Q3');
            data.setValue(22, 1, 207 + 0);

            data.setValue(23, 0, '2010-Q4');
            data.setValue(23, 1, 210 + 0);

            data.setValue(24, 0, '2011-Q1');
            data.setValue(24, 1, 184 + 0);

            data.setValue(25, 0, '2011-Q2');
            data.setValue(25, 1, 188 + 0);

            data.setValue(26, 0, '2011-Q3');
            data.setValue(26, 1, 202 + 0);

            data.setValue(27, 0, '2011-Q4');
            data.setValue(27, 1, 186 + 0);

            data.setValue(28, 0, '2012-Q1');
            data.setValue(28, 1, 204 + 0);

            data.setValue(29, 0, '2012-Q2');
            data.setValue(29, 1, 237 + 0);

            data.setValue(30, 0, '2012-Q3');
            data.setValue(30, 1, 185 + 0);

            data.setValue(31, 0, '2012-Q4');
            data.setValue(31, 1, 195 + 0);

            data.setValue(32, 0, '2013-Q1');
            data.setValue(32, 1, 196 + 0);

            data.setValue(33, 0, '2013-Q2');
            data.setValue(33, 1, 225 + 0);

            data.setValue(34, 0, '2013-Q3');
            data.setValue(34, 1, 218 + 0);

            data.setValue(0, 2, 302 + 0);

            data.setValue(1, 2, 301 + 0);

            data.setValue(2, 2, 301 + 0);

            data.setValue(3, 2, 300 + 0);

            data.setValue(4, 2, 298 + 0);

            data.setValue(5, 2, 296 + 0);

            data.setValue(6, 2, 293 + 0);

            data.setValue(7, 2, 290 + 0);

            data.setValue(8, 2, 286 + 0);

            data.setValue(9, 2, 282 + 0);

            data.setValue(10, 2, 278 + 0);

            data.setValue(11, 2, 274 + 0);

            data.setValue(12, 2, 269 + 0);

            data.setValue(13, 2, 263 + 0);

            data.setValue(14, 2, 257 + 0);

            data.setValue(15, 2, 251 + 0);

            data.setValue(16, 2, 245 + 0);

            data.setValue(17, 2, 239 + 0);

            data.setValue(18, 2, 233 + 0);

            data.setValue(19, 2, 227 + 0);

            data.setValue(20, 2, 222 + 0);

            data.setValue(21, 2, 217 + 0);

            data.setValue(22, 2, 212 + 0);

            data.setValue(23, 2, 208 + 0);

            data.setValue(24, 2, 205 + 0);

            data.setValue(25, 2, 202 + 0);

            data.setValue(26, 2, 201 + 0);

            data.setValue(27, 2, 200 + 0);

            data.setValue(28, 2, 201 + 0);

            data.setValue(29, 2, 201 + 0);

            data.setValue(30, 2, 203 + 0);

            data.setValue(31, 2, 204 + 0);

            data.setValue(32, 2, 206 + 0);

            data.setValue(33, 2, 209 + 0);

            data.setValue(34, 2, 211 + 0);


            chart.draw(data,
                     { title: chartTitle
                     , vAxis: { title: yTitle }
                     , width: 300, height: 300
                     , hAxis: { slantedText: true, slantedTextAngle: 90, textStyle: { fontSize: 10} }
                     , curveType: 'function', lineWidth: 1, pointSize: 1, legend: 'none'
                     , legend: legendType

                     });                        
        }
    </script>
</head>
<body text="black" alink="blue" vlink="purple" link="blue" topmargin="0" leftmargin="0" MARGINWIDTH="0" MARGINHEIGHT="0">
<form runat="server" style="width:100%;" id="form1" name="form1" >
<div id="header" style="display:none;"><MenuDisplay:Menu id="menuDisplay01" runat="server" /></div>
<asp:Label ID="lblWelcome" runat="server" />
<br />
<asp:Label ID="lblError" runat="server" />
    <div id="chart1_div"></div>              
    <br />
    <textarea  id="textbox1" name="textbox1" rows="4" cols="50"></textarea>
    <br />    
    <button onclick="alert10();">Test</button>
    
	
</form>
</body>
</html>

Open in new window

0
Comment
Question by:cwarr
  • 3
  • 2
5 Comments
 
LVL 44

Expert Comment

by:Rainer Jeschor
ID: 39698855
Hi,
is your site running with SSL enabled?
Meaning you open your website with https ...
0
 

Author Comment

by:cwarr
ID: 39698914
Yes, our website is running with SSL enabled.
0
 
LVL 44

Accepted Solution

by:
Rainer Jeschor earned 500 total points
ID: 39699203
Hi,
then you might try to adjust your external script file references to either use also https OR the better way to use it protocol relative like this:
<%@ Page Language="VB" ContentType="text/html" ResponseEncoding="iso-8859-1" %>

<script runat="server">           
Sub Page_Load(Src As Object, E As EventArgs)
	Dim loggedIn As Integer=0	
	IF NOT IsPostBack THEN						
            If loggedIn = 1 Then
                                
                Try
                   
                Catch exc As Exception
                    lblError.Text = exc.ToString() & "<br />"				                
                   
                End Try
            Else
                lblError.Text = ""
            End If
        End If
	
    End Sub                                         
    
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test</title>
<script type="text/javascript" src="//canvg.googlecode.com/svn/trunk/rgbcolor.js"></script> 
    <script type="text/javascript" src="//canvg.googlecode.com/svn/trunk/canvg.js"></script>
    <script type="text/javascript">
        function getImgData(chartContainer) {
            var chartArea = chartContainer.getElementsByTagName('svg')[0].parentNode;
            var svg = chartArea.innerHTML;
            var doc = chartContainer.ownerDocument;
            var canvas = doc.createElement('canvas');
            canvas.setAttribute('width', chartArea.offsetWidth);
            canvas.setAttribute('height', chartArea.offsetHeight);


            canvas.setAttribute(
            'style',
            'position: absolute; ' +
            'top: ' + (-chartArea.offsetHeight * 2) + 'px;' +
            'left: ' + (-chartArea.offsetWidth * 2) + 'px;');
            doc.body.appendChild(canvas);
            canvg(canvas, svg);
            var imgData = canvas.toDataURL("image/png");
            canvas.parentNode.removeChild(canvas);
            return imgData;
        }                               

        function alert10() {
            try {
                textbox1 = document.getElementById('textbox1');
                textbox1.innerHTML = getImgData(document.getElementById('chart1_div'));
            }
            catch (err) {
                alert(err.message);
            }            
        }                        
    </script>
    <script type="text/javascript" src="//www.google.com/jsapi"></script>
    <script type="text/javascript">
        google.load("visualization", "1", { packages: ["corechart", "treemap", "geochart"] });
        google.setOnLoadCallback(drawChart);
        function drawChart() {

            var data;
            var chart;


            document.getElementById('chart1_div').scrollIntoView();

            chartTitle = 'Regular & REO Average Sold Price';

            xColumn = 'Quarter';
            yColumn = 'Avg Sold Price';
            zColumn = 'Smoothed';
            yTitle = 'Price in Thousands';
            chart = new google.visualization.LineChart(document.getElementById('chart1_div'));
            legendType = 'none';

            data = new google.visualization.DataTable();

            data.addColumn('string', xColumn);
            data.addColumn('number', yColumn);
            data.addColumn('number', zColumn);

            data.addRows(35);

            data.setValue(0, 0, '2005-Q1');
            data.setValue(0, 1, 288 + 0);

            data.setValue(1, 0, '2005-Q2');
            data.setValue(1, 1, 285 + 0);

            data.setValue(2, 0, '2005-Q3');
            data.setValue(2, 1, 315 + 0);

            data.setValue(3, 0, '2005-Q4');
            data.setValue(3, 1, 318 + 0);

            data.setValue(4, 0, '2006-Q1');
            data.setValue(4, 1, 310 + 0);

            data.setValue(5, 0, '2006-Q2');
            data.setValue(5, 1, 286 + 0);

            data.setValue(6, 0, '2006-Q3');
            data.setValue(6, 1, 299 + 0);

            data.setValue(7, 0, '2006-Q4');
            data.setValue(7, 1, 278 + 0);

            data.setValue(8, 0, '2007-Q1');
            data.setValue(8, 1, 283 + 0);

            data.setValue(9, 0, '2007-Q2');
            data.setValue(9, 1, 278 + 0);

            data.setValue(10, 0, '2007-Q3');
            data.setValue(10, 1, 287 + 0);

            data.setValue(11, 0, '2007-Q4');
            data.setValue(11, 1, 260 + 0);

            data.setValue(12, 0, '2008-Q1');
            data.setValue(12, 1, 299 + 0);

            data.setValue(13, 0, '2008-Q2');
            data.setValue(13, 1, 273 + 0);

            data.setValue(14, 0, '2008-Q3');
            data.setValue(14, 1, 259 + 0);

            data.setValue(15, 0, '2008-Q4');
            data.setValue(15, 1, 231 + 0);

            data.setValue(16, 0, '2009-Q1');
            data.setValue(16, 1, 233 + 0);

            data.setValue(17, 0, '2009-Q2');
            data.setValue(17, 1, 244 + 0);

            data.setValue(18, 0, '2009-Q3');
            data.setValue(18, 1, 234 + 0);

            data.setValue(19, 0, '2009-Q4');
            data.setValue(19, 1, 219 + 0);

            data.setValue(20, 0, '2010-Q1');
            data.setValue(20, 1, 235 + 0);

            data.setValue(21, 0, '2010-Q2');
            data.setValue(21, 1, 236 + 0);

            data.setValue(22, 0, '2010-Q3');
            data.setValue(22, 1, 207 + 0);

            data.setValue(23, 0, '2010-Q4');
            data.setValue(23, 1, 210 + 0);

            data.setValue(24, 0, '2011-Q1');
            data.setValue(24, 1, 184 + 0);

            data.setValue(25, 0, '2011-Q2');
            data.setValue(25, 1, 188 + 0);

            data.setValue(26, 0, '2011-Q3');
            data.setValue(26, 1, 202 + 0);

            data.setValue(27, 0, '2011-Q4');
            data.setValue(27, 1, 186 + 0);

            data.setValue(28, 0, '2012-Q1');
            data.setValue(28, 1, 204 + 0);

            data.setValue(29, 0, '2012-Q2');
            data.setValue(29, 1, 237 + 0);

            data.setValue(30, 0, '2012-Q3');
            data.setValue(30, 1, 185 + 0);

            data.setValue(31, 0, '2012-Q4');
            data.setValue(31, 1, 195 + 0);

            data.setValue(32, 0, '2013-Q1');
            data.setValue(32, 1, 196 + 0);

            data.setValue(33, 0, '2013-Q2');
            data.setValue(33, 1, 225 + 0);

            data.setValue(34, 0, '2013-Q3');
            data.setValue(34, 1, 218 + 0);

            data.setValue(0, 2, 302 + 0);

            data.setValue(1, 2, 301 + 0);

            data.setValue(2, 2, 301 + 0);

            data.setValue(3, 2, 300 + 0);

            data.setValue(4, 2, 298 + 0);

            data.setValue(5, 2, 296 + 0);

            data.setValue(6, 2, 293 + 0);

            data.setValue(7, 2, 290 + 0);

            data.setValue(8, 2, 286 + 0);

            data.setValue(9, 2, 282 + 0);

            data.setValue(10, 2, 278 + 0);

            data.setValue(11, 2, 274 + 0);

            data.setValue(12, 2, 269 + 0);

            data.setValue(13, 2, 263 + 0);

            data.setValue(14, 2, 257 + 0);

            data.setValue(15, 2, 251 + 0);

            data.setValue(16, 2, 245 + 0);

            data.setValue(17, 2, 239 + 0);

            data.setValue(18, 2, 233 + 0);

            data.setValue(19, 2, 227 + 0);

            data.setValue(20, 2, 222 + 0);

            data.setValue(21, 2, 217 + 0);

            data.setValue(22, 2, 212 + 0);

            data.setValue(23, 2, 208 + 0);

            data.setValue(24, 2, 205 + 0);

            data.setValue(25, 2, 202 + 0);

            data.setValue(26, 2, 201 + 0);

            data.setValue(27, 2, 200 + 0);

            data.setValue(28, 2, 201 + 0);

            data.setValue(29, 2, 201 + 0);

            data.setValue(30, 2, 203 + 0);

            data.setValue(31, 2, 204 + 0);

            data.setValue(32, 2, 206 + 0);

            data.setValue(33, 2, 209 + 0);

            data.setValue(34, 2, 211 + 0);


            chart.draw(data,
                     { title: chartTitle
                     , vAxis: { title: yTitle }
                     , width: 300, height: 300
                     , hAxis: { slantedText: true, slantedTextAngle: 90, textStyle: { fontSize: 10} }
                     , curveType: 'function', lineWidth: 1, pointSize: 1, legend: 'none'
                     , legend: legendType

                     });                        
        }
    </script>
</head>
<body text="black" alink="blue" vlink="purple" link="blue" topmargin="0" leftmargin="0" MARGINWIDTH="0" MARGINHEIGHT="0">
<form runat="server" style="width:100%;" id="form1" name="form1" >
<div id="header" style="display:none;"><MenuDisplay:Menu id="menuDisplay01" runat="server" /></div>
<asp:Label ID="lblWelcome" runat="server" />
<br />
<asp:Label ID="lblError" runat="server" />
    <div id="chart1_div"></div>              
    <br />
    <textarea  id="textbox1" name="textbox1" rows="4" cols="50"></textarea>
    <br />    
    <button onclick="alert10();">Test</button>
    
	
</form>
</body>
</html>

Open in new window


HTH
Rainer
0
 
LVL 44

Expert Comment

by:Rainer Jeschor
ID: 39699216
Additional info:
your chart worked as you referenced the script library using https - but not for the canvas stuff. This results in a mixed security context (both https and http resources) which could cause issues in the browsers.

Using the protocol relative path like "//..." would work then both in HTTP and HTTPS

HTH
Rainer
0
 

Author Closing Comment

by:cwarr
ID: 39700909
This worked like a charm. I can't believe it was something so simple. Thank you for all of your help.
0

Featured Post

MIM Survival Guide for Service Desk Managers

Major incidents can send mastered service desk processes into disorder. Systems and tools produce the data needed to resolve these incidents, but your challenge is getting that information to the right people fast. Check out the Survival Guide and begin bringing order to chaos.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

New Relic: Our company recently started researching several products to figure out what were the best ways for us to increase our web page speed and to quickly identify performance problems that we may be having. One of the products we evaluated wa…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Use Wufoo, an online form creation tool, to make powerful forms. Learn how to selectively show certain fields based on user input using rules to gather relevant information and data from your forms. The rules feature provides you with an opportunity…
Learn how to set-up PayPal payment integration in your Wufoo form. Allow your users to remit payment through PayPal upon completion of your online form. This is helpful for collecting membership payments, customer payments, donations, and more.

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question