Kompas dat naar je cursor wijst Nieuw
Een kompas waarvan de naald met een veerkrachtige zwaai naar je cursor wijst, waar die ook op de pagina staat (op een telefoon naar je vinger). Wijs je een verhuurpunt aan, geef je het focus of tik je erop, dan draait de naald naar de echte richting vanaf het station en staat de afstand eronder. Voor de contact- of routepagina van een fietsverhuur, watersportschool, outdoorwinkel of bedrijf met meerdere vestigingen.
Fietsverhuur rond Zwolle
Gemeten vanaf station Zwolle.
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- Kompas dat naar je cursor wijst · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="kmp">
<svg class="kmp__roos" viewBox="0 0 120 120" aria-hidden="true">
<circle cx="60" cy="60" r="57" fill="#fff" stroke="#0a0a0a" stroke-width="2"/>
<g class="kmp__streepjes" stroke="#8a857e" stroke-width="1.2"></g>
<text x="60" y="22" text-anchor="middle" class="kmp__wind kmp__wind--n">N</text>
<text x="101" y="65" text-anchor="middle" class="kmp__wind">O</text>
<text x="60" y="108" text-anchor="middle" class="kmp__wind">Z</text>
<text x="19" y="65" text-anchor="middle" class="kmp__wind">W</text>
<g class="kmp__naald"><path d="M60 24 L66 60 L54 60 Z" fill="#F5480F"/><path d="M60 96 L66 60 L54 60 Z" fill="#0a0a0a"/><circle cx="60" cy="60" r="4.5" fill="#fff" stroke="#0a0a0a" stroke-width="2"/></g>
</svg>
<div class="kmp__info">
<p class="kmp__kop">Fietsverhuur rond Zwolle</p>
<div class="kmp__lijst">
<button type="button" class="kmp__punt" data-graden="356" data-tekst="Meppel ligt 22 km naar het noorden.">Meppel <span>22 km</span></button>
<button type="button" class="kmp__punt" data-graden="282" data-tekst="Kampen ligt 14 km naar het westen.">Kampen <span>14 km</span></button>
<button type="button" class="kmp__punt" data-graden="186" data-tekst="Deventer ligt 32 km naar het zuiden.">Deventer <span>32 km</span></button>
</div>
<p class="kmp__stand" aria-live="polite">Gemeten vanaf station Zwolle.</p>
</div>
</div>
</div>/* Kompas dat naar je cursor wijst · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.kmp{width:100%;height:100%;display:flex;align-items:center;justify-content:center;gap:20px;padding:14px 18px;box-sizing:border-box;background:#f4f3f1;font-family:Switzer,sans-serif;touch-action:pan-y}
.kmp__roos{flex:0 0 auto;width:min(42%,170px);height:auto;filter:drop-shadow(0 6px 14px rgba(10,10,10,.1))}
.kmp__wind{font-size:14px;font-weight:600;fill:#0a0a0a;font-family:Switzer,sans-serif}
.kmp__wind--n{fill:#F5480F}
.kmp__info{flex:1 1 auto;min-width:0;max-width:200px}
.kmp__kop{margin:0 0 8px;font-size:16px;font-weight:600;color:#0a0a0a;line-height:1.2}
.kmp__lijst{display:flex;flex-direction:column;gap:4px}
.kmp__punt{font:inherit;font-size:14px;font-weight:500;display:flex;justify-content:space-between;align-items:center;min-height:30px;padding:0 10px;border:1px solid #d6d3ce;border-radius:4px;background:#fff;color:#0a0a0a;cursor:pointer;text-align:left;transition:border-color .15s,background-color .15s}
.kmp__punt span{font-size:13px;color:#55524d;font-weight:400}
.kmp__punt:hover,.kmp__punt.is-actief{border-color:#0a0a0a}
.kmp__punt.is-actief{background:#0a0a0a;color:#fff}
.kmp__punt.is-actief span{color:#d6d3ce}
.kmp__punt:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.kmp__stand{margin:8px 0 0;font-size:12px;line-height:1.35;color:#55524d}
@media (max-width:420px){.kmp{gap:12px;padding:10px 12px}.kmp__roos{width:40%}.kmp__kop{font-size:15px;margin-bottom:6px}.kmp__punt{min-height:28px;font-size:13px}}// Kompas dat naar je cursor wijst · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie
// root = het element waarin de HTML staat
function init(root){
const w = root.querySelector('.kmp'); if (!w) return;
const roos = w.querySelector('.kmp__roos'), naald = w.querySelector('.kmp__naald'), stand = w.querySelector('.kmp__stand');
const punten = [...w.querySelectorAll('.kmp__punt')], streep = w.querySelector('.kmp__streepjes');
const rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
for (let i = 0; i < 36; i++){
if (i % 9 === 0) continue;
const a = i * 10 * Math.PI / 180, r1 = i % 3 === 0 ? 46 : 49;
const l = document.createElementNS('http://www.w3.org/2000/svg', 'line');
l.setAttribute('x1', (60 + Math.sin(a) * r1).toFixed(2)); l.setAttribute('y1', (60 - Math.cos(a) * r1).toFixed(2));
l.setAttribute('x2', (60 + Math.sin(a) * 53).toFixed(2)); l.setAttribute('y2', (60 - Math.cos(a) * 53).toFixed(2));
streep.appendChild(l);
}
let a = 0, v = 0, doel = 0, vast = null, raf = 0, zichtbaar = true;
function tik(){
raf = 0; if (!zichtbaar) return;
const d = ((doel - a + 540) % 360) - 180;
if (rm) { a = doel; v = 0; } else { v += d * 0.07; v *= 0.8; a += v; }
naald.setAttribute('transform', 'rotate(' + a.toFixed(2) + ' 60 60)');
if (!rm && Math.abs(v) + Math.abs(d) > 0.05) raf = requestAnimationFrame(tik);
}
const start = () => { if (!raf) raf = requestAnimationFrame(tik); };
function richt(x, y){
if (vast) return;
const r = roos.getBoundingClientRect(); const cx = r.left + r.width / 2, cy = r.top + r.height / 2;
if (Math.hypot(x - cx, y - cy) < 8) return;
doel = Math.atan2(x - cx, -(y - cy)) * 180 / Math.PI; start();
}
document.addEventListener('pointermove', e => { if (zichtbaar && e.pointerType === 'mouse') richt(e.clientX, e.clientY); }, { passive: true });
w.addEventListener('pointerdown', e => { if (!e.target.closest('.kmp__punt')) { kies(null); richt(e.clientX, e.clientY); } });
function kies(p){
vast = p; punten.forEach(q => { q.classList.toggle('is-actief', q === p); q.setAttribute('aria-pressed', String(q === p)); });
if (p) { doel = +p.dataset.graden; stand.textContent = p.dataset.tekst; start(); }
else stand.textContent = 'Gemeten vanaf station Zwolle.';
}
punten.forEach(p => {
p.setAttribute('aria-pressed', 'false');
p.addEventListener('pointerenter', e => { if (e.pointerType === 'mouse') kies(p); });
p.addEventListener('focus', () => kies(p));
p.addEventListener('click', () => kies(p));
});
w.querySelector('.kmp__lijst').addEventListener('pointerleave', e => { if (e.pointerType === 'mouse' && !w.contains(document.activeElement)) kies(null); });
w.addEventListener('focusout', () => setTimeout(() => { if (!w.contains(document.activeElement)) kies(null); }, 0));
if ('IntersectionObserver' in window) new IntersectionObserver(es => { zichtbaar = es[0].isIntersecting; if (zichtbaar && !rm && !vast) { v = 9; start(); } }).observe(w);
tik();
}
init(document.querySelector('.jouw-container'));
Meer uit componenten
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →