写一个方法,实现vue导出d3+canvas绘制的图表为一张图片,改方法入参为 d3的dom的id和canvas的id
// 下载D3生成的SVG图表
function downloadD3Chart(svgSelector, fileName = 'd3-chart') {
// 获取SVG元素
const svg = document.querySelector(svgSelector);
// 克隆SVG以避免修改原始内容
const clone = svg.cloneNode(true);
// 处理样式(将外部样式转换为内联样式)
const style = document.createElementNS("http://www.w3.org/2000/svg", "style");
style.textContent = Array.from(document.styleSheets)
.filter(sheet => !sheet.href || sheet.href.startsWith(window.location.origin))
.map(sheet => Array.from(sheet.cssRules).map(rule => rule.cssText).join('\n'))
.join('\n');
clone.insertBefore(style, clone.firstChild);
// 将SVG转换为字符串
const svgData = new XMLSerializer().serializeToString(clone);
// 创建Blob对象
const blob = new Blob(['<?xml version="1.0" standalone="no"?>\r\n', svgData], {
type: 'image/svg+xml;charset=utf-8'
});
// 创建图片对象加载SVG
const img = new Image();
const url = URL.createObjectURL(blob);
img.onload = function() {
// 创建Canvas绘制图片
const canvas = document.createElement('canvas');
canvas.width = svg.clientWidth;
canvas.height = svg.clientHeight;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#ffffff'; // 设置白色背景
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
// 创建下载链接
const link = document.createElement('a');
link.download = `${fileName}.png`;
link.href = canvas.toDataURL('image/png');
link.click();
// 清理
URL.revokeObjectURL(url);
};
img.src = url;
}
// 下载Canvas图表
function downloadCanvasChart(canvasSelector, fileName = 'canvas-chart') {
const canvas = document.querySelector(canvasSelector);
// 创建临时链接
const link = document.createElement('a');
link.download = `${fileName}.png`;
// 对于已经绘制好的canvas,可以直接获取数据URL
link.href = canvas.toDataURL('image/png');
// 触发下载
link.click();
}
// 组合下载(如果页面同时有D3和Canvas图表)
function downloadCombinedChart(svgSelector, canvasSelector, fileName = 'combined-chart') {
const svg = document.querySelector(svgSelector);
const canvas = document.querySelector(canvasSelector);
// 创建新Canvas用于合并
const combinedCanvas = document.createElement('canvas');
combinedCanvas.width = Math.max(svg.clientWidth, canvas.width);
combinedCanvas.height = svg.clientHeight + canvas.height;
const ctx = combinedCanvas.getContext('2d');
// 绘制背景
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, combinedCanvas.width, combinedCanvas.height);
// 先处理SVG
const svgData = new XMLSerializer().serializeToString(svg);
const svgBlob = new Blob(['<?xml version="1.0" standalone="no"?>\r\n', svgData], {
type: 'image/svg+xml;charset=utf-8'
});
const svgUrl = URL.createObjectURL(svgBlob);
const img = new Image();
img.onload = function() {
// 绘制SVG内容
ctx.drawImage(img, 0, 0);
// 绘制Canvas内容
ctx.drawImage(canvas, 0, svg.clientHeight);
// 下载合并后的图片
const link = document.createElement('a');
link.download = `${fileName}.png`;
link.href = combinedCanvas.toDataURL('image/png');
link.click();
URL.revokeObjectURL(svgUrl);
};
img.src = svgUrl;
}