JSFiddle - React, Tailwind, and code Playground
HTML
<img id="moo" src="data:image/gif;base64,R0lGODlhAQABAPAAAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFMgABACwAAAAAAQABAAACAkwBACH5BAUyAAEALAAAAAABAAEAAAICRAEAOw==" width="2" height="20">
TypeScript
function getCaretGif(r: number, g: number, b: number) {
// original blinky gif data, courtesy of @mrkev, stringified.
// the single non-transparent color in this gif is the first in the color palette,
// so 0xD. the two strings below are gifBytes.substring(0, 0xD) and gifBytes.substring(0x10).
// in other words, everything except the first color in the palette.
const header = "GIF89a\u0001\u0000\u0001\u0000ð\u0000\u0000";
const rest = "ÿÿÿ!ÿ\u000bNETSCAPE2.0\u0003\u0001\u0000\u0000\u0000!ù\u0004\u00052\u0000\u0001\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002L\u0001\u0000!ù\u0004\u00052\u0000\u0001\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0002D\u0001\u0000;"
// it actually made most sense to me to use a Uint8Array for this manipulation, but
// according to my shallow stack overflow and mdn dive, conversion both to
// base64 looks to be a fair bunch of code and memcopying.
//
// thus, we break a bunch of rules and manipulate a gif by converting it into a string
// and then patching a new string together.
const gif = header
+ String.fromCharCode(r)
+ String.fromCharCode(g)
+ String.fromCharCode(b)
+ rest;
return "data:image/gif;base64," + window.btoa(gif);
}
const moo = document.getElementById("moo");
setInterval(() => {
const r = (Math.random() * 255) & 0xFF;
const g = (Math.random() * 255) & 0xFF;
const b = (Math.random() * 255) & 0xFF;
moo.src = getCaretGif(r, g, b);
}, 2000);