Я создал SVG динамически, экспортируя SVG графиков, которые были внутри iframes, а затем объединил их с несколькими base64 изображениями таблиц (также внутри iframes). Этот последний svg, после многократного тестирования, идеален, и так, как мне нужно. Я использую несколько элементов заголовка и размещаю их посередине, и добавляю это изображение через некоторое пространство под заголовком. Наконец, я размещаю свои графики под этими двумя элементами. Когда я отрисовываю их на онлайн-просмотрщике svg , это выглядит так:
Что я хочу
Это то, чего я хочу. Я получил этот svg-код, когда регистрировал его в консоли перед отправкой в функцию svg2pdf.
Что я получаю
Теперь странно то, что когда я экспортирую PDF-файл, в нем отсутствуют некоторые вещи, например: заголовок находится справа или далеко слева, когда я дал ему значение x ($(document).width())/2
, поэтому оно находится посередине. Почему это случилось? Вывод svg, который я вижу в средствах просмотра svg, сильно отличается от pdf, который я получаю. Куда я иду не так?
Пожалуйста, попросите дополнительную информацию, я думаю, что делаю что-то глупое. Или может быть, что экспортированный pdf не поддерживает позиционирование по x и y?
Код
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title></title>
<script data-require="jquery" data-semver="3.1.1"
src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-3d.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/offline-exporting.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.3/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/canvg/1.5/canvg.js"
integrity="sha256-gS9x7L+zPeuIJQi5Ozx6nkmnAKegHZGdx/Zy/jOs/Ao=" crossorigin="anonymous"></script>
</head>
<body>
<header class="header" id="canvas_div_pdf">
<div class="header-toolbar">
<form role="form" method="get" action="" style="width: 100%">
<div class="row">
<div style="padding-left: 2%; padding-top: 0.5%; padding-bottom: 0.5%; width: 98%; border-bottom: 1px solid #cccccc">
<div style="width:30%; float: left; font-size: 2.2rem; ">Test Board ( Global
)
</div>
<div style="width:45%; float: left">
<div style="float:left;border:solid 1pt black;">
<button id="export-pdf" onclick="return false">Export to PDF</button>
<input id="btn-Preview-Image" type="button" value="Preview"/>
<a id="btn-Convert-Html2Image" href="#">Download</a>
<br/>
<h3>Preview :</h3>
<div id="previewImage">
</div>
</div>
<a id="pdf-download">Creating PDF...</a>
<div style="float: right">
<label>Date Range</label>
<input type="text" class="form-control datepicker hasDatepicker" name="boardStartDate"
id="inputstartdate" placeholder="Start Date" value="20-12-2020">
<input type="text" class="form-control datepicker hasDatepicker" name="boardEndDate"
id="inputenddate" placeholder="End Date" value="20-12-2020">
<button type="submit" class="btn btn--small btn--icon btn--success"><span
class="icon icon-check"></span></button>
</div>
</div>
<div style="width:25%; float: right">
<div style="width:15%; min-width:32px; float: right">
<a class="btn btn--small btn--icon btn--primary" onclick="return showAddAnotherPopup(this);"
title="Dashboard Settings" target="popup" href="/admin/pivot_table/genericboard/1/">
<span class="icon-cog"></span>
</a>
</div>
<div style="width:15%; min-width:32px; float: right">
<a class="btn btn--small btn--icon btn--primary" onclick="updateBoardDefault()"
title="Set this dashboard as default" target="_blank">
<span class="icon-check-square-o"></span>
</a>
</div>
<div style="width:15%; min-width:32px; float: right">
<a class="btn btn--small btn--icon btn--primary" id="editBoard" title="Edit Panels on Board"
target="_blank">
<span class="icon-pencil"></span>
</a>
</div>
<div style="width:15%; min-width:32px; float: right">
<a class="btn btn--small btn--icon btn--primary" onclick="exportBoard()"
title="Export board to Excel">
<span class="icon-file-excel-o"></span>
</a>
</div>
<!-- <div style="width:15%; min-width:32px; float: right">-->
<!-- <button class="btn btn--small btn--icon btn--primary" id="export-pdf" onclick="return false" title="Export board to PDF">-->
<!-- <span class="icon-file-pdf-o"></span>-->
<!-- </button>-->
<!-- </div>-->
<div style="width:15%; min-width:32px; float: right;border: 1px solid black">
<button class="btn btn--small btn--icon btn--primary" id="export-div" onclick="return false"
title="Export board to PDF">
<span class="icon-file-pdf-o">download divs</span>
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</header>
<div>
<span>
<h4 id="graph1title">Graph one title</h4>
<iframe id="ifrm1" src="chart.html" width="250" height="250"></iframe>
</span>
<span>
<h4 id="graph2title">Graph two title</h4>
<iframe id="ifrm2" src="chart2.html" width="250" height="250"></iframe>
</span>
<span>
<h4>Table two title</h4>
<iframe id="ifrm3" src="table.html" width="500" height="300"></iframe>
</span>
</div>
<div id="buttonrow">
<button id="set-charts">Set Charts</button>
<button id="export-png">Export to PNG</button>
<button id="export-pdf">Export to PDF</button>
<button class="btn" id="export">Save</button>
</div>
<script src="https://rawgit.com/yWorks/jsPDF/master/dist/jspdf.debug.js"></script>
<script src="https://rawgit.com/yWorks/svg2pdf.js/master/dist/svg2pdf.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="html2canvas.js"></script>
<script src="https://files.codepedia.info/files/uploads/iScripts/html2canvas.js"></script>
<script>
$(window).load(function () {
// var element = $("#ifrm3"); // global variable
var iframe = document.getElementById('ifrm3');
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
var element = innerDoc.getElementById("example")
var getCanvas; // global variable
var imageData;
// $("#btn-Preview-Image").on('click', function () {
html2canvas(element, {
onrendered: function (canvas) {
$("#previewImage").append(canvas);
getCanvas = canvas;
imageData = getCanvas.toDataURL("image/png");
// console.log("html div", imageData);
// Now browser starts downloading it instead of just showing it
var newData = imageData.replace(/^data:image\/png/, "data:application/octet-stream");
$("#btn-Convert-Html2Image").attr("download", "your_pic_name.png").attr("href", newData);
}
});
// console.log("html div", imageData);
// });
// $("#btn-Convert-Html2Image").on('click', function () {
// var imageData = getCanvas.toDataURL("image/png");
// console.log("html div", imageData);
// // Now browser starts downloading it instead of just showing it
// var newData = imageData.replace(/^data:image\/png/, "data:application/octet-stream");
// $("#btn-Convert-Html2Image").attr("download", "your_pic_name.png").attr("href", newData);
// });
var ifrmChart = undefined;
var chartArray = [];
Highcharts.getSVG = function (charts) {
var svgArr = [],
top = 0,
line = false,
count = 0,
width = 0;
graphCount = charts.length;
// console.log(graphCount);
Highcharts.each(charts, function (chartArray, tableObject) {
console.log("@137", tableObject);
chart = chartArray.chart;
var tableSVG;
var xpos = chartArray.xPos;
var ypos = chartArray.yPos;
//console.log('typeof' + typeof(xpos));
//console.log(xpos,ypos);
var svg = chart.getSVG(),
// Get width/height of SVG for export
svgWidth = +svg.match(
/^<svg[^>]*\swidth\s*=\s*\"?(\d+)\"?[^>]*>/
)[1],
svgHeight = +svg.match(
/^<svg[^>]*height\s*=\s*\"?(\d+)\"?[^>]*>/
)[1];
svg = svg.replace('<svg', '<g><path style="padding: 20px"></path></g><g style="padding: 20px" transform="translate(' + ypos + ',' + xpos + ')" ');
svg = svg.replace('</svg>', '</g>');
var iframe = document.getElementById('ifrm3');
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
var innerTable = innerDoc.getElementById("example")
// var iframe = innerTable; // or some other selector to get the iframe
var temp = $('#tableContainer', innerTable);
// html2canvas(tableObject).then(canvas => {
// tableSVG = canvas;
// console.log(tableSVG);
// });
console.log($(document).width()/2);
svg = svg + '<text x="' + ($(document).width())/2 + ' " text-anchor="middle" class="highcharts-title" style="color:#333333;font-size:24px;font-family:Arial;fill:#333333;;border:0px none rgb(51, 51, 51);border-block-end:0px none rgb(51, 51, 51);border-block-end-color:rgb(51, 51, 51);border-block-start:0px none rgb(51, 51, 51);border-block-start-color:rgb(51, 51, 51);border-bottom:0px none rgb(51, 51, 51);border-bottom-color:rgb(51, 51, 51);border-color:rgb(51, 51, 51);border-inline-end:0px none rgb(51, 51, 51);border-inline-end-color:rgb(51, 51, 51);border-inline-start:0px none rgb(51, 51, 51);border-inline-start-color:rgb(51, 51, 51);border-left:0px none rgb(51, 51, 51);border-left-color:rgb(51, 51, 51);border-right:0px none rgb(51, 51, 51);border-right-color:rgb(51, 51, 51);border-top:0px none rgb(51, 51, 51);border-top-color:rgb(51, 51, 51);caret-color:rgb(51, 51, 51);color:rgb(51, 51, 51);column-rule:0px none rgb(51, 51, 51);column-rule-color:rgb(51, 51, 51);font-family:Arial;outline:rgb(51, 51, 51) none 0px;outline-color:rgb(51, 51, 51);text-decoration:none solid rgb(51, 51, 51);text-decoration-color:rgb(51, 51, 51);webkit-border-after:0px none rgb(51, 51, 51);webkit-border-after-color:rgb(51, 51, 51);webkit-border-before:0px none rgb(51, 51, 51);webkit-border-before-color:rgb(51, 51, 51);webkit-border-end:0px none rgb(51, 51, 51);webkit-border-end-color:rgb(51, 51, 51);webkit-border-start:0px none rgb(51, 51, 51);webkit-border-start-color:rgb(51, 51, 51);webkit-column-rule:0px none rgb(51, 51, 51);webkit-column-rule-color:rgb(51, 51, 51);webkit-perspective-origin:113px 0px;webkit-text-emphasis-color:rgb(51, 51, 51);webkit-text-fill-color:rgb(51, 51, 51);webkit-text-stroke-color:rgb(51, 51, 51);" y="19" fill="rgb(51, 51, 51)"><tspan>Board Title Report</tspan></text>' + tableSVG;
//replace 'Column charts' with chart title element text
// console.log("@202", imageData);
svgArr.push(svg);
});
return "<svg height='" + $(document).height() + "' width='" + $(document).width() + "' version='1.1' xmlns='http://www.w3.org/2000/svg'>" +
svgArr.join('') + '<image width="500" height="300" xlink:href="' + imageData + '">' +'</svg>';
};
Highcharts.exportCharts = function (charts, options) {
//Highcharts.setOptions({ });
// Merge the options
options = Highcharts.merge(Highcharts.getOptions().exporting, options);
svgContent = Highcharts.getSVG(charts);
console.log(svgContent);
// console.log($(svgContent));
var svgString = svgContent;
var htmlObject = document.createElement('div');
htmlObject.setAttribute("id", "svgexport");
htmlObject.innerHTML = svgString;
console.log(htmlObject);
var svg = htmlObject.querySelector('svg'),
pdf = new jsPDF('p', 'pt', [$(document).height(), $(document).width()]);
console.log("@232",svg);
setTimeout(function () {
svg2pdf(svg, pdf, {
scale: 72 / 96, // this is the ratio of px to pt units
});
var data = pdf.output('datauristring');
var dl = document.getElementById('pdf-download');
dl.innerHTML = 'Download PDF';
dl.href = data;
dl.download = 'mychart.pdf';
}, 1000);
};
$('#export-png').click(function () {
Highcharts.exportCharts(chartArray);
});
$('#export-pdf').click(function () {
chartArray = [];
tableArray = [];
$("iframe").each(function (index) {
console.log(index + ": " + $(this).attr('id'));
var iFrameId = "#" + $(this).attr('id');
if ($(iFrameId)[0].contentWindow.getChart()) {
var chartObj = $(iFrameId)[0].contentWindow.getChart();
var xPosition = $(iFrameId).parent().offset().top; // added some arbitrary padding
var yPosition = $(iFrameId).parent().offset().left;
//$("div #ifrm1div > iframe").offset()
//var xPosition = $("#ifrm"+index+"div > iframe").offset().top;
//var yPosition = $("#ifrm"+index+"div > iframe").offset().left;
console.log("x " + xPosition + "y " + yPosition);
//console.log(xPosition + "ypos "+ yPosition);
var divChartObj = {
xPos: xPosition,
yPos: yPosition,
chart: chartObj
};
console.log(divChartObj, "@328");
chartArray.push(divChartObj);
} else {
var tableObj = $('#tableContainer', $(iFrameId).contents()).html();
var xPosition = $(iFrameId).parent().offset().top; // added some arbitrary padding
var yPosition = $(iFrameId).parent().offset().left;
console.log("x " + xPosition + "y " + yPosition);
var divTableObj = {
xPos: xPosition,
yPos: yPosition,
chart: tableObj
};
tableArray.push(divTableObj);
var tableObject = $(divTableObj.chart);
console.log($(divTableObj.chart), "@272");
}
});
Highcharts.exportCharts(chartArray, {
type: 'application/pdf'
});
});
});
;
</script>
<!-- <script src="https://code.jquery.com/jquery-1.12.4.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.3/jspdf.min.js"></script> -->
</body>
</html>
Я запустил svg-код в этой программе просмотра svg * , и я получить правильный вывод. Это означает, что мой код верен, но PDF-файл чего-то не хватает.
Кто-нибудь есть идеи? Этот вопрос слишком широкий? или это нормальное поведение svg2pdf, и я должен искать другую библиотеку для экспорта?
Вот вывод svg, который я получаю из console.log