pointer info
by edwardsharp
HTML
<div id="app">
<div id="controls">
<button id="clear">Clear</button>
<button id="toggleLog">Toggle Event Log</button>
<span id="status">Waiting for pointer...</span>
</div>
<div id="testArea">
<div id="crosshair"></div>
<div id="output"></div>
<div id="log"></div>
</div>
</div>
CSS
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: #111;
color: #eee;
font-family:
-apple-system, BlinkMacSystemFont, 'SF Mono', Menlo, Monaco, monospace;
}
body {
overflow: hidden;
}
#app {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
#controls {
flex: 0 0 auto;
padding: 10px;
background: #222;
border-bottom: 1px solid #444;
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
}
button {
font: inherit;
color: white;
background: #444;
border: 1px solid #666;
border-radius: 6px;
padding: 7px 12px;
}
button:active {
background: #666;
}
#status {
color: #aaa;
font-size: 12px;
}
#testArea {
flex: 1 1 auto;
min-height: 0;
/*
* Critical for touch/stylus testing:
* don't let the browser interpret the gesture as scrolling,
* zooming, navigation, etc.
*/
touch-action: none;
position: relative;
overflow: hidden;
background:
linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
background-size: 25px 25px;
}
#crosshair {
position: absolute;
width: 30px;
height: 30px;
margin-left: -15px;
margin-top: -15px;
border: 1px solid #0ff;
border-radius: 50%;
pointer-events: none;
display: none;
}
#crosshair::before,
#crosshair::after {
content: '';
position: absolute;
background: #0ff;
}
#crosshair::before {
width: 1px;
height: 44px;
left: 14px;
top: -8px;
}
#crosshair::after {
width: 44px;
height: 1px;
left: -8px;
top: 14px;
}
#output {
position: absolute;
inset: 10px;
pointer-events: none;
overflow: hidden;
}
.event {
position: absolute;
left: 0;
top: 0;
min-width: 300px;
max-width: min(650px, calc(100vw -...
JavaScript
"use strict";
const testArea = document.getElementById("testArea");
const output = document.getElementById("output");
const log = document.getElementById("log");
const crosshair = document.getElementById("crosshair");
const status = document.getElementById("status");
const MAX_LOG_LINES = 100;
document.getElementById("clear").addEventListener("click", () => {
output.innerHTML = "";
log.innerHTML = "";
status.textContent = "Cleared";
});
document.getElementById("toggleLog").addEventListener("click", () => {
log.hidden = !log.hidden;
});
/*
* Properties defined by PointerEvent / MouseEvent / Event.
*
* We intentionally probe the properties rather than assuming that
* every browser implements every one.
*/
const EVENT_PROPERTIES = [
// Event
[
"Event",
[
"type",
// "timeStamp",
// "bubbles",
// "cancelable",
// "defaultPrevented",
// "isTrusted",
// "composed",
// "eventPhase",
],
],
// Pointer identity
["Pointer", ["pointerId", "pointerType", "isPrimary"]],
// Position
[
"Position",
[
// "clientX",
// "clientY",
// "pageX",
// "pageY",
// "screenX",
// "screenY",
// "offsetX",
// "offsetY",
"movementX",
"movementY",
],
],
// Contact geometry
["Contact Geometry", ["width", "height", "pressure", "tangentialPressure"]],
// Pen orientation
[
"Pen Orientation",
["tiltX", "tiltY", "twist", "altitudeAngle", "azimuthAngle"],
],
// Buttons
["Buttons", ["button", "buttons"]],
// Modifier keys
["Modifier Keys", ["ctrlKey", "shiftKey", "altKey", "metaKey"]],
// Target / capture
["Target", ["target", "currentTarget"]],
];
/*
* These are the Pointer Events we try to observe.
*
* pointerrawupdate is particularly interesting for high-frequency
* stylus input because it can expose updates...