feat: Adjust PDF export (margins, dynamic legend, scale bar)
Deploy Standortplaner / deploy (push) Successful in 17s
Details
Deploy Standortplaner / deploy (push) Successful in 17s
Details
This commit is contained in:
parent
6361f0a1ed
commit
cc1a6545a3
51
app.js
51
app.js
|
|
@ -2971,34 +2971,54 @@ async function resolveLayerConfig(isLocalFile, statusEl) {
|
||||||
exportOverlay.style.fontFamily = 'Arial, sans-serif';
|
exportOverlay.style.fontFamily = 'Arial, sans-serif';
|
||||||
exportOverlay.style.boxShadow = '0 0 10px rgba(0,0,0,0.3)';
|
exportOverlay.style.boxShadow = '0 0 10px rgba(0,0,0,0.3)';
|
||||||
|
|
||||||
const projName = document.getElementById('projectSelector')?.options[document.getElementById('projectSelector')?.selectedIndex]?.text || 'Unbekannt';
|
const projName = document.getElementById('projectSelector')?.options[document.getElementById('projectSelector')?.selectedIndex]?.text || '';
|
||||||
|
const projHtml = projName ? `<div style="font-size: 1rem; margin-bottom: 12px; font-weight: bold;">Projekt: ${projName}</div>` : `<div style="margin-bottom: 12px;"></div>`;
|
||||||
|
|
||||||
|
const showAux = document.getElementById('checkShowAux')?.checked;
|
||||||
|
const showProx = document.getElementById('checkShowProximity')?.checked;
|
||||||
|
|
||||||
exportOverlay.innerHTML = `
|
exportOverlay.innerHTML = `
|
||||||
<div style="font-weight: bold; font-size: 1.4rem; margin-bottom: 8px; color: #004a99;">ENWELO Standortplanung</div>
|
<div style="font-weight: bold; font-size: 1.4rem; margin-bottom: 8px; color: #004a99;">ENWELO Standortplanung</div>
|
||||||
<div style="font-size: 1rem; margin-bottom: 12px; font-weight: bold;">Projekt: ${projName}</div>
|
${projHtml}
|
||||||
<div style="display: flex; flex-direction: column; gap: 6px; font-size: 0.9rem;">
|
<div style="display: flex; flex-direction: column; gap: 6px; font-size: 0.9rem;">
|
||||||
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; background: #00c8ff; border: 1px dashed #00c8ff; opacity: 0.5;"></div> Rotorüberstreichfläche</div>
|
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; background: #00c8ff; border: 1px dashed #00c8ff; opacity: 0.5;"></div> Rotorüberstreichfläche</div>
|
||||||
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; background: #00aaff; border: 1px dashed #00aaff; opacity: 0.5;"></div> Gebietsumring</div>
|
${showAux ? `<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; background: #00aaff; border: 1px dashed #00aaff; opacity: 0.5;"></div> Gebietsumring</div>` : ''}
|
||||||
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 3px; background: #ff0000;"></div> Abstandslinien</div>
|
${showProx ? `<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 3px; background: #ff0000;"></div> Abstandslinien</div>` : ''}
|
||||||
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; border-radius: 50%; background: #00c8ff;"></div> WEA Standort</div>
|
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; border-radius: 50%; background: #00c8ff;"></div> WEA Standort</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
mapContainer.appendChild(exportOverlay);
|
mapContainer.appendChild(exportOverlay);
|
||||||
|
|
||||||
|
// Temporarily increase scale bar size
|
||||||
|
const scaleControl = document.querySelector('.leaflet-control-scale-line');
|
||||||
|
let oldScaleStyle = '';
|
||||||
|
if (scaleControl) {
|
||||||
|
oldScaleStyle = scaleControl.style.cssText;
|
||||||
|
scaleControl.style.transform = 'scale(1.5)';
|
||||||
|
scaleControl.style.transformOrigin = 'bottom left';
|
||||||
|
scaleControl.style.borderWidth = '2px';
|
||||||
|
scaleControl.style.fontSize = '14px';
|
||||||
|
}
|
||||||
|
|
||||||
// Wait a tiny bit for DOM to render overlay
|
// Wait a tiny bit for DOM to render overlay
|
||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
|
||||||
const canvas = await html2canvas(mapContainer, {
|
const canvas = await html2canvas(mapContainer, {
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
allowTaint: true,
|
allowTaint: true,
|
||||||
|
scale: 2, // better resolution
|
||||||
ignoreElements: (element) => {
|
ignoreElements: (element) => {
|
||||||
return element.classList.contains('leaflet-control-zoom');
|
return element.classList.contains('leaflet-control-zoom');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Restore scale bar
|
||||||
|
if (scaleControl) {
|
||||||
|
scaleControl.style.cssText = oldScaleStyle;
|
||||||
|
}
|
||||||
mapContainer.removeChild(exportOverlay);
|
mapContainer.removeChild(exportOverlay);
|
||||||
|
|
||||||
const imgData = canvas.toDataURL('image/png');
|
const imgData = canvas.toDataURL('image/jpeg', 0.9);
|
||||||
const pdf = new jspdf.jsPDF({
|
const pdf = new jspdf.jsPDF({
|
||||||
orientation: 'landscape',
|
orientation: 'landscape',
|
||||||
unit: 'mm',
|
unit: 'mm',
|
||||||
|
|
@ -3008,22 +3028,27 @@ async function resolveLayerConfig(isLocalFile, statusEl) {
|
||||||
const pdfWidth = pdf.internal.pageSize.getWidth();
|
const pdfWidth = pdf.internal.pageSize.getWidth();
|
||||||
const pdfHeight = pdf.internal.pageSize.getHeight();
|
const pdfHeight = pdf.internal.pageSize.getHeight();
|
||||||
|
|
||||||
|
// Set margins (20mm on each side)
|
||||||
|
const margin = 20;
|
||||||
|
const maxRenderWidth = pdfWidth - (margin * 2);
|
||||||
|
const maxRenderHeight = pdfHeight - (margin * 2);
|
||||||
|
|
||||||
const imgProps = pdf.getImageProperties(imgData);
|
const imgProps = pdf.getImageProperties(imgData);
|
||||||
const ratio = imgProps.width / imgProps.height;
|
const ratio = imgProps.width / imgProps.height;
|
||||||
|
|
||||||
let renderWidth = pdfWidth;
|
let renderWidth = maxRenderWidth;
|
||||||
let renderHeight = pdfWidth / ratio;
|
let renderHeight = maxRenderWidth / ratio;
|
||||||
|
|
||||||
if (renderHeight > pdfHeight) {
|
if (renderHeight > maxRenderHeight) {
|
||||||
renderHeight = pdfHeight;
|
renderHeight = maxRenderHeight;
|
||||||
renderWidth = pdfHeight * ratio;
|
renderWidth = maxRenderHeight * ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Center image in PDF
|
// Center image in PDF
|
||||||
const xOffset = (pdfWidth - renderWidth) / 2;
|
const xOffset = margin + (maxRenderWidth - renderWidth) / 2;
|
||||||
const yOffset = (pdfHeight - renderHeight) / 2;
|
const yOffset = margin + (maxRenderHeight - renderHeight) / 2;
|
||||||
|
|
||||||
pdf.addImage(imgData, 'PNG', xOffset, yOffset, renderWidth, renderHeight);
|
pdf.addImage(imgData, 'JPEG', xOffset, yOffset, renderWidth, renderHeight);
|
||||||
pdf.save('Karte_Enwelo.pdf');
|
pdf.save('Karte_Enwelo.pdf');
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue