Home] [About] [Posts] [Resources] [Applets]
dir: Home /
Applets /
canvas api test
published-date: 17 May 2025 09:39 +0700
1{
2
3const canvas = document.getElementById("viewport");
4const ctx = canvas.getContext("2d", {"alpha":false});
5const w = canvas.width;
6const h = canvas.height;
7const pbuf = [0,0,0,0];
8var i=0, j=0, x=0, y=0, rx=0, ry=0;
9
10const _SIN_LK_RES = 128;
11const _SIN_LK = Array.from({length:_SIN_LK_RES+1}, (_, i) => (Math.sin(Math.PI*2*i/_SIN_LK_RES) + 1) / 2);
12const ftoi = (v) => ~~v;
13const sin01 = (v) => _SIN_LK[ftoi((v%1)*_SIN_LK_RES)];
14
15
16function cTimer () {
17 this.f = 0;
18 this.fps = 0;
19 this.t = 0;
20 this.pt = 0;
21 this.dt = 0;
22 this.update = () => {
23 this.f += 1;
24 this.t = Date.now();
25 this.dt = this.t - this.pt;
26 this.pt = this.t;
27 this.fps = this.dt > 0 ? ftoi(1 / this.dt * 1000) : NaN;
28 }
29 this.progress = (n_loop) => this.f % n_loop / Math.max(n_loop-1, 1)
30}
31const timer = new cTimer();
32
33
34function cInputElementValuesProxy () {
35 this.values = {};
36 this.target = {};
37 this.display = {};
38 this.register = (name, _default=null, cast=(v)=>v) => {
39 this.values[name] = null;
40 this.target[name] = document.getElementById(name);
41 this.display[name] = this.target[name].parentElement.querySelector("#" + name + "_value");
42
43 this.target[name].addEventListener("input", (event) => {
44 this.values[name] = cast(event.target.value);
45 if (this.display[name] !== null) {
46 this.display[name].innerHTML = "" + event.target.value;
47 }
48 });
49
50 if (_default !== null) {
51 this.target[name].value = _default;
52 this.values[name] = cast(_default);
53 this.display[name].innerHTML = "" + _default;
54 }
55 };
56}
57const p_inputs = new cInputElementValuesProxy();
58p_inputs.register("loop", 100, parseInt);
59
60
61function evalData(x, y) {
62 rx = x/w;
63 ry = y/h/2;
64 rf = timer.progress(p_inputs.values.loop);
65 pbuf[0] = ftoi(255 * sin01((rx*1 + ry*.2 + rf+1)));
66 pbuf[1] = ftoi(255 * sin01((rx*1 + ry*.6 + rf*3)));
67 pbuf[2] = ftoi(255 * sin01((rx*1 + ry*2 + rf*2)));
68 pbuf[3] = 255;
69}
70
71
72function init() {
73 ctx.fillStyle = "black";
74 timer.update();
75 canvasClear();
76 window.requestAnimationFrame(update);
77}
78
79
80function canvasClear() {
81 ctx.save();
82 ctx.clearRect(0,0,w,h);
83 ctx.fillStyle = "white";
84 ctx.fillRect(0,0,w,h);
85 ctx.restore();
86}
87
88
89function canvasDraw() {
90 const imd = ctx.getImageData(0,0,w,h);
91 for (i=0; i<imd.data.length; i+=4) {
92 x = i/4 % w;
93 y = Math.floor(i/4/w);
94 evalData(x, y);
95 for (j=0; j<4;j+=1) {
96 imd.data[i+j] = pbuf[j];
97 }
98 }
99 ctx.putImageData(imd, 0, 0);
100}
101
102
103function canvasDrawInfo() {
104 const iw = 130;
105 ctx.save();
106 ctx.fillStyle = "black";
107 ctx.fillRect(w-iw, h-16, iw, 16);
108 ctx.fillStyle = "white";
109 ctx.font = "12px monospace";
110 ctx.textBaseline = "middle";
111 ctx.fillText(timer.dt + "ms", w-iw+4, h-7);
112 ctx.fillText("fps:" + timer.fps, w-iw+44, h-7);
113 ctx.fillText(timer.f % p_inputs.values.loop, w-iw+96, h-7);
114 ctx.restore();
115}
116
117
118function update() {
119 timer.update();
120 canvasDraw();
121 canvasDrawInfo();
122 window.requestAnimationFrame(update);
123}
124
125init();
126
127}
Built with Hugo | previoip (c) 2025