Skip to main content

ink.golf.js

Adds a drawing canvas for https://t0.vc/g, allowing literal signing of the guestbook.

gist link

Attachment Type Size
ink.golf.js text/javascript 3.2KiB
ink.js text/javascript 2.4KiB
ink.min.js text/javascript 1.2KiB

ink.golf.js – text/javascript, 3.2KiB

((
    _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"
);

ink.js – text/javascript, 2.4KiB

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);

ink.min.js – text/javascript, 1.2KiB

((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");