Svelte中D3可视化图表图片下载失败,求排查解决方案
解决Svelte中D3图表无法下载的问题
问题根源
- 序列化的是包含SVG的
<div id="chart">而非SVG本身,导致生成的Blob不是有效SVG内容 - Canvas未设置与SVG匹配的宽高,绘制时丢失尺寸信息
canvas.toBlob()默认生成PNG格式,但指定保存为JPG,格式不匹配引发下载异常
修改后的代码
App.svelte
<script> import Chart from "./Chart.svelte"; import saveAs from "./FileSaver.min.js"; function downloadChart() { // 选中SVG元素而非外层div const svg = document.querySelector("#chart svg"); const svgString = new XMLSerializer().serializeToString(svg); const canvas = document.createElement("canvas"); // 设置canvas宽高与SVG一致 canvas.width = svg.getAttribute("width"); canvas.height = svg.getAttribute("height"); const ctx = canvas.getContext("2d"); const data = new Blob([svgString], {type: "image/svg+xml"}); const url = URL.createObjectURL(data); const img = new Image(); // 跨域兼容处理(测试用例无需,但保留更稳妥) img.crossOrigin = "anonymous"; img.onload = () => { ctx.drawImage(img, 0, 0); // 指定生成JPG格式,第二个参数为质量(0-1) canvas.toBlob((blob) => { saveAs(blob, "chart.jpg"); // 释放URL对象,避免内存泄漏 URL.revokeObjectURL(url); }, "image/jpeg", 0.9); }; img.src = url; } </script> <Chart/> <button on:click={downloadChart}>Download Image</button>
Chart.svelte(无需修改,确保SVG宽高属性正确即可)
<script> import { onMount } from "svelte"; import * as d3 from "d3"; let data = [10, 20, 30, 40, 50]; onMount(() => { const svg = d3 .select("#chart") .append("svg") .attr("width", 500) .attr("height", 500); svg .selectAll("rect") .data(data) .enter() .append("rect") .attr("x", (d, i) => i * 50) .attr("y", (d, i) => 500 - d) .attr("width", 50) .attr("height", (d) => d) .attr("fill", "teal"); }); </script> <div id="chart" />
关键修改说明
- 目标元素修正:改为选中SVG元素,确保序列化内容为纯SVG格式
- 尺寸同步:让Canvas宽高与SVG一致,保证绘制的图表尺寸准确
- 格式匹配:明确指定
canvas.toBlob()生成JPG格式,与保存文件名对应 - 内存清理:下载完成后释放URL对象,避免内存泄漏
内容的提问来源于stack exchange,提问作者sprucegoose
相关产品推荐
相关产品推荐

