v0.7.4: light-versie voor de modelpagina's (light.html, js/light/, css/light.css; later in de HUGO-site in een Bootstrap col-12): één model in 3D, doorsnede (snijhoogte tot de goot) en 2D-plattegrond, met beperkte keuzes: per unit breedte en diepte (binnen UnitModel.LIMITS, per model/pagina te beperken), dakvorm met richting, goot- en nokhoogte (helling erbij) en wolfseind, dakbedekking, gevelbekleding met kleur en richting, accent van het model, trasraam (geen/steen, hoogte), binnenspots en buitenverlichting; zelfde berekening als de configurator maar alleen prijs (indicatief, incl. btw), maten, m², inhoud en gewicht zichtbaar; LightModel past keuzes toe op een schone kopie van het model (binnenwanden en inrichting schuiven mee, binnenwanden volgen de goot) en weigert keuzes die de indeling breken (ramen/deuren, binnenwanden, inrichting, ruimtes, overlap) met de dichtstbijzijnde maat die wel past; accordeon-paneel, responsief op de breedte van de tool (container queries), scrollwiel scrolt de pagina tenzij je in de 3D klikt of Ctrl houdt; opslaan = PDF (LightPdf): voorblad "Uw woningontwerp" met render, kerncijfers, keuzes, prijs, contact en QR-code naar de modelpagina (qrcode-generator, MIT), aanzichten en plattegrond (HousePdf klantvariant zonder productie-informatie) en het stappenplan met maatwerk en uitnodiging; doorsnede-afdekking naar HouseModel.sectionCaps (ook in de configurator): 1 mm boven de snede en over de wandtop van wanden die lager blijven, geen flikkerend regelwerk meer; OrbitControls met touch (één vinger draaien, twee vingers knijpen/schuiven); model Vecht (U-vorm 13 × 9,5 m, drie units rond een holte)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
51921650e3
commit
decbbb4b72
Vendored
+54
-20
@@ -4,7 +4,8 @@
|
||||
// hebben om het origineel te vendoren; dekt precies de subset die wall.js
|
||||
// gebruikt (`new THREE.OrbitControls(camera, domElement)`,
|
||||
// `controls.target.set(...)`, `controls.update()`), plus interactie:
|
||||
// links-slepen = roteren, scrollwiel = zoomen, rechts-slepen = pannen.
|
||||
// links-slepen = roteren, scrollwiel = zoomen, rechts-slepen = pannen;
|
||||
// touch: één vinger = roteren, twee vingers = knijpen (zoomen) en samen schuiven (pannen).
|
||||
//
|
||||
// Moet NA three.min.js geladen worden (leunt op window.THREE).
|
||||
// ============================================================
|
||||
@@ -60,13 +61,7 @@
|
||||
lastY = event.clientY;
|
||||
}
|
||||
|
||||
function onPointerMove(event) {
|
||||
if (isRotating) {
|
||||
const dx = event.clientX - lastX;
|
||||
const dy = event.clientY - lastY;
|
||||
lastX = event.clientX;
|
||||
lastY = event.clientY;
|
||||
|
||||
function rotate(dx, dy) {
|
||||
const w = scope.domElement.clientWidth || 1;
|
||||
const h = scope.domElement.clientHeight || 1;
|
||||
|
||||
@@ -79,12 +74,8 @@
|
||||
offset.setFromSpherical(spherical);
|
||||
scope.object.position.copy(scope.target).add(offset);
|
||||
scope.object.lookAt(scope.target);
|
||||
} else if (isPanning) {
|
||||
const dx = event.clientX - lastX;
|
||||
const dy = event.clientY - lastY;
|
||||
lastX = event.clientX;
|
||||
lastY = event.clientY;
|
||||
|
||||
}
|
||||
function pan(dx, dy) {
|
||||
const distance = scope.object.position.distanceTo(scope.target);
|
||||
const fov = (scope.object.fov || 50) * Math.PI / 180;
|
||||
const h = scope.domElement.clientHeight || 1;
|
||||
@@ -95,7 +86,22 @@
|
||||
const yAxis = new THREE.Vector3(te[4], te[5], te[6]).multiplyScalar(dy * factor * scope.panSpeed);
|
||||
scope.target.add(xAxis).add(yAxis);
|
||||
scope.object.position.add(xAxis).add(yAxis);
|
||||
}
|
||||
}
|
||||
function zoom(scale) {
|
||||
offset.copy(scope.object.position).sub(scope.target);
|
||||
const distance = Math.max(scope.minDistance, Math.min(scope.maxDistance, offset.length() * scale));
|
||||
offset.setLength(distance);
|
||||
scope.object.position.copy(scope.target).add(offset);
|
||||
}
|
||||
|
||||
function onPointerMove(event) {
|
||||
if (!isRotating && !isPanning) return;
|
||||
const dx = event.clientX - lastX;
|
||||
const dy = event.clientY - lastY;
|
||||
lastX = event.clientX;
|
||||
lastY = event.clientY;
|
||||
if (isRotating) rotate(dx, dy);
|
||||
else pan(dx, dy);
|
||||
}
|
||||
|
||||
function onPointerUp() { isRotating = false; isPanning = false; }
|
||||
@@ -103,13 +109,33 @@
|
||||
function onWheel(event) {
|
||||
if (!scope.enableZoom) return;
|
||||
event.preventDefault();
|
||||
const scale = event.deltaY > 0 ? 1 / getZoomScale() : getZoomScale();
|
||||
offset.copy(scope.object.position).sub(scope.target);
|
||||
const distance = Math.max(scope.minDistance, Math.min(scope.maxDistance, offset.length() * scale));
|
||||
offset.setLength(distance);
|
||||
scope.object.position.copy(scope.target).add(offset);
|
||||
zoom(event.deltaY > 0 ? 1 / getZoomScale() : getZoomScale());
|
||||
}
|
||||
|
||||
// Touch: midden en afstand van de vingers; bij een wissel van het aantal vingers opnieuw beginnen.
|
||||
let touch = null;
|
||||
function touchState(list) {
|
||||
const a = list[0], b = list[1] || list[0];
|
||||
return { n: list.length, x: (a.clientX + b.clientX) / 2, y: (a.clientY + b.clientY) / 2, d: Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY) };
|
||||
}
|
||||
function onTouchStart(event) {
|
||||
event.preventDefault();
|
||||
touch = touchState(event.touches);
|
||||
}
|
||||
function onTouchMove(event) {
|
||||
if (!touch) return;
|
||||
event.preventDefault();
|
||||
const t = touchState(event.touches);
|
||||
if (t.n !== touch.n) { touch = t; return; }
|
||||
if (t.n === 1) { if (scope.enableRotate) rotate(t.x - touch.x, t.y - touch.y); }
|
||||
else {
|
||||
if (scope.enablePan) pan(t.x - touch.x, t.y - touch.y);
|
||||
if (scope.enableZoom && t.d > 0 && touch.d > 0) zoom(touch.d / t.d);
|
||||
}
|
||||
touch = t;
|
||||
}
|
||||
function onTouchEnd(event) { touch = event.touches.length ? touchState(event.touches) : null; }
|
||||
|
||||
function onContextMenu(event) { event.preventDefault(); }
|
||||
|
||||
this.domElement.addEventListener('mousedown', onPointerDown);
|
||||
@@ -117,6 +143,10 @@
|
||||
window.addEventListener('mouseup', onPointerUp);
|
||||
this.domElement.addEventListener('wheel', onWheel, { passive: false });
|
||||
this.domElement.addEventListener('contextmenu', onContextMenu);
|
||||
this.domElement.addEventListener('touchstart', onTouchStart, { passive: false });
|
||||
this.domElement.addEventListener('touchmove', onTouchMove, { passive: false });
|
||||
this.domElement.addEventListener('touchend', onTouchEnd);
|
||||
this.domElement.addEventListener('touchcancel', onTouchEnd);
|
||||
|
||||
this.dispose = function () {
|
||||
scope.domElement.removeEventListener('mousedown', onPointerDown);
|
||||
@@ -124,6 +154,10 @@
|
||||
window.removeEventListener('mouseup', onPointerUp);
|
||||
scope.domElement.removeEventListener('wheel', onWheel);
|
||||
scope.domElement.removeEventListener('contextmenu', onContextMenu);
|
||||
scope.domElement.removeEventListener('touchstart', onTouchStart);
|
||||
scope.domElement.removeEventListener('touchmove', onTouchMove);
|
||||
scope.domElement.removeEventListener('touchend', onTouchEnd);
|
||||
scope.domElement.removeEventListener('touchcancel', onTouchEnd);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user