feat: Add PDF export with legend and logo, update WEA icon
Deploy Standortplaner / deploy (push) Successful in 31s
Details
Deploy Standortplaner / deploy (push) Successful in 31s
Details
This commit is contained in:
parent
894144a2c0
commit
6361f0a1ed
100
app.js
100
app.js
|
|
@ -56,11 +56,13 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
state.map = L.map('map', {
|
||||
center: [51.5, 7.5], // Center NRW roughly
|
||||
zoom: 13,
|
||||
zoomControl: false
|
||||
zoomControl: false,
|
||||
preferCanvas: true
|
||||
});
|
||||
|
||||
// Add Zoom Control to the right
|
||||
L.control.zoom({ position: 'topright' }).addTo(state.map);
|
||||
L.control.zoom({ position: 'bottomright' }).addTo(state.map);
|
||||
L.control.scale({ imperial: false, position: 'bottomleft' }).addTo(state.map);
|
||||
|
||||
const updateZoomClass = () => {
|
||||
const zoom = state.map.getZoom();
|
||||
|
|
@ -2939,3 +2941,97 @@ async function resolveLayerConfig(isLocalFile, statusEl) {
|
|||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
// --- PDF Export Logic ---
|
||||
const btnExportPDF = document.getElementById('btnExportPDF');
|
||||
if (btnExportPDF) {
|
||||
btnExportPDF.addEventListener('click', async () => {
|
||||
const originalText = btnExportPDF.innerText;
|
||||
btnExportPDF.innerText = 'Exportiere...';
|
||||
btnExportPDF.disabled = true;
|
||||
|
||||
try {
|
||||
if (typeof html2canvas === 'undefined' || typeof jspdf === 'undefined') {
|
||||
throw new Error('PDF Bibliotheken (html2canvas, jspdf) sind noch nicht geladen.');
|
||||
}
|
||||
|
||||
const mapContainer = document.getElementById('map');
|
||||
|
||||
// Add Overlay
|
||||
const exportOverlay = document.createElement('div');
|
||||
exportOverlay.style.position = 'absolute';
|
||||
exportOverlay.style.bottom = '30px';
|
||||
exportOverlay.style.left = '30px';
|
||||
exportOverlay.style.zIndex = '9999';
|
||||
exportOverlay.style.background = 'rgba(255, 255, 255, 0.95)';
|
||||
exportOverlay.style.padding = '15px';
|
||||
exportOverlay.style.border = '2px solid #333';
|
||||
exportOverlay.style.borderRadius = '5px';
|
||||
exportOverlay.style.color = '#333';
|
||||
exportOverlay.style.fontFamily = 'Arial, sans-serif';
|
||||
exportOverlay.style.boxShadow = '0 0 10px rgba(0,0,0,0.3)';
|
||||
|
||||
const projName = document.getElementById('projectSelector')?.options[document.getElementById('projectSelector')?.selectedIndex]?.text || 'Unbekannt';
|
||||
|
||||
exportOverlay.innerHTML = `
|
||||
<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>
|
||||
<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: #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>
|
||||
<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>
|
||||
`;
|
||||
mapContainer.appendChild(exportOverlay);
|
||||
|
||||
// Wait a tiny bit for DOM to render overlay
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
|
||||
const canvas = await html2canvas(mapContainer, {
|
||||
useCORS: true,
|
||||
allowTaint: true,
|
||||
ignoreElements: (element) => {
|
||||
return element.classList.contains('leaflet-control-zoom');
|
||||
}
|
||||
});
|
||||
|
||||
mapContainer.removeChild(exportOverlay);
|
||||
|
||||
const imgData = canvas.toDataURL('image/png');
|
||||
const pdf = new jspdf.jsPDF({
|
||||
orientation: 'landscape',
|
||||
unit: 'mm',
|
||||
format: 'a3'
|
||||
});
|
||||
|
||||
const pdfWidth = pdf.internal.pageSize.getWidth();
|
||||
const pdfHeight = pdf.internal.pageSize.getHeight();
|
||||
|
||||
const imgProps = pdf.getImageProperties(imgData);
|
||||
const ratio = imgProps.width / imgProps.height;
|
||||
|
||||
let renderWidth = pdfWidth;
|
||||
let renderHeight = pdfWidth / ratio;
|
||||
|
||||
if (renderHeight > pdfHeight) {
|
||||
renderHeight = pdfHeight;
|
||||
renderWidth = pdfHeight * ratio;
|
||||
}
|
||||
|
||||
// Center image in PDF
|
||||
const xOffset = (pdfWidth - renderWidth) / 2;
|
||||
const yOffset = (pdfHeight - renderHeight) / 2;
|
||||
|
||||
pdf.addImage(imgData, 'PNG', xOffset, yOffset, renderWidth, renderHeight);
|
||||
pdf.save('Karte_Enwelo.pdf');
|
||||
|
||||
} catch (err) {
|
||||
console.error('Fehler beim PDF Export:', err);
|
||||
alert('Fehler beim PDF Export: ' + err.message);
|
||||
} finally {
|
||||
btnExportPDF.innerText = originalText;
|
||||
btnExportPDF.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
15
index.html
15
index.html
|
|
@ -62,7 +62,16 @@
|
|||
|
||||
<details class="section wea-accordion">
|
||||
<summary style="font-weight: bold; font-size: 1.1rem; color: var(--primary-color); display: flex; align-items: center; gap: 8px; cursor: pointer;">
|
||||
<span>🌀</span> WEA Konfiguration <span style="margin-left: auto;">+</span>
|
||||
<span style="display: inline-block; width: 24px; height: 24px; vertical-align: middle;">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="width: 100%; height: 100%;">
|
||||
<path d="M11.5 22L12.5 22L12.2 12L11.8 12L11.5 22Z" fill="var(--primary-color)" />
|
||||
<circle cx="12" cy="12" r="1.5" fill="var(--primary-color)" stroke="white" stroke-width="0.5"/>
|
||||
<path d="M12 12L12 3" stroke="white" stroke-width="1.8" stroke-linecap="round" />
|
||||
<path d="M12 12L19.7942 16.5" stroke="white" stroke-width="1.8" stroke-linecap="round" />
|
||||
<path d="M12 12L4.20577 16.5" stroke="white" stroke-width="1.8" stroke-linecap="round" />
|
||||
</svg>
|
||||
</span>
|
||||
WEA Konfiguration <span style="margin-left: auto;">+</span>
|
||||
</summary>
|
||||
<div style="margin-top: 12px; cursor: default;">
|
||||
<div style="display: flex; gap: 8px; margin-bottom: 6px;">
|
||||
|
|
@ -129,6 +138,8 @@
|
|||
style="flex: 0.4; padding: 6px; margin-top: 0;">📏</button>
|
||||
<button class="btn-secondary btn-mini" id="btnMeasureArea" title="Fläche messen"
|
||||
style="flex: 0.4; padding: 6px; margin-top: 0;">📐</button>
|
||||
<button class="btn-primary btn-mini" id="btnExportPDF" title="Karte als PDF exportieren"
|
||||
style="flex: 1; padding: 6px; margin-top: 4px; min-width: 100%;">📄 Karte PDF</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -288,6 +299,8 @@
|
|||
<script src="libs/shp.min.js"></script>
|
||||
<script src="libs/leaflet.js"></script>
|
||||
<script src="libs/turf.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue