- bootstrap-icons: @font-face correct ingebed (selector .bi::before was stuk) - core/skybox.js + assets/skybox-data.js (lazy), knop Lucht in alle 3D-weergaven - woning: met lucht aan raster en sandwichpanelen onzichtbaar Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
2.9 KiB
JavaScript
80 lines
2.9 KiB
JavaScript
/*!
|
|
* Tectum
|
|
* Copyright © 2026 Machiel Heinen.
|
|
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
|
|
* Zie LICENTIE.md.
|
|
*/
|
|
// ============================================================
|
|
// core/skybox.js — lucht-achtergrond (equirectangulair panorama) voor de
|
|
// 3D-weergaven, met een "Lucht"-knop in de 3D-werkbalk. De afbeelding
|
|
// (assets/skybox-data.js, gegenereerd uit assets/skybox.webp) wordt pas bij
|
|
// de eerste keer aanzetten geladen en daarna gedeeld. De keuze aan/uit wordt
|
|
// onthouden (localStorage, alleen gemak).
|
|
// Plain script (geen ES-module).
|
|
// ============================================================
|
|
|
|
window.Skybox = (() => {
|
|
const PREF_KEY = 'tectum.skybox';
|
|
let texturePromise = null;
|
|
|
|
function load() {
|
|
if (texturePromise) return texturePromise;
|
|
texturePromise = new Promise((resolve, reject) => {
|
|
const fromData = () => {
|
|
const img = new Image();
|
|
img.onload = () => {
|
|
const tex = new THREE.Texture(img);
|
|
tex.mapping = THREE.EquirectangularReflectionMapping;
|
|
tex.needsUpdate = true;
|
|
resolve(tex);
|
|
};
|
|
img.onerror = reject;
|
|
img.src = window.TECTUM_SKYBOX;
|
|
};
|
|
if (window.TECTUM_SKYBOX) return fromData();
|
|
const s = document.createElement('script');
|
|
s.src = 'assets/skybox-data.js';
|
|
s.onload = fromData;
|
|
s.onerror = reject;
|
|
document.head.appendChild(s);
|
|
});
|
|
texturePromise.catch(() => { texturePromise = null; });
|
|
return texturePromise;
|
|
}
|
|
|
|
function isOn() {
|
|
try { return localStorage.getItem(PREF_KEY) === '1'; } catch (e) { return false; }
|
|
}
|
|
function remember(on) {
|
|
try { localStorage.setItem(PREF_KEY, on ? '1' : '0'); } catch (e) { /* geen opslag: alleen deze sessie */ }
|
|
}
|
|
|
|
// Zet de achtergrond van `scene`: lucht als on, anders fallbackColor (hex).
|
|
// wanted() wordt na het laden nog eens gevraagd (knop intussen uitgezet?).
|
|
function apply(scene, on, fallbackColor, wanted) {
|
|
if (!on) { scene.background = new THREE.Color(fallbackColor); return; }
|
|
load().then(tex => { if (!wanted || wanted()) scene.background = tex; })
|
|
.catch(() => { scene.background = new THREE.Color(fallbackColor); });
|
|
}
|
|
|
|
// "Lucht"-knop in een 3D-werkbalk. onChange(on) bij elke klik (en niet bij
|
|
// aanmaken: de aanroeper leest de begintoestand met isOn()).
|
|
function createToggle(toolbar, onChange) {
|
|
const btn = document.createElement('button');
|
|
btn.type = 'button';
|
|
btn.className = 'btn-3d-toggle' + (isOn() ? ' active' : '');
|
|
btn.title = 'Lucht als achtergrond';
|
|
btn.innerHTML = '<i class="bi bi-cloud-sun"></i>Lucht';
|
|
btn.addEventListener('click', () => {
|
|
const on = !btn.classList.contains('active');
|
|
btn.classList.toggle('active', on);
|
|
remember(on);
|
|
onChange(on);
|
|
});
|
|
toolbar.appendChild(btn);
|
|
return btn;
|
|
}
|
|
|
|
return { load, isOn, apply, createToggle };
|
|
})();
|