Files

59 lines
2.4 KiB
JavaScript

/* custom pixel cursor — appears only once we know the real pointer position,
so it never flashes at a stale spot on page changes. native cursor is hidden
via CSS (*{cursor:none}). */
(function () {
if (!window.matchMedia("(pointer: fine)").matches) return;
var c = document.createElement("canvas");
c.style.cssText =
"position:fixed;left:0;top:0;pointer-events:none;z-index:9999;" +
"image-rendering:pixelated;will-change:transform;opacity:0;" +
"transform:translate3d(-200px,-200px,0);";
document.body.appendChild(c);
var ctx = c.getContext("2d");
var px = 2;
var art = [
"_BB_______", "BRRB______", "BRRRB_____", "BRRRRB____", "BRRRRRB___",
"BRRRRRRB__", "BRRRRRRB__", "BRRRRSB___", "BRRSRRB___", "_BBBRRB___", "____BBB___"
];
var rows = art.length;
var cols = Math.max.apply(null, art.map(function (r) { return r.length; }));
c.width = cols * px; c.height = rows * px;
c.style.width = cols * px + "px"; c.style.height = rows * px + "px";
art.forEach(function (line, y) {
for (var x = 0; x < line.length; x++) {
var ch = line[x];
if (ch === "B") ctx.fillStyle = "#1a1a1a";
else if (ch === "R") ctx.fillStyle = "#ffffff";
else if (ch === "S") ctx.fillStyle = "#b0b0b0";
else continue;
ctx.fillRect(x * px, y * px, px, px);
}
});
var mx = -200, my = -200, raf = 0, shown = false;
function place() {
raf = 0;
c.style.transform = "translate3d(" + mx + "px," + my + "px,0)";
if (!shown) { shown = true; c.style.opacity = "1"; }
}
function move(e) {
mx = e.clientX; my = e.clientY;
if (!raf) raf = requestAnimationFrame(place);
}
function hide() { shown = false; c.style.opacity = "0"; }
document.addEventListener("mousemove", move, { passive: true });
document.addEventListener("mouseenter", function (e) { mx = e.clientX; my = e.clientY; place(); }, { passive: true });
// hide when the pointer leaves the window or the page is navigating away
document.addEventListener("mouseleave", hide, { passive: true });
window.addEventListener("blur", hide);
window.addEventListener("pagehide", hide);
// over a cross-origin iframe (vimeo, doom) we get no mousemove, so hide ours
// instead of leaving it frozen at the edge; it returns on the next move out
document.addEventListener("mouseover", function (e) {
if (e.target && e.target.tagName === "IFRAME") hide();
}, true);
})();