New: Vergunningcheck online

This commit is contained in:
2026-02-16 10:37:39 +01:00
parent 75f8e29973
commit ab2b980d97
18 changed files with 405 additions and 82 deletions

View File

@@ -0,0 +1,14 @@
{{ define "main" }}
<section class="section">
<div class="container">
<div class="row">
<div class="p-4 p-sm-5 shadow rounded content">
<h1>{{ .Title }} </h1>
<p>{{ .Content }}</p>
</div>
</div>
</div>
</section>
{{ end }}

View File

@@ -0,0 +1,12 @@
{{ define "main" }}
<main id="content" role="main">
<section class="section">
<div class="container">
<h1>{{ .Title }} </h1>
<p>{{ .Content }}</p>
</div>
</section>
</main>
{{ end }}

View File

@@ -23,6 +23,10 @@
},
"address": {
"@type": "PostalAddress",
"streetAddress": "Valkhof 122",
"postalCode": "3772EG",
"addressLocality": "Barneveld",
"addressRegion": "Gelderland",
"addressCountry": "NL"
},
"contactPoint": [

View File

@@ -19,3 +19,24 @@
}
</script>
{{- end }}
{{- with .Params.application }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
{{- range . }}
"name": {{ .name | jsonify }},
"operatingSystem": {{ .operatingSystem | jsonify }},
"applicationCategory": {{ .applicationCategory | jsonify }},
"description": {{ .description | jsonify }},
"offers": {
"@type": "Offer",
"price": {{ .offers.price | jsonify }},
"priceCurrency": {{ .offers.priceCurrency | jsonify }}
},
"featureList": {{ .featureList | jsonify }}
{{- end }}
}
</script>
{{- end }}

View File

@@ -1,4 +1,5 @@
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.4.0/model-viewer.min.js"></script>
<!-- <script type="module" src="/js/model-viewer.min.js"></script> -->
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script>
<style>
.model-container {
@@ -18,7 +19,6 @@
--poster-color: transparent;
}
/* De poster/lader wordt door model-viewer zelf verborgen na laden */
#lazy-load-poster {
display: flex;
justify-content: center;
@@ -30,12 +30,12 @@
#ar-button {
background-color: #ffffff;
border-radius: 30px; /* Iets ronder voor moderne look */
border-radius: 30px;
border: 1px solid #007bff;
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%); /* Netjes in het midden onderaan */
transform: translateX(-50%);
padding: 12px 24px;
font-family: system-ui, -apple-system, sans-serif;
font-size: 15px;
@@ -56,8 +56,6 @@
transform: translateX(-50%) scale(0.95);
}
/* Verbergt de knop op desktop (omdat AR daar niet kan) */
/* Maar we laten hem op mobiel altijd staan voor de test */
@media (pointer: fine) {
#ar-button {
display: none;
@@ -65,6 +63,8 @@
}
</style>
<!-- ios-src="/3d/{{ .Get "model" }}.usdz" -->
<div class="model-container">
<model-viewer
id="woning-viewer"
@@ -75,20 +75,18 @@
camera-controls
shadow-intensity="1"
auto-rotate
loading="lazy"
touch-action="pan-y"
reveal="auto"
scale="0.01 0.01 0.01"
camera-orbit="45deg 75deg auto">
<div slot="poster" id="lazy-load-poster">
<div class="text-center">
<div class="spinner-border text-primary" role="status"></div>
<p class="mt-2">Woning wordt op ware grootte geplaatst...</p>
</div>
</div>
<div slot="poster"
id="lazy-load-poster"
style="background-image: url('/images/favicon.png'); background-position:center; background-repeat:no-repeat;">
</div>
<button slot="ar-button" id="ar-button">
👋 BEKIJK IN UW TUIN
</button>
</model-viewer>
</div>
</model-viewer>
</div>

View File

