Volle maan verdwijnt achter de Dom
Zie timelapse
Zeldzaam moment eindelijk vastgelegd: timelapse van de volle maan aan een (bijna) onbewolkte hemel die achter de Dom verdwijnt.
Op 30 januari 1953 ontwikkelde zich ten zuiden van IJsland een zware stormdepressie die boven Schotland extreem hoge windsnelheden veroorzaakte. De volgende dag nam het systeem een voor Nederland desastreuze koers aan: een stormveld van circa duizend kilometer lang dat zich precies over het water recht op onze kust richtte. Geanimeerde reconstructie van de stormvloed op basis van ERA5-data.

Nederland in volle glorie: een zonovergoten Nederland vastgelegd in een satellietmozaïek van 1 mei 2026. Vogelvlucht over de wijdse Wadden, slingerende Schelde, verdronken velden, spiegelende meren, bloeiende bloemen.
165.208 panden in de Utrechtse binnenstad gekleurd op basis van het geregistreerde bouwjaar. Data: Gemeente Utrecht (bomenbestand), Kadaster (basisregistratie grootschalige topografie) en TU Delft (BAG3D).
<div id="_wrapper" style="position:relative; width:100%; height:80vh; font-family:Arial, sans-serif;">
<div id="_map" style="width:100%; height:100%;">
Lengtegraad
<div id="_lonDigits" style="display:flex; gap:2px;">
(function() {
const imageUrl = 'https://www.vizualism.nl/wp-content/uploads/color_maps_view.png';
// From color_maps_view.pgw
const A = 0.25;
const D = 0.0;
const B = 0.0;
const E = -0.25;
const C = 140365.49601;
const F = 457192.46368;
const mapId = '_map';
const latDigitsId = '_latDigits';
const lonDigitsId = '_lonDigits';
// 4 editable decimals + 1 fixed wildcard digit
const COORD_TEMPLATE = '00.0000-';
proj4.defs('EPSG:28992',
'+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 ' +
'+k=0.9999079 +x_0=155000 +y_0=463000 ' +
'+ellps=bessel ' +
'+towgs84=565.2369,50.0087,465.658,' +
'-0.406857330322397,0.350732676542563,-1.8703473836068,4.0812 ' +
'+units=m +no_defs'
);
ol.proj.proj4.register(proj4);
const rd = ol.proj.get('EPSG:28992');
let bounds = null;
let imageLayer = null;
const maskSource = new ol.source.Vector();
const maskLayer = new ol.layer.Vector({
source: maskSource,
style: function(feature) {
const type = feature.get('type');
if (type === 'mask') {
return new ol.style.Style({
fill: new ol.style.Fill({ color: 'rgba(0,0,0,0.5)' })
});
}
if (type === 'outline') {
return new ol.style.Style({
stroke: new ol.style.Stroke({ color: '#ffffff', width: 2 })
});
}
return null;
}
});
const map = new ol.Map({
target: mapId,
layers: [maskLayer],
view: new ol.View({
projection: rd,
center: [0, 0],
zoom: 2
})
});
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
function buildBounds(imgWidth, imgHeight) {
const minX = C - (A / 2);
const maxY = F - (E / 2);
const maxX = minX + imgWidth * A;
const minY = maxY + imgHeight * E;
return [minX, minY, maxX, maxY];
}
function readDigits(containerId, template) {
const inputs = document.getElementById(containerId).querySelectorAll('input');
let strMin = '';
let strMax = '';
let idx = 0;
for (const char of template) {
if (char === '.') {
strMin += '.';
strMax += '.';
} else if (char === '-') {
strMin += '0';
strMax += '9';
} else {
const val = inputs[idx].value;
if (val === '') {
strMin += '0';
strMax += '9';
} else {
strMin += val;
strMax += val;
}
idx++;
}
}
return [parseFloat(strMin), parseFloat(strMax)];
}
function refreshMapSoon() {
setTimeout(() => {
map.updateSize();
map.render();
}, 50);
}
function applyRange() {
if (!bounds) return;
const [latMin, latMax] = readDigits(latDigitsId, COORD_TEMPLATE);
const [lonMin, lonMax] = readDigits(lonDigitsId, COORD_TEMPLATE);
const bl = proj4('EPSG:4326', 'EPSG:28992', [lonMin, latMin]);
const tr = proj4('EPSG:4326', 'EPSG:28992', [lonMax, latMax]);
let x1 = Math.min(bl[0], tr[0]);
let x2 = Math.max(bl[0], tr[0]);
let y1 = Math.min(bl[1], tr[1]);
let y2 = Math.max(bl[1], tr[1]);
x1 = clamp(x1, bounds[0], bounds[2]);
x2 = clamp(x2, bounds[0], bounds[2]);
y1 = clamp(y1, bounds[1], bounds[3]);
y2 = clamp(y2, bounds[1], bounds[3]);
const minSize = 0.25;
if ((x2 - x1) < minSize) {
const cx = (x1 + x2) / 2;
x1 = cx - minSize / 2;
x2 = cx + minSize / 2;
}
if ((y2 - y1) {
if (char === '.') {
const span = document.createElement('span');
span.textContent = '.';
span.style.display = 'inline-block';
span.style.width = '8px';
span.style.textAlign = 'center';
span.style.lineHeight = '32px';
container.appendChild(span);
} else if (char === '-') {
const span = document.createElement('span');
span.textContent = '-';
span.style.display = 'inline-block';
span.style.width = '12px';
span.style.textAlign = 'center';
span.style.lineHeight = '32px';
span.style.fontWeight = 'bold';
container.appendChild(span);
} else {
const inp = document.createElement('input');
inp.type = 'text';
inp.maxLength = 1;
inp.placeholder = '_';
inp.inputMode = 'numeric';
inp.autocomplete = 'off';
inp.autocorrect = 'off';
inp.autocapitalize = 'off';
inp.spellcheck = false;
inp.pattern = '[0-9]*';
inp.style.width = '22px';
inp.style.height = '32px';
inp.style.textAlign = 'center';
inp.style.padding = '4px';
inp.style.boxSizing = 'border-box';
inp.style.fontSize = '16px';
const triggerUpdate = () => {
inp.value = inp.value.replace(/[^0-9]/g, '');
window.requestAnimationFrame(() => {
applyRange();
map.updateSize();
map.render();
});
};
inp.addEventListener('input', triggerUpdate);
inp.addEventListener('keyup', triggerUpdate);
inp.addEventListener('change', triggerUpdate);
inp.addEventListener('blur', triggerUpdate);
container.appendChild(inp);
}
});
}
createDigits(latDigitsId, COORD_TEMPLATE);
createDigits(lonDigitsId, COORD_TEMPLATE);
const img = new Image();
img.onload = function() {
bounds = buildBounds(img.naturalWidth, img.naturalHeight);
imageLayer = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: imageUrl,
projection: rd,
imageExtent: bounds
})
});
map.getLayers().insertAt(0, imageLayer);
map.getView().fit(bounds, {
padding: [20, 20, 20, 20]
});
applyRange();
refreshMapSoon();
};
img.src = imageUrl;
window.addEventListener('resize', () => {
refreshMapSoon();
});
window.addEventListener('orientationchange', () => {
refreshMapSoon();
});
})();
<?php
return ob_get_clean();
}
add_shortcode('geoquest', 'vizualism_digit_range_mask_shortcode');