I have an element with a \"pointerMove\" EventListener added to it. Now when moving my mouse around, I can measure the number of data points \"pointerMove\" delivers per sec
Specs now encourage browser vendors to threshold most UI Events in order to improve performances.
For instance you can find such a notice in mousemove UI-Event specs:
Implementations are encouraged to determine the optimal frequency rate to balance responsiveness with performance.
And about the same in PointerEvents' pointermove specs drafts
These events may be coalesced or aligned to animation frame callbacks based on UA decision.
In the facts, both Firefox and Chrome do currently coalesce these events in animation frame callback (that is in Chrome it's actually aligned on your monitor's refresh rate, in FF it's currently 60FPS).
This also means that for pointermove we can retrieve all these events using the PointerEvent.getCoalescedEvents method.
const canvas = document.getElementById("canvas");
let
count = 0,
start = 0;
const opts = {passive: true};
canvas.addEventListener("pointerdown", pointerdown, opts);
canvas.addEventListener("pointermove", pointermove, opts);
canvas.addEventListener("pointerup", pointerup, opts);
canvas.addEventListener("touchstart", prevent);
canvas.addEventListener("touchmove", prevent);
function pointermove(event) {
if(canvas.hasPointerCapture(event.pointerId)) {
const coalesced = event.getCoalescedEvents();
count += coalesced.length;
points.push(...coalesced);
draw();
}
}
function pointerdown(event) {
canvas.setPointerCapture(event.pointerId);
count = 1;
start = new Date().getTime();
points.length = 0;
}
function pointerup(event) {
if(canvas.hasPointerCapture(event.pointerId)) {
canvas.releasePointerCapture(event.pointerId);
count++;
const PPS = (count / (new Date().getTime() - start) * 1000);
log.textContent = PPS + "pps";
}
}
// just to show we have real Events
const ctx = canvas.getContext('2d');
const points = [];
function draw() {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
points.forEach(evt => {
ctx.lineTo(evt.offsetX, evt.offsetY);
});
ctx.stroke();
}
// prevent default touch events or pointer ones are discarded
function prevent(evt) {
evt.preventDefault();
}
#canvas {
border: 1px solid;
}
<pre id="log"></pre>
<canvas id="canvas" width="2000" heigth="2000"></canvas>
Note that in Chrome these Events do have their own timestamp
, so you can know when they should have fired, but in Firefox this property is set to 0
...
However, a pointerrawupdate event is coming in the drafts and is already available in Chrome under the Experimental Web Platform features flag.
This event will not be aligned to animation frames and instead will fire "as soon as possible".
if(!('onpointerrawupdate' in window)) {
console.error("Your browser doesn't support 'pointerrawupdate' event. You may need to toggle some config flags");
}
else {
const canvas = document.getElementById("canvas");
let
count = 0,
start = 0;
const opts = {passive: true};
canvas.addEventListener("pointerdown", pointerdown, opts);
canvas.addEventListener("pointerrawupdate", pointermove, opts);
canvas.addEventListener("pointerup", pointerup, opts);
function pointermove(event) {
if(canvas.hasPointerCapture(event.pointerId)) {
const coalesced = event.getCoalescedEvents();
count += coalesced.length;
}
}
function pointerdown(event) {
canvas.setPointerCapture(event.pointerId);
count = 1;
start = new Date().getTime();
}
function pointerup(event) {
if(canvas.hasPointerCapture(event.pointerId)) {
canvas.releasePointerCapture(event.pointerId);
count++;
const PPS = (count / (new Date().getTime() - start) * 1000);
log.textContent = PPS + "pps";
}
}
// Removed the drawing part because drawing should be made in animation frames
}
#canvas {
border: 1px solid;
}
<pre id="log"></pre>
<canvas id="canvas" width="2000" heigth="2000"></canvas>
But in your case (a drawing app) you'd be better to stick with getCoalescedEvents
since your drawings should anyway happen only in animation frames.
Ps: about why the threshold is deactivated when dev-tools are open, that's probably a browser bug.