@@ -0,0 +1,140 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.3.1/ol.css">
<style>
.bouwplanner-wrapper { height: 700px; }
@media (max-width: 768px) { .bouwplanner-wrapper { height: auto; min-height: 800px; } }
#map { background: #f8f9fa; cursor: crosshair; }
#sidebar::-webkit-scrollbar { width: 5px; }
#sidebar::-webkit-scrollbar-thumb { background: #dee2e6; border-radius: 10px; }
.u-label { font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: #6c757d; }
</style>
<div class="row g-0 shadow rounded border overflow-hidden bg-white bouwplanner-wrapper">
<div id="sidebar" class="col-md-4 col-lg-3 border-end d-flex flex-column h-100 bg-white p-3">
<div class="mb-3 border-bottom pb-2">
<h3 class="h5 mb-0 d-flex align-items-center"><span class="me-2">🏠</span> Bouwplanner</h3>
</div>
<div id="feature-details" class="flex-grow-1 overflow-auto">
<div class="alert alert-light border shadow-sm small italic">Zoom in en klik op een gebouw voor de kavelanalyse.</div>
</div>
<div id="actions" class="mt-3 pt-3 border-top" style="display:none;">
<a id="link-omgevingswet" class="btn btn-outline-primary btn-sm w-100 mb-2 shadow-sm fw-bold" target="_blank">Check Omgevingswet</a>
</div>
<div class="mt-3 p-2 bg-light rounded-3 border">
<span class="u-label d-block mb-2">Kaartlagen</span>
<div class="form-check form-switch small mb-1">
<input class="form-check-input" type="checkbox" id="toggle-panden" checked>
<label class="form-check-label" for="toggle-panden">Gebouwen & Percelen</label>
</div>
</div>
</div>
<div class="col-md-8 col-lg-9 h-100 position-relative">
<div id="map" class="w-100 h-100"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/ol@v10.3.1/dist/ol.js"></script>
<script>
const TILESERVER_URL = "https://maps.start-it.nl";
let selectedRef = null;
const pandStyle = new ol.style.Style({
fill: new ol.style.Fill({ color: 'rgba(33, 37, 41, 0.15)' }),
stroke: new ol.style.Stroke({ color: '#212529', width: 0.8 })
});
const perceelStyle = new ol.style.Style({
stroke: new ol.style.Stroke({ color: '#dc3545', width: 1.5, lineDash: [4, 4] })
});
const highlightPandStyle = new ol.style.Style({
fill: new ol.style.Fill({ color: 'rgba(13, 110, 253, 0.3)' }),
stroke: new ol.style.Stroke({ color: '#0d6efd', width: 3 })
});
const highlightPerceelStyle = new ol.style.Style({
stroke: new ol.style.Stroke({ color: '#dc3545', width: 4 }),
fill: new ol.style.Fill({ color: 'rgba(220, 53, 69, 0.05)' })
});
const perceelLayer = new ol.layer.VectorTile({
source: new ol.source.VectorTile({
format: new ol.format.MVT(),
url: TILESERVER_URL + '/public.brk_perceel_3857/{z}/{x}/{y}.pbf'
}),
style: f => (selectedRef && f.get('nationalcadastralreference') === selectedRef) ? highlightPerceelStyle : perceelStyle,
minZoom: 14
});
const pandLayer = new ol.layer.VectorTile({
source: new ol.source.VectorTile({
format: new ol.format.MVT(),
url: TILESERVER_URL + '/public.panden_gecalculeerd_final/{z}/{x}/{y}.pbf'
}),
style: f => (selectedRef && f.get('nationalcadastralreference') === selectedRef) ? highlightPandStyle : pandStyle,
minZoom: 15
});
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({ source: new ol.source.OSM() }),
perceelLayer,
pandLayer
],
view: new ol.View({
center: ol.proj.fromLonLat([5.594, 52.285]),
zoom: 17,
maxZoom: 20
})
});
map.on('singleclick', function(evt) {
const features = map.getFeaturesAtPixel(evt.pixel);
const detailsContainer = document.getElementById('feature-details');
const actionsContainer = document.getElementById('actions');
if (!features || features.length === 0) {
selectedRef = null;
pandLayer.changed(); perceelLayer.changed();
actionsContainer.style.display = 'none';
detailsContainer.innerHTML = '<div class="alert alert-light border small italic">Klik op een gebouw voor details.</div>';
return;
}
const p = features[0].getProperties();
if (p.nationalcadastralreference) {
selectedRef = p.nationalcadastralreference;
pandLayer.changed(); perceelLayer.changed();
const volledigNr = (p.huisnummer || '') + (p.huisletter || '') + (p.toevoeging || '');
const straatHuis = (p.openbare_ruimte_naam || '') + ' ' + volledigNr;
const pc = p.postcode || '';
const woonplaats = p.woonplaats_naam || '';
const percOpp = Math.round(p.perceel_oppervlakte || 0);
const bebouwd = Math.round(p.totaal_bebouwd_oppervlakte || 0);
const pct = percOpp > 0 ? Math.round((bebouwd / percOpp) * 100) : 0;
detailsContainer.innerHTML = '<div class="mb-3 mt-1 text-dark">' +
'<span class="u-label text-muted">Locatie</span>' +
'<h5 class="mb-0 fw-bold">' + straatHuis + '</h5>' +
'<div class="small text-muted">' + pc + ', ' + woonplaats + '</div></div>' +
'<div class="card bg-light border-0 mb-3 shadow-sm text-dark"><div class="card-body p-3">' +
'<div class="row g-0 text-center">' +
'<div class="col-6 border-end"><small class="u-label d-block mb-1">Bebouwd</small><span class="h5 fw-bold">' + bebouwd + ' m²</span></div>' +
'<div class="col-6"><small class="u-label d-block mb-1">Kavel</small><span class="h5 fw-bold">' + percOpp + ' m²</span></div>' +
'</div>' +
'<div class="text-center border-top mt-2 pt-2"><small class="u-label">Bezetting: ' + pct + '%</small></div>' +
'</div></div>';
actionsContainer.style.display = 'block';
const locStr = straatHuis + ', ' + pc + ' ' + woonplaats;
document.getElementById('link-omgevingswet').href = 'https://omgevingswet.overheid.nl/regels-op-de-kaart/documenten?locatie=' + encodeURIComponent(locStr);
}
});
document.getElementById('toggle-panden').onchange = function(e) {
pandLayer.setVisible(e.target.checked);
perceelLayer.setVisible(e.target.checked);
};
</script>