Raw (unaccelerated) pointer-lock mouse input and jump-delta filter for Web 3D games.
Fixes the sudden view / crosshair jumps in browser games that use the Pointer Lock API (Eaglercraft, krunker, three.js FPS demos, and similar) — without touching the game's code.
▶ Usage · npm · Configuration · How it works
Camera spin-outs under pointer lock are caused by three well-known issues:
| Cause | Description | Fix |
|---|---|---|
| OS mouse acceleration | Locking without options delivers accelerated values, so fast movement over-rotates the camera | Inject unadjustedMovement: true |
| High-polling-rate mice | Chromium (Windows) with 500–1000 Hz mice randomly spikes movementX/Y (e.g. 1 → 627) | Velocity spike filter |
| Lock re-acquire / tab resume | A single huge delta arrives right after (re)lock and tab focus return | Recovery window (120 ms) + stall detection (250 ms) |
pjfix is a zero-install CLI: if you have Node installed, it downloads and runs
automatically. Point it at the folder that contains your game HTML files:
npx -y pjfix # inject into all *.html in the current directory
cd E:\games && npx -y pjfix # go to your game folder first, then run itEach targeted file gets a *.orig backup automatically — nothing is ever lost:
npx -y pjfix # patch all *.html in the current dir (backs up as *.orig)
npx -y pjfix a.html b.html # only these files
npx -y pjfix --root .. # target the parent directory instead
npx -y pjfix --unpatch # restore the original files from *.orig
npx -y pjfix --help # show all options
npx -y pjfix --version # print the versionWorks when opened via file://. Re-running updates the fix in place; --unpatch
restores the originals any time.
- Requires: Node.js 18+. If you don't have Node, use the userscript (B) or the
one-line
<script>include (C) instead.
Paste pointer-jump-fix.user.js as a new script. Narrow the @match lines to limit targets.
<script src="pointer-jump-fix.js"></script>Define window.__PLFIX__ before the script runs to override defaults
(in the userscript put it before the CORE marker).
window.__PLFIX__ = {
unadjustedMovement: true, // inject { unadjustedMovement: true } into requestPointerLock
clampEnabled: true, // absolute-delta safety limiter
maxDelta: 0, // 0 = auto (larger screen edge ×2)
recoverMs: 120, // recovery window after lock/focus re-acquire (ms)
stallMs: 250, // zero the first delta after an inactivity longer than this (ms)
spikeFloor: 256, // min delta (px) to be considered a spike
spikeRatio: 6, // reject deltas above this multiple of the recent average (flicks pass)
spikeMaxGapMs: 64, // max event gap for a spike verdict (ms)
resetOnRelock: true, // recovery window on pointerlockchange / pointerlockerror
resetOnFocus: true, // recovery window on focus / visibilitychange
autoRelock: false, // click to re-lock after Esc
relockGraceMs: 1500, // auto-re-lock grace period after Esc (ms)
debug: false // log activity to the console
};window.__PLFIX__stats exposes hit counters for every filter:
__PLFIX__stats.clamped() // events zeroed by the absolute limiter
__PLFIX__stats.spiked() // events zeroed by the spike filter
__PLFIX__stats.stalled() // events zeroed by stall recovery
__PLFIX__stats.recovered() // events zeroed inside the recovery window
__PLFIX__stats.rawLocks() // requestPointerLock calls with injected raw input
__PLFIX__stats.config // active configurationnpm test # core + CLI self-tests (Node only)
node cli.mjs --help # CLI reference
npm pack --dry-run # preview the publish contents| File | Purpose |
|---|---|
pointer-jump-fix.js |
Core (HTML injection / console) |
lib.mjs |
Shared inject / restore / build logic |
cli.mjs |
CLI (also the npm bin entry) |
pointer-jump-fix.user.js |
Tampermonkey / Violentmonkey userscript (synced from core) |
test/ |
Core and CLI test suites (npm test) |
- No effect on games or pages that do not use Pointer Lock.
- To run the userscript on
file://pages, enable "Allow access to file URLs" in the userscript manager settings. - A Chrome extension with the same core lives in a separate folder / repository (not part of this package).
- Use at your own risk if game terms of service prohibit modifications.