PageSourceSearch

https://www.whatismyscreenresolution.org/assets/js/hz.js?v=548220

js whatismyscreenresolution.org collected 2026-10-04 05:34:21 UTC 3,344 bytes, 102 lines download raw bytes

1/* Refresh-rate measurement.
2   Also drives the small live Hz tile on the homepage, so both stay in step.
3
4   Method: time successive animation frames and take the MEDIAN interval.
5   Median, not mean, because a single dropped frame (GC, tab work, a scroll)
6   doubles one interval and would drag an average down hard. */
7(function () {
8  'use strict';
9
10  var out = document.getElementById('hz-value');
11  if (!out) return;
12
13  var sub      = document.getElementById('hz-sub');
14  var barsEl   = document.getElementById('hz-bars');
15  var statEl   = document.getElementById('hz-stats');
16  var WINDOW   = 180;          // frames kept for the rolling estimate
17  var times    = [];
18  var last     = 0;
19  var settled  = false;
20  var history  = [];           // recent Hz readings, for the sparkline
21
22  function median(a) {
23    if (!a.length) return 0;
24    var s = a.slice().sort(function (x, y) { return x - y; });
25    var m = s.length >> 1;
26    return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
27  }
28
29  /* Panels advertise round numbers but run slightly off them (59.94, 143.9).
30     Snap only when we are very close, so a real 75Hz panel is not called 60. */
31  function label(hz) {
32    var common = [24, 30, 48, 50, 60, 75, 90, 100, 120, 144, 165, 240, 360, 480];
33    for (var i = 0; i < common.length; i++) {
34      if (Math.abs(hz - common[i]) < 1.2) return common[i];
35    }
36    return Math.round(hz);
37  }
38
39  function drawBars() {
40    if (!barsEl) return;
41    var n = 40;
42    var slice = history.slice(-n);
43    if (!slice.length) return;
44    var max = Math.max.apply(null, slice);
45    var min = Math.min.apply(null, slice);
46    var span = Math.max(2, max - min);
47    var html = '';
48    for (var i = 0; i < slice.length; i++) {
49      var h = 12 + 88 * ((slice[i] - min) / span);
50      html += '<i style="height:' + h.toFixed(1) + '%"></i>';
51    }
52    barsEl.innerHTML = html;
53  }
54
55  function tick(ts) {
56    if (last) {
57      var dt = ts - last;
58      // Ignore absurd gaps: tab was backgrounded, or the thread stalled.
59      if (dt > 0.5 && dt < 200) {
60        times.push(dt);
61        if (times.length > WINDOW) times.shift();
62      }
63    }
64    last = ts;
65
66    if (times.length >= 12) {
67      var med = median(times);
68      var hz = 1000 / med;
69
70      out.textContent = hz.toFixed(1);
71
72      if (!settled && times.length >= 60) {
73        settled = true;
74        if (sub) sub.textContent = 'Your display is running at about ' + label(hz) + ' Hz.';
75      }
76
77      if (times.length % 6 === 0) {
78        history.push(hz);
79        if (history.length > 120) history.shift();
80        drawBars();
81      }
82
83      if (statEl && times.length % 12 === 0) {
84        var mn = Math.min.apply(null, times), mx = Math.max.apply(null, times);
85        statEl.innerHTML =
86          '<span><b>' + label(hz) + '</b> Hz nominal</span>' +
87          '<span><b>' + med.toFixed(2) + '</b> ms per frame</span>' +
88          '<span><b>' + (1000 / mx).toFixed(1) + '–' + (1000 / mn).toFixed(1) + '</b> Hz range</span>' +
89          '<span><b>' + times.length + '</b> frames sampled</span>';
90      }
91    }
92
93    requestAnimationFrame(tick);
94  }
95
96  requestAnimationFrame(tick);
97
98  // A backgrounded tab throttles rAF hard; drop the stale sample on return.
99  document.addEventListener('visibilitychange', function () {
100    if (!document.hidden) { times = []; last = 0; }
101  });
102})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.