4

I'm using AMcharts to draw graphs. I need to display the graph in pdf. So, i have converted the graph to png image and displaying it in a pdf. This processes successfully works in modern browsers except IE9.

My problem is in IE9 only.

I have two svg tags in a div container. The second svg tag is parsed perfectly as I expected. But the first svg tag is displaying as an blank image.

I'm using canvg.js for the html canvas.

<script src="http://canvg.googlecode.com/svn/trunk/canvg.js" type="text/javascript"></script>
<script src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js" type="text/javascript"></script>
<script src="http://www.amcharts.com/lib/amcharts.js" type="text/javascript"></script>
<script type="text/javascript">
 var chart;
 var chartData = [];
 AmCharts.ready(function () {
 // generate some random data first
 generateChartData();
 // SERIAL CHART 
 chart = new AmCharts.AmSerialChart();
 chart.pathToImages = "http://amcharts.com/lib/samples/stock/images/";
 chart.zoomOutButton = {
 backgroundColor: '#000000',
 backgroundAlpha: 0.15
 };
 chart.dataProvider = chartData;
 chart.categoryField = "date";
 // listen for "dataUpdated" event (fired when chart is inited) and call zoomChart method when it happens
 chart.addListener("dataUpdated", zoomChart);
 // AXES
 // category 
 var categoryAxis = chart.categoryAxis;
 categoryAxis.parseDates = true; // as our data is date-based, we set parseDates to true
 categoryAxis.minPeriod = "DD"; // our data is daily, so we set minPeriod to DD
 categoryAxis.dashLength = 2;
 categoryAxis.gridAlpha = 0.15;
 categoryAxis.axisColor = "#DADADA";
 // first value axis (on the left)
 var valueAxis1 = new AmCharts.ValueAxis();
 valueAxis1.axisColor = "#FF6600";
 valueAxis1.axisThickness = 2;
 valueAxis1.gridAlpha = 0;
 chart.addValueAxis(valueAxis1);
 // second value axis (on the right) 
 var valueAxis2 = new AmCharts.ValueAxis();
 valueAxis2.position = "right"; // this line makes the axis to appear on the right
 valueAxis2.axisColor = "#FCD202";
 valueAxis2.gridAlpha = 0;
 valueAxis2.axisThickness = 2;
 chart.addValueAxis(valueAxis2);
 // third value axis (on the left, detached)
 valueAxis3 = new AmCharts.ValueAxis();
 valueAxis3.offset = 50; // this line makes the axis to appear detached from plot area
 valueAxis3.gridAlpha = 0;
 valueAxis3.axisColor = "#B0DE09";
 valueAxis3.axisThickness = 2;
 chart.addValueAxis(valueAxis3);
 // GRAPHS
 // first graph
 var graph1 = new AmCharts.AmGraph();
 graph1.valueAxis = valueAxis1; // we have to indicate which value axis should be used
 graph1.title = "red line";
 graph1.valueField = "visits";
 graph1.bullet = "round";
 graph1.hideBulletsCount = 30;
 chart.addGraph(graph1);
 // second graph 
 var graph2 = new AmCharts.AmGraph();
 graph2.valueAxis = valueAxis2; // we have to indicate which value axis should be used
 graph2.title = "yellow line";
 graph2.valueField = "hits";
 graph2.bullet = "square";
 graph2.hideBulletsCount = 30;
 chart.addGraph(graph2);
 // third graph
 var graph3 = new AmCharts.AmGraph();
 graph3.valueAxis = valueAxis3; // we have to indicate which value axis should be used
 graph3.valueField = "views";
 graph3.title = "green line";
 graph3.bullet = "triangleUp";
 graph3.hideBulletsCount = 30;
 chart.addGraph(graph3);
 // CURSOR
 var chartCursor = new AmCharts.ChartCursor();
 chartCursor.cursorPosition = "mouse";
 chart.addChartCursor(chartCursor);
 // SCROLLBAR
 var chartScrollbar = new AmCharts.ChartScrollbar();
 chart.addChartScrollbar(chartScrollbar);
 // LEGEND
 var legend = new AmCharts.AmLegend();
 legend.marginLeft = 110;
 chart.addLegend(legend);
 // WRITE
 chart.write("chartdiv");
 });
 // generate some random data, quite different range
 function generateChartData() {
 var firstDate = new Date();
 firstDate.setDate(firstDate.getDate() - 50);
 for (var i = 0; i < 50; i++) {
 var newDate = new Date(firstDate);
 newDate.setDate(newDate.getDate() + i);
 var visits = Math.round(Math.random() * 40) + 100;
 var hits = Math.round(Math.random() * 80) + 500;
 var views = Math.round(Math.random() * 6000);
 chartData.push({
 date: newDate,
 visits: visits,
 hits: hits,
 views: views
 });
 }
 }
 // this method is called when chart is first inited as we listen for "dataUpdated" event
 function zoomChart() {
 // different zoom methods can be used - zoomToIndexes, zoomToDates, zoomToCategoryValues
 chart.zoomToIndexes(10, 20);
 }
/*
 * Export.js - AmCharts to PNG
 * Benjamin Maertz ([email protected])
 *
 * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
 * canvg.js - http://code.google.com/p/canvg/
 * amcharts.js - http://www.amcharts.com/download
 */
