Solved

save Google Visualization chart as image

Posted on 2013-12-05
5
610 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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Foreword (May 2015) This web page has appeared at Google.  It's definitely worth considering! https://www.google.com/about/careers/students/guide-to-technical-development.html How to Know You are Making a Difference at EE In August, 2013, one …
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…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
Wufoo.com provides powerful tools for surveying targeted groups, and utilizing data from completed surveys to find trends, discover areas of demand or customer expectation, and make business decisions on products or services.

706 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now