- Zwei Finger auf- und zuziehen zoomt die Uebersicht. Beide Zeiger werden mitgefuehrt; laesst man einen Finger los, geht es nahtlos ins Drehen ueber. - Mausrad zoomt weiterhin, jetzt auch mit gedrueckter Strg-Taste - der Seitenzoom des Browsers wird dabei unterdrueckt. Die Schrittweite kommt aus dem Betrag des Radwegs, damit Trackpads feiner dosieren koennen. - Zoombereich 9 bis 120 m statt 14 bis 110 m. - Das Wischen des Rundgangs wird im Uebersichtsmodus nicht mehr ausgewertet; sonst sammelte sich dort eine Blickdrehung an, die beim Zurueckwechseln sprang. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -264,6 +264,9 @@ Damit es nicht ruppig wirkt:
|
||||
Oberkante geht in die Höhenabfrage ein (`walkHeight` in `main.ts`,
|
||||
`treppeTritte` in `structures.ts`). Ob man hinaufkommt, entscheidet nur die
|
||||
Stufenhöhe (45 cm). Holz-, Lamellen- und Betonwände bleiben Hindernisse.
|
||||
- In der **Übersicht** dreht Ziehen die Ansicht; gezoomt wird mit dem Mausrad
|
||||
(auch mit `Strg`, wobei der Seitenzoom des Browsers unterdrückt wird) und am
|
||||
Handy mit zwei Fingern. Abstand 9 bis 120 m.
|
||||
- Das **Gartentor** öffnet sich, wenn man darauf zugeht, und schliesst sich
|
||||
hinter einem wieder; `E` übersteuert das von Hand. Im Durchgang selbst
|
||||
schliesst es nie.
|
||||
|
||||
@@ -145,6 +145,7 @@ export class Walker {
|
||||
let last = { x: 0, y: 0 };
|
||||
let start = { x: 0, y: 0, t: 0 };
|
||||
dom.addEventListener('touchstart', (e) => {
|
||||
if (!this.enabled) return;
|
||||
for (const t of Array.from(e.changedTouches)) {
|
||||
if (touchId === null && t.clientX > window.innerWidth * 0.35) {
|
||||
touchId = t.identifier;
|
||||
@@ -154,6 +155,7 @@ export class Walker {
|
||||
}
|
||||
}, { passive: true });
|
||||
dom.addEventListener('touchmove', (e) => {
|
||||
if (!this.enabled) { touchId = null; return; }
|
||||
for (const t of Array.from(e.changedTouches)) {
|
||||
if (t.identifier !== touchId) continue;
|
||||
this.lookDelta.x += (t.clientX - last.x) * 0.006;
|
||||
|
||||
+55
-5
@@ -336,27 +336,77 @@ async function main() {
|
||||
},
|
||||
};
|
||||
|
||||
const ABSTAND = { nah: 9, fern: 120 };
|
||||
const zoome = (faktor: number) => {
|
||||
orbit.distance = Math.max(ABSTAND.nah, Math.min(ABSTAND.fern, orbit.distance * faktor));
|
||||
orbit.apply();
|
||||
};
|
||||
|
||||
// Ziehen dreht, zwei Finger zoomen. Beide Zeiger werden mitgefuehrt, damit
|
||||
// beim Loslassen eines Fingers nahtlos weitergedreht wird.
|
||||
let dragging = false;
|
||||
let lastPointer = { x: 0, y: 0 };
|
||||
const zeiger = new Map<number, { x: number; y: number }>();
|
||||
let kneifStart = 0;
|
||||
let kneifAbstand = 0;
|
||||
const kneifSpanne = () => {
|
||||
const [a, b] = [...zeiger.values()];
|
||||
return Math.hypot(a.x - b.x, a.y - b.y);
|
||||
};
|
||||
|
||||
canvas.addEventListener('pointerdown', (e) => {
|
||||
if (!orbit.active) return;
|
||||
zeiger.set(e.pointerId, { x: e.clientX, y: e.clientY });
|
||||
canvas.setPointerCapture(e.pointerId);
|
||||
if (zeiger.size === 2) {
|
||||
dragging = false;
|
||||
kneifAbstand = kneifSpanne();
|
||||
kneifStart = orbit.distance;
|
||||
} else if (zeiger.size === 1) {
|
||||
dragging = true;
|
||||
lastPointer = { x: e.clientX, y: e.clientY };
|
||||
canvas.setPointerCapture(e.pointerId);
|
||||
}
|
||||
});
|
||||
canvas.addEventListener('pointermove', (e) => {
|
||||
if (!orbit.active || !dragging) return;
|
||||
if (!orbit.active || !zeiger.has(e.pointerId)) return;
|
||||
zeiger.set(e.pointerId, { x: e.clientX, y: e.clientY });
|
||||
if (zeiger.size >= 2) {
|
||||
// Finger auseinander = naeher heran
|
||||
const jetzt = kneifSpanne();
|
||||
if (jetzt > 1 && kneifAbstand > 1) {
|
||||
orbit.distance = Math.max(ABSTAND.nah, Math.min(ABSTAND.fern, kneifStart * (kneifAbstand / jetzt)));
|
||||
orbit.apply();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!dragging) return;
|
||||
orbit.yaw -= (e.clientX - lastPointer.x) * 0.006;
|
||||
orbit.pitch = Math.max(0.12, Math.min(1.45, orbit.pitch + (e.clientY - lastPointer.y) * 0.004));
|
||||
lastPointer = { x: e.clientX, y: e.clientY };
|
||||
orbit.apply();
|
||||
});
|
||||
canvas.addEventListener('pointerup', () => { dragging = false; });
|
||||
const zeigerWeg = (e: PointerEvent) => {
|
||||
zeiger.delete(e.pointerId);
|
||||
if (zeiger.size === 1) {
|
||||
// Vom Zoomen zurueck aufs Drehen, ohne Sprung
|
||||
const [rest] = [...zeiger.values()];
|
||||
lastPointer = { ...rest };
|
||||
dragging = true;
|
||||
} else if (zeiger.size === 0) {
|
||||
dragging = false;
|
||||
}
|
||||
};
|
||||
canvas.addEventListener('pointerup', zeigerWeg);
|
||||
canvas.addEventListener('pointercancel', zeigerWeg);
|
||||
|
||||
// Mausrad zoomt - auch mit Strg, wo der Browser sonst die Seite vergroessern
|
||||
// wuerde. Trackpads melden feine Schritte, deshalb wird die Staerke aus dem
|
||||
// Betrag abgeleitet statt nur aus der Richtung.
|
||||
canvas.addEventListener('wheel', (e) => {
|
||||
if (!orbit.active) return;
|
||||
e.preventDefault();
|
||||
orbit.distance = Math.max(14, Math.min(110, orbit.distance * (1 + Math.sign(e.deltaY) * 0.12)));
|
||||
orbit.apply();
|
||||
const schritt = Math.max(-1, Math.min(1, e.deltaY / (e.deltaMode === 1 ? 3 : 120)));
|
||||
zoome(1 + schritt * 0.14);
|
||||
}, { passive: false });
|
||||
|
||||
// -- Umschalten zwischen den Darstellungen --------------------------------
|
||||
|
||||
+2
-1
@@ -178,7 +178,8 @@ export function setupHud(opts: HudOptions): Hud {
|
||||
<li>Treppen, Stufen und Sitzmauern sind begehbar. Das Gartentor öffnet sich,
|
||||
wenn man darauf zugeht; <kbd>E</kbd> öffnet oder schliesst es von Hand.</li>
|
||||
<li>Am Handy: auf den Boden tippen, links der Joystick, rechts wischen zum Umsehen</li>
|
||||
<li>Übersicht: ziehen zum Drehen, Mausrad zum Zoomen</li>
|
||||
<li>Übersicht: ziehen zum Drehen; zoomen mit dem Mausrad (auch mit <kbd>Strg</kbd>),
|
||||
am Handy mit zwei Fingern auf- und zuziehen</li>
|
||||
<li>Die Sonne steht für Abtwil SG astronomisch korrekt</li>
|
||||
</ul>
|
||||
<p id="sun-readout"></p>
|
||||
|
||||
Reference in New Issue
Block a user