// Lookup for required libs
if ( typeof(AmCharts) === 'undefined' || typeof(canvg) === 'undefined' || typeof(RGBColor) === 'undefined' ) {
 throw('Woup smth is wrong you might review that http://www.amcharts.com/forum/viewtopic.php?id=11001');
}
// Define custom util
AmCharts.getExport = function(anything) {
 /*
 ** PRIVATE FUNCTIONS
 */
 // Word around until somebody found out how to cover that
 function removeImages(svg) {
 var startStr = '<image';
 var stopStr = '</image>';
 var start = svg.indexOf(startStr);
 var stop = svg.indexOf(stopStr);
 var match = '';
 // Recursion
 if ( start != -1 && stop != -1 ) {
 svg = removeImages(svg.slice(0,start) + svg.slice(stop + stopStr.length,svg.length));
 }
 return svg;
 };
 // Senseless function to handle any input
 function gatherAnything(anything,inside) {
 switch(String(anything)) {
 case '[object String]':
 if ( document.getElementById(anything) ) {
 anything = inside?document.getElementById(anything):new Array(document.getElementById(anything));
 }
 break;
 case '[object Array]':
 for ( var i=0;i<anything.length;i++) {
 anything[i] = gatherAnything(anything[i],true);
 }
 break;
 case '[object XULElement]':
 anything = inside?anything:new Array(anything);
 break;
 case '[object HTMLDivElement]':
 anything = inside?anything:new Array(anything);
 break;
 default:
 anything = new Array();
 for ( var i=0;i<AmCharts.charts.length;i++) {
 anything.push(AmCharts.charts[i].div);
 }
 break;
 }
 return anything;
 }
 /*
 ** varibales VARIABLES!!!
 */
 var chartContainer = gatherAnything(anything);
 var chartImages = [];
 var canvgOptions = {
 ignoreAnimation : true,
 ignoreMouse : true,
 ignoreClear : true,
 ignoreDimensions: true,
 offsetX : 0,
 offsetY : 0
 };
 /*
 ** Loop, generate, offer
 */
 // Loop through given container
 for(var i1=0;i1<chartContainer.length;i1++) {
 var canvas = document.createElement('canvas');
 var context = canvas.getContext('2d');
 var svgs = chartContainer[i1].getElementsByTagName('svg');
 var image = new Image();
 var heightCounter = 0;
 // Set dimensions, background color to the canvas
 canvas.width = chartContainer[i1].offsetWidth;
 canvas.height = chartContainer[i1].offsetHeight;
 context.fillStyle = '#FFFFFF';
 context.fillRect(0,0,canvas.width,canvas.height);
 // Loop through all svgs within the container
 for(var i2=0;i2<svgs.length;i2++) {
 var wrapper = svgs[i2].parentNode;
 var clone = svgs[i2].cloneNode(true);
 var cloneDiv = document.createElement('div');
 var offsets = {
 x: wrapper.style.left.slice(0,-2) || 0,
 y: wrapper.style.top.slice(0,-2) || 0,
 height: wrapper.offsetHeight,
 width: wrapper.offsetWidth
 };
 // Remove the style and append the clone to the div to receive the full SVG data
 clone.setAttribute('style','');
 cloneDiv.appendChild(clone);
 innerHTML = removeImages(cloneDiv.innerHTML); // without imagery
 // Apply parent offset
 if ( offsets.y == 0 ) {
 offsets.y = heightCounter;
 heightCounter += offsets.height;
 }
 canvgOptions.offsetX = offsets.x;
 canvgOptions.offsetY = offsets.y;
 // Some magic beyond the scenes...
 canvg(canvas,innerHTML,canvgOptions);
 }
 //console.log(canvas);return false;
 // Get the final data URL and throw that image to the array
 image.src = canvas.toDataURL();
 chartImages.push(image);
 }
 // Return DAT IMAGESS!!!!
 return chartImages
}
// Function to show the export in the document
function exportThis(opt) {
 var items = AmCharts.getExport('chartdiv');
 document.getElementById('button').innerHTML = 'Update Export';
 document.getElementById('not_button').innerHTML = '';
 for ( index in items ) {
 document.getElementById('not_button').appendChild(items[index]); 
 }
}
</script>
<div id="chartdiv" style="width:100%; height:400px; margin-bottom:10px;"></div>
<button id="button" onclick="exportThis();">Export</button>
<div id="not_button"></div>

Please help me to resolve this. This is my first post. Thanks in advance.

asked Feb 28, 2013 at 6:43
3
  • Fiddle here jsfiddle.net/vinodkumar93/yJUTB Commented Feb 28, 2013 at 6:50
  • 1
    This can be some support issue. Check your features support here caniuse.com/#cats=SVG Commented Feb 28, 2013 at 7:13
  • 1
    @MJQ - Thanks for your link. I have learnt lot from that. Commented Feb 28, 2013 at 12:59

1 Answer 1

1

Update your removeimages function. It will work.

function removeImages(svg) {
 var startStr = '<image';
 var stopStr = '</image>';
 if(navigator.userAgent.toLowerCase().match('msie')) {
 var stopStr = 'gif" />';
 }
 var start = svg.indexOf(startStr);
 var stop = svg.indexOf(stopStr);
 var match = '';
 // Recursion
 if ( start != -1 && stop != -1 ) {
 svg = removeImages(svg.slice(0,start) + svg.slice(stop + stopStr.length,svg.length));
 }
 console.log(svg);
 return svg;
};

Amcharts create the closing tag itself in IE9. So this is the case. If image tag present inside the svg tag, todataURL won't work.

answered Feb 28, 2013 at 12:55
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.