У меня есть график SVG, который создается с использованием библиотеки d3 и стилизован с использованием css.Я хотел бы преобразовать этот график в PDF, сохраняя при этом его свойства CSS.
Я пробовал разные подходы, но ни один из них не захватил svg с его атрибутами стиля.В настоящее время я использую html2canvas и jsPDF для создания холста и сохранения его в формате PDF.Я включил код для минимального воспроизводимого примера стилизованного графа + код, который мне сейчас нужен для создания PDF.
<script src="https://d3js.org/d3.v5.js"></script>
<!-- jQuery CDN -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript">
</script>
<!-- html2canvas CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js" type="text/javascript">
<!-- jsPDF CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js"
integrity="sha384-NaWTHo/8YCBYJ59830LTz/P4aQZK1sS0SneOgAvhsIl3zBu8r9RevNg5lHCHAuQ/" crossorigin="anonymous">
</script>
<script>
function genPDF() {
// gets the quality based on the value that is input in the field
if (quality = document.getElementById("quality").value) {
// window.devicePixelRatio = 2;
html2canvas(document.getElementById("svg1"), {
// scale based on quality value input
scale: quality,
// logging for debugging
logging: true,
letterRendering: 1,
// allows for cross origin images
allowTaint: true,
useCORS: true
}).then(function (canvas) {
// creating a canvas with page data
var img = canvas.toDataURL('image/png');
// creating a portrait a4 page
var doc = new jsPDF('l', 'mm', 'a4');
// setting the width of the page to auto
const imgProps = doc.getImageProperties(img);
const pdfWidth = doc.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
// adding the image canvas to the pdf and saving
doc.addImage(img, 'PNG', 2, 2, pdfWidth, pdfHeight);
doc.save('generatedPDF.pdf');
});
} else {
// throw if no scale value is entered
throw "Please enter a scale value!";
}
}
</script>
<style>
rect {
fill: #868e96;
opacity: 0.3;
}
</style>
<body>
<form>
Enter scale quality:<br>
<input type="text" id="quality" name="quality" placeholder="1 - 5">
</form>
<button onclick="genPDF()">Generate PDF</button>
<svg id="svg1" width="1000" height="700">
<g id="elementsContainer">
<rect x="25" y="25" width="240" height="240" />
<rect x="275" y="25" width="240" height="240" />
<rect x="25" y="275" width="240" height="240" />
<rect x="275" y="275" width="240" height="240" />
</g>
</svg>
</body>
Я только что получил черный нестандартный график.
Редактировать: Я пытался добавить функцию тайм-аута, которая, похоже, все еще не решает проблему:
function genPDF() {
// gets the quality based on the value that is input in the field
if (quality = document.getElementById("quality").value) {
// window.devicePixelRatio = 2;
html2canvas(document.getElementById("apply"), {
// scale based on quality value input
scale: quality,
// logging for debugging
logging: true,
letterRendering: 1,
// allows for cross origin images
allowTaint: true,
useCORS: true
}).then(function (canvas) {
setTimeout(function () {
var img = canvas.toDataURL('image/png');
var doc = new jsPDF('l', 'mm', 'a4');
const imgProps = doc.getImageProperties(img);
const pdfWidth = doc.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
doc.addImage(img, 'PNG', 2, 2, pdfWidth, pdfHeight);
doc.save('generatedPDF.pdf');
}, 3000);
});
} else {
// throw if no scale value is entered
throw "Please enter a scale value!";
}
}
Редактировать: Лучшее решение, которое я нашел, - это просто добавить свойства стиля, встроенные в теги SVG.