D3.js导出SVG为图片:点击按钮无下载,求排查缺失项
解决D3.js折线图导出PNG无下载问题
看起来你遇到的问题大概率是几个关键环节没做到位,我帮你梳理下可能的遗漏点和修复方案:
1. 缺少核心辅助函数的实现
你代码里调用了getSVGString和svgString2Image这两个工具函数,但从你提供的代码里看不到它们的定义——这俩是示例实现导出功能的核心,必须把它们添加到你的代码中:
// 辅助函数:将SVG节点转为可序列化的字符串 function getSVGString(svgNode) { svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink'); var cssStyleText = getCSSStyles(svgNode); appendCSS(cssStyleText, svgNode); var serializer = new XMLSerializer(); var svgString = serializer.serializeToString(svgNode); svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); return svgString; function getCSSStyles(parentElement) { var selectorTextArr = []; selectorTextArr.push('#' + parentElement.id); for (var c = 0; c < parentElement.classList.length; c++) if (!contains('.' + parentElement.classList[c], selectorTextArr)) selectorTextArr.push('.' + parentElement.classList[c]); var nodes = parentElement.getElementsByTagName("*"); for (var i = 0; i < nodes.length; i++) { var id = nodes[i].id; if (!contains('#' + id, selectorTextArr)) selectorTextArr.push('#' + id); var classes = nodes[i].classList; for (var c = 0; c < classes.length; c++) if (!contains('.' + classes[c], selectorTextArr)) selectorTextArr.push('.' + classes[c]); } var extractedCSSText = ""; for (var i = 0; i < document.styleSheets.length; i++) { var s = document.styleSheets[i]; try { if (!s.cssRules) continue; } catch(e) { if (e.name !== 'SecurityError') throw e; continue; } var cssRules = s.cssRules; for (var r = 0; r < cssRules.length; r++) { if (contains(cssRules[r].selectorText, selectorTextArr)) extractedCSSText += cssRules[r].cssText; } } return extractedCSSText; function contains(str, arr) { return arr.indexOf(str) === -1 ? false : true; } } function appendCSS(cssText, element) { var styleElement = document.createElement("style"); styleElement.setAttribute("type", "text/css"); styleElement.innerHTML = cssText; var refNode = element.hasChildNodes() ? element.children[0] : null; element.insertBefore(styleElement, refNode); } } // 辅助函数:将SVG字符串转为图片Blob对象 function svgString2Image(svgString, width, height, format, callback) { var format = format ? format : 'png'; var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgString))); var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); canvas.width = width; canvas.height = height; var image = new Image(); image.onload = function() { context.clearRect(0, 0, width, height); context.drawImage(image, 0, 0, width, height); canvas.toBlob(function(blob) { var filesize = Math.round(blob.length/1024) + ' KB'; callback(blob, filesize); }, 'image/' + format); }; image.src = imgsrc; }
2. 修复save函数的语法问题
你在点击回调里定义save函数的方式有语法错误,应该改成正确的内联函数形式,修复后的点击事件代码如下:
d3.select('#saveButton').on('click', function(){ var svg = d3.select('svg'); // 确保这里正确获取到你的折线图SVG元素 var width = svg.attr('width'); var height = svg.attr('height'); var svgString = getSVGString(svg.node()); svgString2Image( svgString, 2*width, 2*height, 'png', function(dataBlob, filesize ){ saveAs( dataBlob, 'D3 vis exported to PNG.png' ); // 确保FileSaver.js已引入 }); });
3. 确认依赖库已正确引入
你需要确保FileSaver.js已经添加到项目中,可以通过脚本标签引入:
<script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js"></script>
4. 检查SVG元素的获取是否准确
如果页面上有多个SVG元素,不要用泛泛的d3.select('svg'),应该通过ID精准获取你的折线图SVG,比如d3.select('#your-linechart-svg')。
按照上面的步骤调整后,点击按钮应该就能正常下载导出的PNG图片了。
内容的提问来源于stack exchange,提问作者ShittyDeveloper
相关产品推荐
相关产品推荐

