Skip to content

Commit a2e8a0b

Browse files
committed
rebase
1 parent 2ef979a commit a2e8a0b

2 files changed

Lines changed: 41 additions & 307 deletions

File tree

‎vizmat-app/index.js‎

Lines changed: 1 addition & 307 deletions
Original file line numberDiff line numberDiff line change
@@ -1,315 +1,9 @@
11
(function () {
2+
const canvas = document.getElementById("bevy-canvas");
23
const loader = document.getElementById("app-loader");
34
const status = document.getElementById("loader-status");
4-
const canvas = document.getElementById("bevy-canvas");
5-
const pickerInput = document.getElementById("picker-keyboard-input");
65
if (!loader) return;
76

8-
const emitPickerQuery = (action) => {
9-
if (!pickerInput) return;
10-
const query = pickerInput.value || "";
11-
window.dispatchEvent(
12-
new CustomEvent("vizmat-picker-query", {
13-
detail: {
14-
query,
15-
action,
16-
},
17-
}),
18-
);
19-
};
20-
21-
if (pickerInput) {
22-
window.addEventListener("vizmat-structure-picker-open", () => {
23-
pickerInput.value = "";
24-
try {
25-
pickerInput.focus({ preventScroll: true });
26-
} catch (error) {
27-
pickerInput.focus();
28-
}
29-
emitPickerQuery("change");
30-
});
31-
32-
window.addEventListener("vizmat-structure-picker-close", () => {
33-
pickerInput.blur();
34-
pickerInput.value = "";
35-
});
36-
37-
pickerInput.addEventListener("input", () => emitPickerQuery("change"));
38-
pickerInput.addEventListener("keydown", (event) => {
39-
if (event.key === "Enter") {
40-
event.preventDefault();
41-
emitPickerQuery("submit");
42-
event.stopPropagation();
43-
}
44-
});
45-
}
46-
47-
const emitTouchGesture = (gesture) => {
48-
window.dispatchEvent(
49-
new CustomEvent("vizmat-touch-gesture", {
50-
detail: gesture,
51-
}),
52-
);
53-
};
54-
55-
const toVec = (touch) => ({ x: touch.clientX, y: touch.clientY });
56-
57-
const touchPanState = {
58-
one: null,
59-
two: {
60-
active: false,
61-
midpoint: null,
62-
distance: null,
63-
},
64-
};
65-
66-
const getMidpoint = (a, b) => ({
67-
x: (a.x + b.x) * 0.5,
68-
y: (a.y + b.y) * 0.5,
69-
});
70-
71-
const getDistance = (a, b) => {
72-
const dx = a.x - b.x;
73-
const dy = a.y - b.y;
74-
return Math.hypot(dx, dy);
75-
};
76-
77-
const clearTouchState = () => {
78-
touchPanState.one = null;
79-
touchPanState.two = {
80-
active: false,
81-
midpoint: null,
82-
distance: null,
83-
};
84-
};
85-
86-
const emitIf = (condition, payload) => {
87-
if (!condition) return false;
88-
emitTouchGesture(payload);
89-
return true;
90-
};
91-
92-
if (canvas) {
93-
canvas.style.touchAction = "none";
94-
95-
if (window.PointerEvent) {
96-
const pointerState = new Map();
97-
98-
const removePointer = (event) => {
99-
if (event.pointerType !== "touch") return;
100-
if (!event.currentTarget || !pointerState.has(event.pointerId)) return;
101-
pointerState.delete(event.pointerId);
102-
103-
if (pointerState.size === 0) {
104-
clearTouchState();
105-
return;
106-
}
107-
108-
if (pointerState.size === 1) {
109-
touchPanState.one = [...pointerState.values()][0];
110-
touchPanState.two = {
111-
active: false,
112-
midpoint: null,
113-
distance: null,
114-
};
115-
return;
116-
}
117-
118-
const points = [...pointerState.values()];
119-
touchPanState.two = {
120-
active: true,
121-
midpoint: getMidpoint(points[0], points[1]),
122-
distance: getDistance(points[0], points[1]),
123-
};
124-
};
125-
126-
const updateSinglePointer = (point) => {
127-
if (!touchPanState.one) {
128-
touchPanState.one = point;
129-
return;
130-
}
131-
132-
const dx = point.x - touchPanState.one.x;
133-
const dy = point.y - touchPanState.one.y;
134-
const emitted = emitIf(dx !== 0 || dy !== 0, {
135-
gesture: "Rotate",
136-
dx,
137-
dy,
138-
scale_delta: 0,
139-
});
140-
if (emitted) {
141-
touchPanState.one = point;
142-
}
143-
};
144-
145-
const updateTwoPointer = (a, b) => {
146-
if (!touchPanState.two.active) {
147-
touchPanState.two = {
148-
active: true,
149-
midpoint: getMidpoint(a, b),
150-
distance: getDistance(a, b),
151-
};
152-
return;
153-
}
154-
155-
const midpoint = getMidpoint(a, b);
156-
const distance = getDistance(a, b);
157-
const panDx = midpoint.x - touchPanState.two.midpoint.x;
158-
const panDy = midpoint.y - touchPanState.two.midpoint.y;
159-
const scaleDelta =
160-
touchPanState.two.distance > 0
161-
? (distance - touchPanState.two.distance) / touchPanState.two.distance
162-
: 0;
163-
164-
const emitted = emitIf(panDx !== 0 || panDy !== 0 || scaleDelta !== 0, {
165-
gesture: "TwoFinger",
166-
dx: panDx,
167-
dy: panDy,
168-
scale_delta: scaleDelta,
169-
});
170-
171-
if (emitted) {
172-
touchPanState.two.midpoint = midpoint;
173-
touchPanState.two.distance = distance;
174-
}
175-
};
176-
177-
canvas.addEventListener(
178-
"pointerdown",
179-
(event) => {
180-
if (event.pointerType !== "touch") return;
181-
if (!event.target) return;
182-
const point = toVec(event);
183-
pointerState.set(event.pointerId, point);
184-
event.currentTarget.setPointerCapture(event.pointerId);
185-
touchPanState.one = point;
186-
touchPanState.two = {
187-
active: false,
188-
midpoint: null,
189-
distance: null,
190-
};
191-
event.preventDefault();
192-
},
193-
{ passive: false },
194-
);
195-
196-
canvas.addEventListener(
197-
"pointermove",
198-
(event) => {
199-
if (event.pointerType !== "touch") return;
200-
if (!pointerState.has(event.pointerId)) return;
201-
202-
const point = toVec(event);
203-
pointerState.set(event.pointerId, point);
204-
205-
if (pointerState.size === 1) {
206-
updateSinglePointer(point);
207-
} else if (pointerState.size >= 2) {
208-
const points = [...pointerState.values()];
209-
const a = points[0];
210-
const b = points[1];
211-
updateTwoPointer(a, b);
212-
}
213-
214-
event.preventDefault();
215-
},
216-
{ passive: false },
217-
);
218-
219-
canvas.addEventListener(
220-
"pointerup",
221-
removePointer,
222-
{ passive: false },
223-
);
224-
canvas.addEventListener("pointercancel", removePointer, {
225-
passive: false,
226-
});
227-
canvas.addEventListener("pointerleave", removePointer, {
228-
passive: false,
229-
});
230-
canvas.addEventListener("pointerout", removePointer, { passive: false });
231-
canvas.addEventListener("pointerlostcapture", removePointer);
232-
} else {
233-
canvas.addEventListener(
234-
"touchstart",
235-
(event) => {
236-
if (!event.target) return;
237-
if (event.touches.length === 1) {
238-
touchPanState.one = toVec(event.touches[0]);
239-
touchPanState.two.active = false;
240-
} else if (event.touches.length === 2) {
241-
const a = toVec(event.touches[0]);
242-
const b = toVec(event.touches[1]);
243-
touchPanState.two = {
244-
active: true,
245-
midpoint: getMidpoint(a, b),
246-
distance: getDistance(a, b),
247-
};
248-
touchPanState.one = null;
249-
}
250-
event.preventDefault();
251-
},
252-
{ passive: false },
253-
);
254-
255-
canvas.addEventListener(
256-
"touchmove",
257-
(event) => {
258-
if (event.touches.length === 1 && touchPanState.one) {
259-
const current = toVec(event.touches[0]);
260-
const dx = current.x - touchPanState.one.x;
261-
const dy = current.y - touchPanState.one.y;
262-
263-
if (dx !== 0 || dy !== 0) {
264-
emitTouchGesture({
265-
gesture: "Rotate",
266-
dx,
267-
dy,
268-
scale_delta: 0,
269-
});
270-
touchPanState.one = current;
271-
}
272-
event.preventDefault();
273-
return;
274-
}
275-
276-
if (event.touches.length === 2 && touchPanState.two.active) {
277-
const a = toVec(event.touches[0]);
278-
const b = toVec(event.touches[1]);
279-
const midpoint = getMidpoint(a, b);
280-
const distance = getDistance(a, b);
281-
282-
const panDx = midpoint.x - touchPanState.two.midpoint.x;
283-
const panDy = midpoint.y - touchPanState.two.midpoint.y;
284-
const scaleDelta =
285-
touchPanState.two.distance > 0
286-
? (distance - touchPanState.two.distance) / touchPanState.two.distance
287-
: 0;
288-
289-
if (panDx !== 0 || panDy !== 0 || scaleDelta !== 0) {
290-
emitTouchGesture({
291-
gesture: "TwoFinger",
292-
dx: panDx,
293-
dy: panDy,
294-
scale_delta: scaleDelta,
295-
});
296-
touchPanState.two.midpoint = midpoint;
297-
touchPanState.two.distance = distance;
298-
}
299-
300-
event.preventDefault();
301-
}
302-
},
303-
{ passive: false },
304-
);
305-
}
306-
307-
const clearTouch = () => clearTouchState();
308-
canvas.addEventListener("touchend", clearTouch, { passive: false });
309-
canvas.addEventListener("touchcancel", clearTouch, { passive: false });
310-
canvas.addEventListener("touchleave", clearTouch, { passive: false });
311-
}
312-
3137
if (canvas) {
3148
// Keep RMB free for in-app panning instead of opening browser context menu.
3159
canvas.addEventListener("contextmenu", (event) => event.preventDefault());

‎vizmat-app/mobile-gesture.js‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,45 @@
11
(function () {
22
const canvas = document.getElementById("bevy-canvas");
3+
const pickerInput = document.getElementById("picker-keyboard-input");
4+
5+
const emitPickerQuery = (action) => {
6+
if (!pickerInput) return;
7+
const query = pickerInput.value || "";
8+
window.dispatchEvent(
9+
new CustomEvent("vizmat-picker-query", {
10+
detail: {
11+
query,
12+
action,
13+
},
14+
}),
15+
);
16+
};
17+
18+
if (pickerInput) {
19+
window.addEventListener("vizmat-structure-picker-open", () => {
20+
pickerInput.value = "";
21+
try {
22+
pickerInput.focus({ preventScroll: true });
23+
} catch (error) {
24+
pickerInput.focus();
25+
}
26+
emitPickerQuery("change");
27+
});
28+
29+
window.addEventListener("vizmat-structure-picker-close", () => {
30+
pickerInput.blur();
31+
pickerInput.value = "";
32+
});
33+
34+
pickerInput.addEventListener("input", () => emitPickerQuery("change"));
35+
pickerInput.addEventListener("keydown", (event) => {
36+
if (event.key === "Enter") {
37+
event.preventDefault();
38+
emitPickerQuery("submit");
39+
event.stopPropagation();
40+
}
41+
});
42+
}
343

444
const emitTouchGesture = (gesture) => {
545
window.dispatchEvent(

0 commit comments

Comments
 (0)