Skip to content

Commit f7c7924

Browse files
sudomakeinstallfinetjul
authored andcommitted
docs: Create MouseEvent example
1 parent 3b54de3 commit f7c7924

1 file changed

Lines changed: 210 additions & 0 deletions

File tree

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
import '@kitware/vtk.js/favicon';
2+
3+
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
4+
5+
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
6+
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
7+
import vtkConeSource from '@kitware/vtk.js/Filters/Sources/ConeSource';
8+
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
9+
10+
// ----------------------------------------------------------------------------
11+
// Standard rendering code setup
12+
// ----------------------------------------------------------------------------
13+
14+
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
15+
const renderer = fullScreenRenderer.getRenderer();
16+
const renderWindow = fullScreenRenderer.getRenderWindow();
17+
const interactor = renderWindow.getInteractor();
18+
19+
const coneSource = vtkConeSource.newInstance();
20+
const mapper = vtkMapper.newInstance();
21+
mapper.setInputConnection(coneSource.getOutputPort());
22+
const actor = vtkActor.newInstance();
23+
actor.setMapper(mapper);
24+
renderer.addActor(actor);
25+
renderer.resetCamera();
26+
renderWindow.render();
27+
28+
fullScreenRenderer
29+
.getContainer()
30+
.addEventListener('contextmenu', (e) => e.preventDefault());
31+
32+
// ----------------------------------------------------------------------------
33+
// Event log UI
34+
// ----------------------------------------------------------------------------
35+
36+
const panel = document.createElement('div');
37+
Object.assign(panel.style, {
38+
position: 'absolute',
39+
top: '8px',
40+
right: '8px',
41+
width: '320px',
42+
maxHeight: 'calc(100vh - 16px)',
43+
background: 'rgba(0, 0, 0, 0.75)',
44+
color: '#e0e0e0',
45+
fontFamily: 'monospace',
46+
fontSize: '12px',
47+
borderRadius: '6px',
48+
overflow: 'hidden',
49+
display: 'flex',
50+
flexDirection: 'column',
51+
zIndex: '100',
52+
});
53+
document.body.appendChild(panel);
54+
55+
// Header
56+
const header = document.createElement('div');
57+
Object.assign(header.style, {
58+
padding: '8px 12px',
59+
borderBottom: '1px solid #444',
60+
fontSize: '13px',
61+
fontWeight: 'bold',
62+
});
63+
header.textContent = 'Mouse Events';
64+
panel.appendChild(header);
65+
66+
// Instructions
67+
const instructions = document.createElement('div');
68+
Object.assign(instructions.style, {
69+
padding: '8px 12px',
70+
fontSize: '11px',
71+
color: '#999',
72+
lineHeight: '1.5',
73+
borderBottom: '1px solid #333',
74+
});
75+
instructions.textContent =
76+
'Click in the 3D view with mouse buttons. Hold one button and press ' +
77+
'another to test chorded button detection. All press/release events ' +
78+
'should appear in the log.';
79+
panel.appendChild(instructions);
80+
81+
// Button state indicators
82+
const indicators = document.createElement('div');
83+
Object.assign(indicators.style, {
84+
display: 'flex',
85+
gap: '8px',
86+
padding: '8px 12px',
87+
borderBottom: '1px solid #333',
88+
});
89+
panel.appendChild(indicators);
90+
91+
const buttonState = { left: false, middle: false, right: false };
92+
const indElements = {};
93+
94+
['left', 'middle', 'right'].forEach((name) => {
95+
const el = document.createElement('span');
96+
Object.assign(el.style, {
97+
padding: '4px 12px',
98+
borderRadius: '4px',
99+
background: '#333',
100+
transition: 'background 0.1s',
101+
});
102+
el.textContent = name.charAt(0).toUpperCase() + name.slice(1);
103+
indicators.appendChild(el);
104+
indElements[name] = el;
105+
});
106+
107+
function updateIndicators() {
108+
Object.entries(buttonState).forEach(([name, active]) => {
109+
indElements[name].style.background = active ? '#e94560' : '#333';
110+
});
111+
}
112+
113+
// Controls
114+
const controls = document.createElement('div');
115+
Object.assign(controls.style, {
116+
display: 'flex',
117+
gap: '8px',
118+
alignItems: 'center',
119+
padding: '8px 12px',
120+
});
121+
panel.appendChild(controls);
122+
123+
const clearBtn = document.createElement('button');
124+
clearBtn.textContent = 'Clear Log';
125+
controls.appendChild(clearBtn);
126+
127+
const moveLabel = document.createElement('label');
128+
Object.assign(moveLabel.style, { fontSize: '11px', cursor: 'pointer' });
129+
const moveCheckbox = document.createElement('input');
130+
moveCheckbox.type = 'checkbox';
131+
moveLabel.appendChild(moveCheckbox);
132+
moveLabel.append(' Log MouseMove');
133+
controls.appendChild(moveLabel);
134+
135+
// Event log
136+
const log = document.createElement('div');
137+
Object.assign(log.style, {
138+
flex: '1',
139+
overflowY: 'auto',
140+
padding: '4px 12px',
141+
lineHeight: '1.6',
142+
});
143+
panel.appendChild(log);
144+
145+
let eventCount = 0;
146+
147+
function logEvent(name, color) {
148+
eventCount++;
149+
const entry = document.createElement('div');
150+
entry.style.color = color;
151+
entry.textContent = `${String(eventCount).padStart(4, ' ')} ${name}`;
152+
log.appendChild(entry);
153+
log.scrollTop = log.scrollHeight;
154+
}
155+
156+
clearBtn.addEventListener('click', () => {
157+
log.replaceChildren();
158+
eventCount = 0;
159+
});
160+
161+
// ----------------------------------------------------------------------------
162+
// Subscribe to interactor events
163+
// ----------------------------------------------------------------------------
164+
165+
interactor.onLeftButtonPress(() => {
166+
buttonState.left = true;
167+
updateIndicators();
168+
logEvent('LeftButtonPress', '#53d769');
169+
});
170+
interactor.onLeftButtonRelease(() => {
171+
buttonState.left = false;
172+
updateIndicators();
173+
logEvent('LeftButtonRelease', '#fc3d39');
174+
});
175+
176+
interactor.onMiddleButtonPress(() => {
177+
buttonState.middle = true;
178+
updateIndicators();
179+
logEvent('MiddleButtonPress', '#53d769');
180+
});
181+
interactor.onMiddleButtonRelease(() => {
182+
buttonState.middle = false;
183+
updateIndicators();
184+
logEvent('MiddleButtonRelease', '#fc3d39');
185+
});
186+
187+
interactor.onRightButtonPress(() => {
188+
buttonState.right = true;
189+
updateIndicators();
190+
logEvent('RightButtonPress', '#53d769');
191+
});
192+
interactor.onRightButtonRelease(() => {
193+
buttonState.right = false;
194+
updateIndicators();
195+
logEvent('RightButtonRelease', '#fc3d39');
196+
});
197+
198+
interactor.onMouseMove(() => {
199+
if (moveCheckbox.checked) {
200+
logEvent('MouseMove', '#888');
201+
}
202+
});
203+
204+
// ----------------------------------------------------------------------------
205+
// Globals for debugging
206+
// ----------------------------------------------------------------------------
207+
208+
global.interactor = interactor;
209+
global.renderWindow = renderWindow;
210+
global.renderer = renderer;

0 commit comments

Comments
 (0)