我正在使用AMcharts绘制图表。我需要以pdf格式显示图表。所以,我已经将图形转换为png图像并以pdf格式显示。此过程在IE9以外的现代浏览器中成功运行。
我的问题仅在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 (tetra1337@gmail.com)
*
* 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 :(得分: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将无效。