Wijzigen voor document Tekenveld

Laatst gewijzigd door Jeeves de Butler op 23-10-2026 02:42

Van versie 9.1
gewijzigd door Jeeves de Butler
op 19-10-2026 01:24
Opmerking bij wijziging: Er is geen opmerking bij deze versie
Naar versie 5.1
gewijzigd door Jeeves de Butler
op 16-10-2026 12:29
Opmerking bij wijziging: Er is geen opmerking bij deze versie

Samenvatting

Details

Paginaeigenschappen
Inhoud
... ... @@ -1,4 +1,4 @@
1 -Tekenveld op de startpagina van de Kennisbank: een bijna onzichtbaar veld van letters en cijfers achter de inhoud, met een muisspoor, hartslagringen, af en toe een rode ECG-lijn en een smiley bij een klik op de lege achtergrond. Vijf snelle klikken op de lege achtergrond geven een explosie; daarna komt het veld in een minuut terug. Het is hetzelfde veld als in Ember, in een rustige variant: het vervaagt naar het midden en ligt stil na een minuut zonder muis.
1 +Tekenveld op de startpagina van de Kennisbank: een bijna onzichtbaar veld van letters en cijfers achter de inhoud, met een muisspoor, hartslagringen, af en toe een ECG-lijn en een smiley bij een klik op de lege achtergrond. Het is hetzelfde veld als in Ember, in een rustige variant: het vervaagt naar het midden en ligt stil na een minuut zonder muis.
2 2  
3 3  Het object //JavaScriptExtension// op deze pagina is de engine van Ember plus een korte opstart; het object //StyleSheetExtension// zet het canvas achter de inhoud. Beide staan op //onDemand// en worden alleen geladen door [[Startpagina>>doc:Wardenburg.Code.Startpagina]].
4 4  
XWiki.JavaScriptExtension[0]
code
... ... @@ -1,5 +1,5 @@
1 1  /* Tekenveld voor de Kennisbank. Gemaakt met maak-tekenveld.js uit de skill xwiki-wardenburg-admin.
2 - Engine: Ember src/lib/glyphField.js, commit 83ea536. Niet hier wijzigen: pas de bron aan en maak opnieuw. */
2 + Engine: Ember src/lib/glyphField.js, commit 2af047d. Niet hier wijzigen: pas de bron aan en maak opnieuw. */
3 3  (function () {
4 4  "use strict";
5 5  // /src/lib/glyphField.js
... ... @@ -258,11 +258,9 @@
258 258   const styles = getComputedStyle(root);
259 259   const text = styles.getPropertyValue("--text").trim() || "#111827";
260 260   const accent = styles.getPropertyValue("--brand-red").trim() || "#e62b27";
261 - // Een eigen kleur voor de hartslaglijn (ECG); zonder --glyph-line is dat het accent, zoals in Ember.
262 - const line = styles.getPropertyValue("--glyph-line").trim() || accent;
263 263   // :root zonder attribuut is in Ember donker; zie layout.css.
264 264   const mode = root.getAttribute("data-appearance") === "light" ? "light" : "dark";
265 - return { text, accent, line, mode };
263 + return { text, accent, mode };
266 266  }
267 267  
268 268  /* De tekens van een thema: een niet-lege lijst van hooguit 256 tekens (de index staat in een Uint8Array). */
... ... @@ -307,12 +307,9 @@
307 307   let trail = new Float32Array(0);
308 308   let pulse = new Float32Array(0);
309 309   let streak = new Float32Array(0);
310 - // Het spoor van de hartslaglijn apart van dat van de smileys, zodat de lijn een eigen kleur kan hebben.
311 - let lineTrail = new Float32Array(0);
312 312   let quiet = new Float32Array(0);
313 313   let neutralAtlas = null;
314 314   let accentAtlas = null;
315 - let lineAtlas = null;
316 316   let yellowAtlas = null;
317 317   let orangeAtlas = null;
318 318   let smokeAtlas = null;
... ... @@ -361,7 +361,6 @@
361 361   function buildAtlases() {
362 362   neutralAtlas = buildAtlas(theme.text);
363 363   accentAtlas = buildAtlas(theme.accent);
364 - lineAtlas = theme.line === theme.accent ? accentAtlas : buildAtlas(theme.line);
365 365   // Vuurkleuren voor de explosie.
366 366   yellowAtlas = buildAtlas(theme.mode === "light" ? "#eab308" : "#facc15");
367 367   orangeAtlas = buildAtlas("#f97316");
... ... @@ -393,7 +393,6 @@
393 393   trail = new Float32Array(cols * rows);
394 394   pulse = new Float32Array(cols * rows);
395 395   streak = new Float32Array(cols * rows);
396 - lineTrail = new Float32Array(cols * rows);
397 397   quiet = new Float32Array(cols * rows);
398 398   minC = minR = 1;
399 399   maxC = maxR = 0;
... ... @@ -405,7 +405,7 @@
405 405  
406 406   function applyTheme() {
407 407   const next = readTheme();
408 - if (next.text === theme.text && next.accent === theme.accent && next.line === theme.line && next.mode === theme.mode) return;
401 + if (next.text === theme.text && next.accent === theme.accent && next.mode === theme.mode) return;
409 409   theme = next;
410 410   buildAtlases();
411 411   lastAmbient = -Infinity;
... ... @@ -632,7 +632,7 @@
632 632   const phase = x / ecg.beatWidth + ecg.offset;
633 633   const y = ecg.baseY - (ecgShape(phase % 1) * beatScale(ecg, Math.floor(phase)) + wander) * ecg.amplitude;
634 634   if (Math.hypot(x - ecg.stampX, y - ecg.stampY) >= options.ecgRadius * 0.3) {
635 - stamp(x, y, options.ecgRadius, options.ecgStrength, true, lineTrail);
628 + stamp(x, y, options.ecgRadius, options.ecgStrength, true, streak);
636 636   ecg.stampX = x;
637 637   ecg.stampY = y;
638 638   }
... ... @@ -808,9 +808,8 @@
808 808   let heat = trail[index];
809 809   let beat = pulse[index];
810 810   let flash = streak[index];
811 - let pulseLine = lineTrail[index];
812 812   let hush = quiet[index];
813 - if (heat <= 0 && beat <= 0 && flash <= 0 && pulseLine <= 0 && hush <= 0) continue;
805 + if (heat <= 0 && beat <= 0 && flash <= 0 && hush <= 0) continue;
814 814  
815 815   if (heat > 0) {
816 816   heat *= decay;
... ... @@ -827,17 +827,12 @@
827 827   if (flash < 0.03) flash = 0;
828 828   streak[index] = flash;
829 829   }
830 - if (pulseLine > 0) {
831 - pulseLine *= streakDecay;
832 - if (pulseLine < 0.03) pulseLine = 0;
833 - lineTrail[index] = pulseLine;
834 - }
835 835   if (hush > 0) {
836 836   hush *= streakDecay;
837 837   if (hush < 0.03) hush = 0;
838 838   quiet[index] = hush;
839 839   }
840 - if (heat === 0 && beat === 0 && flash === 0 && pulseLine === 0 && hush === 0) continue;
827 + if (heat === 0 && beat === 0 && flash === 0 && hush === 0) continue;
841 841  
842 842   if (c < nextMinC) nextMinC = c;
843 843   if (c > nextMaxC) nextMaxC = c;
... ... @@ -845,7 +845,7 @@
845 845   if (r > nextMaxR) nextMaxR = r;
846 846  
847 847   // Onder het spoor en de hartslag wisselen de tekens snel.
848 - if (dt > 0 && Math.random() < (heat * 9 + beat * 5 + (flash + pulseLine) * 6) * dt) glyphs[index] = randomGlyph();
835 + if (dt > 0 && Math.random() < (heat * 9 + beat * 5 + flash * 6) * dt) glyphs[index] = randomGlyph();
849 849  
850 850   // Een verse ring is roder dan het spoor; verder weg is hij al zwakker en daarmee
851 851   // vanzelf grijzer.
... ... @@ -859,10 +859,9 @@
859 859   const x = cellX(c);
860 860   const sx = glyphs[index] * tileW;
861 861   // Achter een smiley wordt het rustende veld stilgezet (hush), zodat het gezicht
862 - // niet in de wolken verdwijnt. De smileys (flash) en de hartslaglijn (pulseLine) zijn vooral rood; de lijn in --glyph-line.
863 - const neutral = ambient[index] * calm * (1 - lift) * (1 - hush) + neutralMax * lift + streakNeutral * Math.max(flash, pulseLine);
849 + // niet in de wolken verdwijnt. De lijn en de smileys (flash) zijn vooral rood.
850 + const neutral = ambient[index] * calm * (1 - lift) * (1 - hush) + neutralMax * lift + streakNeutral * flash;
864 864   const red = Math.max(glow * glow * accentMax, flash * streakAccent);
865 - const lineRed = pulseLine * streakAccent;
866 866   ctx.clearRect(x, y, tileW, tileH);
867 867   if (neutral >= MIN_ALPHA) {
868 868   ctx.globalAlpha = neutral;
... ... @@ -872,10 +872,6 @@
872 872   ctx.globalAlpha = Math.min(1, red);
873 873   ctx.drawImage(accentAtlas, sx, 0, tileW, tileH, x, y, tileW, tileH);
874 874   }
875 - if (lineRed > 0.01) {
876 - ctx.globalAlpha = Math.min(1, lineRed);
877 - ctx.drawImage(lineAtlas, sx, 0, tileW, tileH, x, y, tileW, tileH);
878 - }
879 879   }
880 880   }
881 881  
... ... @@ -1204,7 +1204,6 @@
1204 1204   fallers = null;
1205 1205   canvas.style.transform = "";
1206 1206   streak.fill(0);
1207 - lineTrail.fill(0);
1208 1208   quiet.fill(0);
1209 1209   minC = minR = 1;
1210 1210   maxC = maxR = 0;
... ... @@ -1306,13 +1306,6 @@
1306 1306  // beeldverkeer op de terminalserver); bij de eerste beweging loopt het weer.
1307 1307  const KB_STILSTAND_MS = 60000;
1308 1308  
1309 -// De explosie van de engine: vijf klikken op de lege achtergrond binnen 1,6 seconde, met een
1310 -// nasleep van een minuut. Dezelfde getallen als de standaard van de engine; hier alleen om
1311 -// tijdens de explosie het vervagen naar het midden weg te halen en het veld wakker te houden.
1312 -const KB_BOEM_KLIKKEN = 5;
1313 -const KB_BOEM_VENSTER_MS = 1600;
1314 -const KB_BOEM_DUUR_MS = 62000;
1315 -
1316 1316  function kbTekenveld() {
1317 1317   // Alleen op de startpagina; de extensie wordt ook alleen daar geladen.
1318 1318   if (!document.querySelector(".wb-home")) return;
... ... @@ -1325,59 +1325,29 @@
1325 1325   canvas.setAttribute("aria-hidden", "true");
1326 1326   document.body.prepend(canvas);
1327 1327  
1328 - const isAchtergrond = (event) => event.target instanceof Element && !event.target.closest(KB_NIET_ACHTERGROND);
1329 1329   const opties = {
1330 1330   ...glyphFieldSettings({ intensity: "lijst" }),
1331 - isBackground: isAchtergrond,
1304 + // Geen atoomexplosie op de Kennisbank.
1305 + nukeClicks: Infinity,
1306 + isBackground: (event) => event.target instanceof Element && !event.target.closest(KB_NIET_ACHTERGROND),
1332 1332   obstacles: () => Array.from(document.querySelectorAll(KB_BLOKKEN), (element) => element.getBoundingClientRect()),
1333 1333   };
1334 1334  
1335 1335   let veld = null;
1336 1336   let rustTimer = 0;
1337 - let klikken = [];
1338 - let boemTot = 0;
1339 1339  
1340 - function slaap() {
1341 - // Tijdens een explosie niet: de nasleep duurt een minuut, ook zonder muis.
1342 - if (Date.now() < boemTot) {
1343 - rustTimer = window.setTimeout(slaap, boemTot - Date.now());
1344 - return;
1345 - }
1346 - // Het laatste beeld blijft staan; alleen de animatie stopt.
1347 - veld.destroy();
1348 - veld = null;
1349 - }
1350 -
1351 - // De klik die een slapend veld wekt, ziet de engine zelf niet (hij luistert pas daarna);
1352 - // die telt hier dus ook niet mee, anders lopen de twee tellers uiteen.
1353 - let wekklik = null;
1354 -
1355 - function wakker(event) {
1356 - if (!veld) {
1357 - veld = createGlyphField(canvas, opties);
1358 - wekklik = event || null;
1359 - }
1313 + function wakker() {
1314 + if (!veld) veld = createGlyphField(canvas, opties);
1360 1360   window.clearTimeout(rustTimer);
1361 - rustTimer = window.setTimeout(slaap, KB_STILSTAND_MS);
1316 + rustTimer = window.setTimeout(() => {
1317 + // Het laatste beeld blijft staan; alleen de animatie stopt.
1318 + veld.destroy();
1319 + veld = null;
1320 + }, KB_STILSTAND_MS);
1362 1362   }
1363 1363  
1364 - function telKlik(event) {
1365 - const nu = Date.now();
1366 - if (event === wekklik || event.button !== 0 || nu < boemTot || !isAchtergrond(event)) return;
1367 - klikken = klikken.filter((tijd) => nu - tijd < KB_BOEM_VENSTER_MS);
1368 - klikken.push(nu);
1369 - if (klikken.length < KB_BOEM_KLIKKEN) return;
1370 - klikken = [];
1371 - boemTot = nu + KB_BOEM_DUUR_MS;
1372 - // Tijdens de explosie het hele scherm, niet alleen de randen.
1373 - canvas.classList.add("kb-tekenveld--boem");
1374 - window.setTimeout(() => canvas.classList.remove("kb-tekenveld--boem"), KB_BOEM_DUUR_MS);
1375 - }
1376 -
1377 1377   window.addEventListener("pointermove", wakker, { passive: true });
1378 - // Eerst wakker maken, zodat de engine de klik ook krijgt als het veld sliep.
1379 1379   window.addEventListener("pointerdown", wakker, { passive: true });
1380 - window.addEventListener("pointerdown", telKlik, { passive: true });
1381 1381   wakker();
1382 1382  }
1383 1383  
XWiki.StyleSheetExtension[0]
Caching policy
... ... @@ -1,1 +1,0 @@
1 -long
Code
... ... @@ -1,54 +1,0 @@
1 -/* Tekenveld op de startpagina van de Kennisbank (Wardenburg.Code.Tekenveld); alleen geladen op
2 - de startpagina. Het canvas ligt achter de inhoud; de vlakken eromheen worden doorzichtig. */
3 -
4 -/* Kleuren voor de engine: de tekstkleur en het donkere oranje (brand-warning) uit het kleurthema;
5 - de hartslaglijn in het rood van het thema (brand-danger). */
6 -html {
7 - --text: #202124;
8 - --brand-red: #e8920c;
9 - --glyph-line: #d0021b;
10 - background: #ffffff;
11 -}
12 -
13 -body,
14 -#body,
15 -#contentcontainer,
16 -#contentcolumn,
17 -#mainContentArea,
18 -.main,
19 -#xwikicontent,
20 -.wb-home {
21 - background: transparent !important;
22 -}
23 -
24 -canvas.kb-tekenveld {
25 - position: fixed;
26 - inset: 0;
27 - z-index: -1;
28 - pointer-events: none;
29 - /* Naar het midden, waar het zoekveld en de tegels staan, vervaagt het veld tot 40%: het zwakke
30 - grijze veld is daar vrijwel weg, de rode hartslaglijn komt er nog doorheen. */
31 - -webkit-mask-image: radial-gradient(ellipse 48% 58% at 50% 55%, rgba(0, 0, 0, .4) 45%, #000 100%);
32 - mask-image: radial-gradient(ellipse 48% 58% at 50% 55%, rgba(0, 0, 0, .4) 45%, #000 100%);
33 -}
34 -
35 -/* Tijdens de explosie (vijf snelle klikken) het hele scherm. */
36 -canvas.kb-tekenveld.kb-tekenveld--boem {
37 - -webkit-mask-image: none;
38 - mask-image: none;
39 -}
40 -
41 -/* Leesbaarheid: een zachte witte gloed achter de kop, het zoekveld en elke tegel. */
42 -.wb-zoek > h1,
43 -.wb-zoek > p,
44 -.wb-zoek > form,
45 -.wb-tegels > li > a {
46 - background: radial-gradient(closest-side, rgba(255, 255, 255, .97) 62%, rgba(255, 255, 255, 0) 100%);
47 -}
48 -
49 -.wb-home-onder {
50 - background: #ffffff;
51 - border-radius: 16px;
52 - box-shadow: 0 0 36px 28px #ffffff;
53 -}
54 -
Content Type
... ... @@ -1,1 +1,0 @@
1 -CSS
Naam
... ... @@ -1,1 +1,0 @@
1 -Wardenburg tekenveld
Inhoud verwerken
... ... @@ -1,1 +1,0 @@
1 -Nee
Gebruik deze uitbreiding
... ... @@ -1,1 +1,0 @@
1 -onDemand