2013-02-28 171 views
4

我正在使用AMcharts繪製圖形。我需要以pdf格式顯示圖表。所以,我已經將圖轉換爲PNG圖像並以pdf格式顯示。這個過程在IE9以外的現代瀏覽器中成功運行。HTML畫布圖像

我的問題僅限於IE9。

我在div容器中有兩個svg標籤。第二個svg標籤完全按照我的預期分析。 但第一個svg標籤顯示爲空白圖像。

我使用canvg.js作爲html畫布。

<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> 

請幫我解決這個問題。這是我的第一篇文章。提前致謝。

+0

這裏的小提琴http://jsfiddle.net/vinodkumar93/yJUTB/ – user2118463 2013-02-28 06:50:14

+0

任何人都可以提供幫助嗎? – user2118463 2013-02-28 07:01:56

+1

這可能是一些支持問題。請點擊http://caniuse.com/#cats=SVG – MJQ 2013-02-28 07:13:53

回答

1

更新您的removeimages函數。它會工作。

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在IE9中創建結束標記本身。所以情況就是如此。如果圖像標籤存在於svg標籤內,todataURL將不起作用。