maxm-streaminggif.web.val.run
Readme

An animated gif that streams the current time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { createCanvas, loadImage } from "https://deno.land/x/canvas@v1.4.1/mod.ts";
import GifEncoder from "https://esm.sh/gif-encoder";
import { DateTime } from "https://esm.sh/luxon";
const scale = 0.15;
export default async function(req: Request) {
let timerId: number | undefined;
const body = new ReadableStream({
async start(controller) {
const width = 300;
const height = 300;
const canvas = createCanvas(width, height);
const img = await loadImage("https://static.esm.town/build/_assets/valtown-logotype-blackOnWhite-R2XK5XHC.png");
const encoder = new GifEncoder(width, height);
encoder.setRepeat(0);
encoder.setDelay(20); // 50fps
encoder.on("data", (d) => {
controller.enqueue(d);
});
encoder.writeHeader();
let angle = 0;
console.log(img.height(), img.width());
timerId = setInterval(() => {
const ctx = canvas.getContext("2d");
ctx.fillStyle = "white";
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "black";
ctx.font = "20px Arial";
ctx.save();
ctx.translate(width / 2, (height / 2) + 30);
ctx.rotate(angle);
ctx.scale(scale, scale);
ctx.drawImage(img, -img.width() / 2, -img.height() / 2, img.width(), img.height());
ctx.restore();
angle += 0.02;
const now = DateTime.now().setZone("America/New_York").toFormat("yyyy-LL-dd hh:mm:ss");
ctx.fillText(now, 35, 50);
encoder.addFrame(ctx.getImageData(0, 0, width, height).data);
}, 20);
},
cancel() {
if (typeof timerId === "number") {
clearInterval(timerId);
}
},
});
return new Response(body, {
headers: {
"Content-Type": "image/gif",
},
});
}
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
v32
June 6, 2024