Skip to content

Instantly share code, notes, and snippets.

@jason-s13r
Last active June 10, 2024 02:29
Show Gist options
  • Save jason-s13r/68a6e8827c50800fbe5edd107487d21f to your computer and use it in GitHub Desktop.
Save jason-s13r/68a6e8827c50800fbe5edd107487d21f to your computer and use it in GitHub Desktop.
Adds a drawing canvas for https://t0.vc/g, allowing literal signing of the guestbook.
((
_state_pens,
$Document,
Points,
Id,
_str_mouse,
_str_touch,
_str_click,
_str_move,
_str_over,
_str_map,
_str_querySelector,
_str_createElement,
_str_addEventListener,
_str_preventDefault,
_canvas_context,
$Canvas,
$Reset,
$TextArea,
XY,
Push,
Dirty,
Start,
Stop,
Move,
Clear,
) => {
$Canvas = $Document[_str_createElement]("canvas");
$Reset = $Document[_str_createElement]("a");
$TextArea = $Document[_str_querySelector]("textarea");
$Document[_str_querySelector]('[name^="web"]').after(
"\n\nDraw (optional):\n",
$Canvas,
$Reset
);
$Canvas.style.border = "solid 1px #000";
$Reset.href = "#";
$Reset.textContent = "Reset";
_canvas_context = $Canvas.getContext("2d");
XY = (p, b) => (
(b = $Canvas.getBoundingClientRect()),
[p.clientX - b.left, p.clientY - b.top]
);
Dirty = () =>
new Uint32Array(
_canvas_context.getImageData(0, 0, $Canvas.width, $Canvas.height).data.buffer
).some((color) => color !== 0);
Start = (event) => (
e[_str_preventDefault](),
Points(event)[_str_map](
(t) =>
(event.type !== _str_mouse + _str_over || event.buttons !== 0) &&
(_state_pens[Id(t)] = XY(t))
)
);
Stop = (event) => (
e[_str_preventDefault](),
Points(event)[_str_map]((t) => (_state_pens[Id(t)] = 0))
);
Move = (event, touches) => {
e[_str_preventDefault]();
touches = event.touches;
Points(event)[_str_map](
(t, from, to) => (
(from = _state_pens[Id(t)]),
from &&
((to = _state_pens[Id(t)] = XY(t)),
(event.type !== _str_mouse + _str_move || event.buttons !== 0) &&
(_canvas_context.beginPath(),
_canvas_context.moveTo(...from),
_canvas_context.lineTo(...to),
_canvas_context.stroke()))
)
);
};
Clear = () => (_canvas_context.reset(), (_state_pens = {}));
Push = () =>
Dirty() &&
$Canvas.toBlob(
async (blob, b) => (
(b = new FormData()),
b.append("pic", blob),
($TextArea.value += `<img src="${(
await (
await fetch("https://pic.t0.vc", {
body: b,
method: "POST",
})
).text()
).trim()}" />`),
Clear()
)
);
[_str_touch + "start", _str_mouse + "down", _str_mouse + _str_over][
_str_map
]((x) => $Canvas[_str_addEventListener](x, Start));
[_str_touch + "stop", _str_touch + "end", _str_mouse + "up"][_str_map](
(x) => $Canvas[_str_addEventListener](x, Stop)
);
[_str_touch, _str_mouse][_str_map]((x) =>
$Canvas[_str_addEventListener](x + _str_move, Move)
);
$TextArea[_str_addEventListener](_str_click, Push);
$Reset[_str_addEventListener](_str_click, Clear);
})(
{},
document,
(e) => Array.from(e.changedTouches || [e]),
(t) => t.identifier || 0,
"mouse",
"touch",
"click",
"move",
"over",
"map",
"querySelector",
"createElement",
"addEventListener",
"preventDefault"
);
const canvas = document.createElement("canvas");
const reset = document.createElement("a");
const textarea = document.querySelector("textarea");
document.querySelector('[name^="web"]').after("\n\nDraw (optional):\n", canvas, reset);
canvas.style.border = "solid 1px #000";
reset.href = "#";
reset.textContent = "Reset";
const ctx = canvas.getContext('2d');
const xy = (p, b) => {
b = canvas.getBoundingClientRect();
return [p.clientX - b.left, p.clientY - b.top];
};
const pens = new Map();
const dirty = () => {
const context = canvas.getContext('2d');
const pixelBuffer = new Uint32Array(
context.getImageData(0, 0, canvas.width, canvas.height).data.buffer
);
return pixelBuffer.some(color => color !== 0);
};
const start = event => {
event.preventDefault();
Array.from(event.changedTouches || [event], t => {
if (event.type === 'mouseover' && event.buttons === 0) {
return;
}
pens.set(t.identifier || 0, xy(t));
});
};
const stop = event => {
event.preventDefault();
Array.from(event.changedTouches || [event], t => {
pens.delete(t.identifier || 0);
});
};
const move = event => {
event.preventDefault();
Array.from(event.changedTouches || [event], t => {
const id = t.identifier || 0;
const start = pens.get(id);
if (!start) {
return;
}
const end = xy(t);
pens.set(id, end);
if (event.type === 'mousemove' && event.buttons === 0) {
return;
}
const shade = (255 * id) % 255;
ctx.beginPath();
ctx.moveTo(...start);
ctx.lineTo(...end);
ctx.strokeColor = `rgb(${[shade, shade, shade].join(',')})`;
ctx.stroke();
});
};
const clear = event => (ctx.reset(), pens.clear());
const push = (event) =>
dirty() &&
canvas.toBlob(async (blob, body) => {
body = new FormData();
body.append("pic", blob);
textarea.value += `<img src="${(
await (
await fetch("https://pic.t0.vc", {
body,
method: "POST",
})
).text()
).trim()}" />`;
clear();
});
canvas.addEventListener("touchstart", start);
canvas.addEventListener("touchstop", stop);
canvas.addEventListener("touchend", stop);
canvas.addEventListener("touchmove", move);
canvas.addEventListener("mousedown", start);
canvas.addEventListener("mouseover", start);
canvas.addEventListener("mouseup", stop);
canvas.addEventListener("mousemove", move);
textarea.addEventListener('click', push);
reset.addEventListener('click', clear);
((t,a,n,o,r,i,c,s,d,l,m,p,u,h,f,g,b,v,w,y,x,D,T,C,k)=>{g=a[p]("canvas"),b=a[p]("a"),v=a[m]("textarea"),a[m]('[name^="web"]').after("\n\nDraw (optional):\n",g,b),g.style.border="solid 1px #000",b.href="#",b.textContent="Reset",f=g.getContext("2d"),w=(e,t)=>(t=g.getBoundingClientRect(),[e.clientX-t.left,e.clientY-t.top]),x=()=>new Uint32Array(f.getImageData(0,0,g.width,g.height).data.buffer).some((e=>0!==e)),D=a=>(e[h](),n(a)[l]((e=>(a.type!==r+d||0!==a.buttons)&&(t[o(e)]=w(e))))),T=a=>(e[h](),n(a)[l]((e=>t[o(e)]=0))),C=(a,i)=>{e[h](),a.touches,n(a)[l](((e,n,i)=>(n=t[o(e)])&&(i=t[o(e)]=w(e),(a.type!==r+s||0!==a.buttons)&&(f.beginPath(),f.moveTo(...n),f.lineTo(...i),f.stroke()))))},k=()=>(f.reset(),t={}),y=()=>x()&&g.toBlob((async(e,t)=>((t=new FormData).append("pic",e),v.value+=`<img src="${(await(await fetch("https://pic.t0.vc",{body:t,method:"POST"})).text()).trim()}" />`,k()))),[i+"start",r+"down",r+d][l]((e=>g[u](e,D))),[i+"stop",i+"end",r+"up"][l]((e=>g[u](e,T))),[i,r][l]((e=>g[u](e+s,C))),v[u](c,y),b[u](c,k)})({},document,(e=>Array.from(e.changedTouches||[e])),(e=>e.identifier||0),"mouse","touch","click","move","over","map","querySelector","createElement","addEventListener","preventDefault");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment