Solved

save Google Visualization chart as image

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Using Quotation Marks in PHP This question (http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28217211.html) seems to come up a lot for developers who are new to PHP.  And it got me thinking, "How can we explain the rule…
JavaScript can be used in a browser to change parts of a webpage dynamically. It begins with the following pattern: If condition W is true, do thing X to target Y after event Z. Below are some tips and tricks to help you get started with JavaScript …
This video teaches viewers how to create their own website using cPanel and Wordpress. Tutorial walks users through how to set up their own domain name from tools like Domain Registrar, Hosting Account, and Wordpress. More specifically, the order in…
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.

867 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

22 Experts available now in Live!

Get 1:1 Help Now