Cursorspoor dat tekent Nieuw
De cursor laat een dunne oranje lijn achter die als potloodstreep meetrekt en na ruim een seconde vervaagt; zonder muis tekent het vlak zelf rustig een lus. Canvas met afgevlakte beweging, stopt buiten beeld. Voor de hero van een ontwerpstudio, architect of illustrator. Bij minder beweging staat er één stilstaande lijn.
Elk interieur begint met een lijn op papier.
Studio Wiersma, interieurarchitectuur in Groningen
Bekijk ons werkZo 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.
<!-- Cursorspoor dat tekent · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="cst">
<canvas class="cst__c" aria-hidden="true"></canvas>
<div class="cst__txt"><h3 class="cst__h">Elk interieur begint met een lijn op papier.</h3><p class="cst__p">Studio Wiersma, interieurarchitectuur in Groningen</p><a class="cst__btn" href="#cursorspoor-tekent">Bekijk ons werk</a></div>
</div>
</div>/* Cursorspoor dat tekent · NedDev · eigen werk. */
.cst{position:absolute;inset:0;overflow:hidden;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;background:#f4f3f1;text-align:left;touch-action:pan-y}
.cst__c{position:absolute;inset:0;width:100%;height:100%;display:block}
.cst__txt{position:absolute;left:18px;right:18px;bottom:16px;pointer-events:none}
.cst__h{margin:0;max-width:16em;font-size:clamp(18px,5.4cqi,26px);line-height:1.08;font-weight:700;letter-spacing:-.025em}
.cst{container-type:inline-size}
.cst__p{margin:6px 0 0;font-size:12.5px;color:#4a4a4a}
.cst__btn{pointer-events:auto;display:inline-flex;align-items:center;min-height:34px;margin-top:10px;padding:0 13px;background:#0a0a0a;color:#fff;border-radius:4px;font-size:12.5px;font-weight:600;text-decoration:none;transition:background-color .15s,color .15s}
.cst__btn:hover{background:#F5480F;color:#0a0a0a}
.cst__btn:focus-visible{outline:2px solid #F5480F;outline-offset:2px}// Cursorspoor dat tekent · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w = root.querySelector('.cst'), c = w.querySelector('.cst__c'), ctx = c.getContext('2d');
var rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
var W = 0, H = 0, dpr = 1, pts = [], LIFE = 1300, tx = 0, ty = 0, x = 0, y = 0, auto = true, idleT = 0, raf = 0, vis = true, t0 = performance.now();
w.querySelector('.cst__btn').addEventListener('click', function (e) { e.preventDefault(); });
function size() {
dpr = Math.min(2, window.devicePixelRatio || 1); W = w.clientWidth; H = w.clientHeight;
c.width = W * dpr; c.height = H * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
if (rm) still();
}
function lus(t) { return [W * .62 + W * .26 * Math.sin(t / 1500), H * .36 + H * .2 * Math.sin(t / 950) * Math.cos(t / 2600)]; }
function still() {
ctx.clearRect(0, 0, W, H); ctx.strokeStyle = '#F5480F'; ctx.lineWidth = 1.8; ctx.lineCap = 'round'; ctx.beginPath();
for (var t = 0; t < 5200; t += 40) { var p = lus(t); if (t) ctx.lineTo(p[0], p[1]); else ctx.moveTo(p[0], p[1]); }
ctx.stroke();
}
function draw(now) {
raf = 0;
if (auto) { var p = lus(now - t0); tx = p[0]; ty = p[1]; }
var nx = x + (tx - x) * .2, ny = y + (ty - y) * .2;
if (Math.abs(nx - x) + Math.abs(ny - y) > .4 || !pts.length) pts.push({ x: nx, y: ny, t: now });
x = nx; y = ny;
while (pts.length && now - pts[0].t > LIFE) pts.shift();
ctx.clearRect(0, 0, W, H); ctx.lineCap = 'round'; ctx.lineJoin = 'round';
for (var i = 2; i < pts.length; i++) {
var a = pts[i - 2], b = pts[i - 1], q = pts[i], f = 1 - (now - q.t) / LIFE;
ctx.strokeStyle = 'rgba(245,72,15,' + f.toFixed(3) + ')'; ctx.lineWidth = .8 + 1.6 * f;
ctx.beginPath(); ctx.moveTo((a.x + b.x) / 2, (a.y + b.y) / 2); ctx.quadraticCurveTo(b.x, b.y, (b.x + q.x) / 2, (b.y + q.y) / 2); ctx.stroke();
}
if (vis && !document.hidden && (auto || pts.length > 1)) raf = requestAnimationFrame(draw);
}
function kick() { if (!raf && !rm) raf = requestAnimationFrame(draw); }
size();
if ('ResizeObserver' in window) new ResizeObserver(size).observe(w);
if (rm) return;
var p0 = lus(0); x = tx = p0[0]; y = ty = p0[1];
w.addEventListener('pointermove', function (e) {
var r = w.getBoundingClientRect(); tx = e.clientX - r.left; ty = e.clientY - r.top;
if (auto) { auto = false; x = tx; y = ty; pts = []; }
clearTimeout(idleT); idleT = setTimeout(function () { auto = true; t0 = performance.now() - 0; var p = lus(0); tx = p[0]; ty = p[1]; kick(); }, 3500);
kick();
});
if ('IntersectionObserver' in window) new IntersectionObserver(function (e) { vis = e[0].isIntersecting; if (vis) kick(); }).observe(w);
document.addEventListener('visibilitychange', kick);
kick();
}
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 →