)
}
}
)
(
}
{
)
)
(
)
(
(
{
}
)
(
)
}
)
)
{
(
(
)
)
}
)
(
}

Obfuscated Canvas Commands

  1. const oCan = (
  2.   d = document,
  3.   b = d.body,
  4.   canvas = b.appendChild(document.createElement('canvas')),
  5.   c = canvas.getContext('2d'),
  6.   props = [],
  7.   o = {},
  8.   docs = {},
  9.   cmds = [],
  10.   L,
  11.   k,
  12.   du,
  13.   j,
  14.   draw,
  15.   id
  16. ) => {
  17.   ;(onresize = () => {
  18.     canvas.width = innerWidth
  19.     canvas.height = innerHeight
  20.     if (draw) {
  21.       clearTimeout(id)
  22.       id = setTimeout(() => cmds.forEach(v => draw(v)), 500)
  23.     }
  24.   })()
  25.  
  26.   Object.assign(b.style, { margin: 0, height: '100%' })
  27.  
  28.   // longer way: console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(c)));
  29.   for (let i in c) props.push(i)
  30.  
  31.   // make alphabetical since object keys have
  32.   // no order
  33.   props.sort().map(i => {
  34.     L = i.match(/[A-Z]/)
  35.     k = i[0]
  36.     if (L) k += L[0]
  37.     du = 0
  38.     if (o[k]) {
  39.       j = 0
  40.       while (o[k]) k += i[++j]
  41.     }
  42.  
  43.     o[k] =
  44.       (typeof c[i])[0] == 'f'
  45.         ? (...args) => c[i].apply(c, args)
  46.         : v => (c[i] = v)
  47.     docs[i] = k
  48.   })
  49.  
  50.   console.log('docs:', JSON.stringify(docs, null, 2))
  51.  
  52.   return (draw = (s, cmd, currFn, args = [], part, fn, num) => {
  53.     cmd = s.split(/\s+/)
  54.     cmds.push(s)
  55.     c.save()
  56.     for (let i = 0; i < cmd.length; i++) {
  57.       part = cmd[i]
  58.       fn = o[part]
  59.       if (fn && currFn != fn) {
  60.         currFn && currFn.apply(c, args)
  61.         currFn = fn
  62.         args = []
  63.       } else {
  64.         num = parseFloat(part)
  65.         args.push(!isNaN(num) ? num : part)
  66.       }
  67.     }
  68.     currFn && currFn.apply(c, args)
  69.     c.restore()
  70.   })
  71. }
  72.  
  73. const c = oCan()
  74. // `font` & text not suppoted
  75. // make str a function so resize works?
  76. c(`
  77.   fS #ccc
  78.   fR 0 0 400 ${innerHeight}
  79.   fS blue
  80.   fR 40 0 20 20
  81.   gCl difference
  82.   ro .25
  83.   fR 50 0 30 30
  84.   gCl source-over
  85.   fS rgba(200,100,9)
  86.   fR 100 100 40 40
  87.   `)

I’ve had this idea for a long time, never bothered doing it until now. I wrote it in a semi-golfed style for no reason… Anyway, this lets you write canvas code in a strange obfuscated syntax that looks like this:

  1. c(`
  2.   fS #ccc
  3.   fR 0 0 400 ${innerHeight}
  4.   fS blue
  5.   fR 40 0 20 20
  6.   gCl difference
  7.   ro .25
  8.   fR 50 0 30 30
  9.   gCl source-over
  10.   fS rgba(200,100,9)
  11.   fR 100 100 40 40
  12.   `)

This snippet logs out some JSON that shows all the method aliases for the canvas context.

Creative Coding Auto-Painting

  1. Object.getOwnPropertyNames(Math).map(i => (this[i] = Math[i]))
  2. ;((
  3.   width = innerWidth * 2,
  4.   height = innerHeight * 2,
  5.   cnv = document.body.appendChild(
  6.     Object.assign(document.createElement('canvas'), {
  7.       width,
  8.       height
  9.     })
  10.   ),
  11.   c = cnv.getContext('2d'),
  12.   r = (n = 1) => Math.random() * n,
  13.   NUM = 50,
  14.   f = () => ({
  15.     ax: r(width),
  16.     ay: r(height),
  17.     x: 0,
  18.     y: 0,
  19.     T: r(9),
  20.     R: r(innerWidth * 0.8) + 40,
  21.     t: r(6),
  22.     C: round(r(255)),
  23.     m: r(5) + 1
  24.   }),
  25.   cs,
  26.   sn,
  27.   dx,
  28.   dy,
  29.   ns = [...Array(NUM)].map(f)
  30. ) => {
  31.   Object.assign(cnv.style, {
  32.     transformOrigin: '0 0',
  33.     transform: 'scale(.5)'
  34.   })
  35.   Object.assign(document.body.style, {
  36.     margin: 0,
  37.     padding: 0
  38.   })
  39.  
  40.   const clear = () => {
  41.     c.fillStyle = '#666668'
  42.     c.fillRect(0, 0, width, height)
  43.     c.globalAlpha = 0.5
  44.   }
  45.  
  46.   onresize = () => {
  47.     width = cnv.width = innerWidth * 2
  48.     height = cnv.height = innerHeight * 2
  49.     clear()
  50.   }
  51.  
  52.   clear()
  53.  
  54.   setInterval(() => {
  55.     for (i = 0; i < 30; i++) {
  56.       ns.map((n, i) => {
  57.         with (n) {
  58.           x = ax + R * cos(t)
  59.           y = ay + R * sin(t) * pow(sin(t * 0.5), m)
  60.           c.fillStyle = `rgba(${C},${C},${C},.02)`
  61.           ;(cs = cos(T)), (sn = sin(T)), (dx = x - ax), (dy = y - ay)
  62.           c.fillRect(cs * dx - sn * dy + ax, sn * dx + cs * dy + ay, 50, 50)
  63.           t += 0.1
  64.           R -= 0.01
  65.           if (R < 5) ns[i] = f()
  66.         }
  67.       })
  68.     }
  69.   }, 16)
  70. })()

Speed coded semi-golfed canvas texture. Best if viewed in fullscreen.

Creative Coding Greyscale Circle Texture

  1. const canvas = document.createElement('canvas'),
  2.   c = canvas.getContext('2d');
  3.  
  4. document.body.appendChild(canvas);
  5. document.body.style.margin = 0;
  6.  
  7. function brush() {
  8.   let pnts = [];
  9.   let cx = innerWidth * Math.random(),
  10.     cy = innerHeight * Math.random();
  11.   let x = y = 0;
  12.   let ro = innerWidth / (1 + Math.random() * 2);
  13.   let oro = ro;
  14.   let r2 = innerWidth / (2 + Math.random() * 2);
  15.   let rx = innerWidth / 4;
  16.   let ry = rx;
  17.  
  18.   ro = Math.min(300, ro);
  19.  
  20.   let t = 0;
  21.   let vt = 0.05;
  22.   let wt = 0.05;
  23.   let fric = 0.99;
  24.   let t2 = 0;
  25.   let x2 = 0;
  26.   let y2 = 0;
  27.   let vx2 = 0;
  28.   let vy2 = 0;
  29.   let col = ['black', 'white'][Math.floor(Math.random() * 2)];
  30.   let cc = 0; //[0, 255][Math.floor(Math.random() * 2)];
  31.   let s = 0.05 + Math.random() * 0.25;
  32.  
  33.   function draw() {
  34.     c.save();
  35.     c.translate(cx, cy);
  36.     c.scale(s, s);
  37.     for (let i = 0; i < 50; i++) {
  38.       if (Math.random() < 0.13) {
  39.         vt += Math.random() * 0.1 - 0.05;
  40.       }
  41.       if (Math.random() < 0.13) {
  42.         wt += Math.random() * 0.1 - 0.05;
  43.       }
  44.       vt *= 0.99;
  45.       wt *= 0.98;
  46.       rx += (vt + wt * r2 + ro - rx) / 12;
  47.       ry += (vt + wt * r2 + ro - ry) / 12;
  48.  
  49.       if (Math.random() < 0.001) {
  50.         ro += 100 * Math.sin(t2 / 5);
  51.         if (Math.abs(ro) < 50) ro = 50;
  52.       }
  53.       t2 += 0.01;
  54.       x = rx * Math.cos(t / 10) + y2;
  55.       y = ry * Math.sin(t / 10) + x2;
  56.  
  57.       if (Math.random() < 0.01) {
  58.         vx2 += Math.random() * 0.2 - 0.1;
  59.       }
  60.       if (Math.random() < 0.01) {
  61.         vy2 += Math.random() * 0.2 - 0.1;
  62.       }
  63.  
  64.       vx2 *= fric;
  65.       vy2 *= fric;
  66.  
  67.       x2 += vx2;
  68.       y2 += vy2;
  69.       t += vt;
  70.  
  71.       c.fillStyle = col;
  72.       c.fillRect(x, y, 4, 4);
  73.       pnts.push([x, y]);
  74.  
  75.       if (Math.random() < 0.1) {
  76.         const a = pnts[Math.floor(Math.random() * pnts.length)];
  77.         const b = pnts[Math.floor(Math.random() * pnts.length)];
  78.         c.strokeStyle = `rgba(${cc}, ${cc}, ${cc}, ${Math.random() / 2})`;
  79.         c.beginPath();
  80.         c.moveTo(a[0], a[1]);
  81.         c.lineTo(b[0], b[1]);
  82.         c.stroke();
  83.       }
  84.     }
  85.     c.restore();
  86.   }
  87.   return draw;
  88. }
  89.  
  90. const NUM = 20;
  91. let brushes = [];
  92.  
  93. function resize() {
  94.   canvas.width = innerWidth;
  95.   canvas.height = innerHeight;
  96.   c.fillStyle = 'gray';
  97.   c.fillRect(0, 0, canvas.width, canvas.height);
  98.  
  99.   brushes = [];
  100.   for (let i = 0; i < NUM; i++) {
  101.     brushes.push(brush());
  102.   }
  103. }
  104. addEventListener('resize', resize);
  105. resize();
  106.  
  107. function loop() {
  108.   c.globalAlpha = 1;
  109.   c.fillStyle = 'rgba(155, 155, 155, 0.0018)';
  110.   c.fillRect(0, 0, canvas.width, canvas.height);
  111.   c.globalAlpha = 0.5;
  112.   for (let i = 0; i < brushes.length; i++) {
  113.     brushes[i]();
  114.   }
  115.   requestAnimationFrame(loop);
  116. }
  117. loop();

I learned how to code making things like this in Director Lingo. This speed coded snippet draws some shaky circles and lines. (Make sure to view it in fullscreen).

Save Large Canvas

  1. // https://stackoverflow.com/questions/38781968/problems-downloading-big-filemax-15-mb-on-google-chrome
  2. function dataUriToBlob(dataURI) {
  3.   const binStr = atob(dataURI.split(',')[1]);
  4.   const len = binStr.length;
  5.   const arr = new Uint8Array(len);
  6.   const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
  7.   for (let i = 0; i < len; i++) {
  8.     arr[i] = binStr.charCodeAt(i);
  9.   }
  10.  
  11.   const blob = new Blob([arr], {
  12.     type: mimeString
  13.   });
  14.  
  15.   return URL.createObjectURL(blob);
  16. }
  17.  
  18. const save = document.createElement('a');
  19. save.innerText = 'save this big image';
  20. document.body.appendChild(save);
  21.  
  22. const canvas = document.createElement('canvas');
  23. const c = canvas.getContext('2d');
  24.  
  25. canvas.width = window.innerWidth * 4;
  26. canvas.height = window.innerHeight * 4;
  27. canvas.style.transformOrigin = '0 0';
  28. canvas.style.transform = `scale(0.14)`;
  29. document.body.appendChild(canvas);
  30.  
  31. c.fillStyle = 'black';
  32. c.fillRect(0, 0, canvas.width, canvas.height);
  33.  
  34. const size = Math.max(window.innerWidth, window.innerHeight);
  35.  
  36. // draw some rectangles
  37. c.globalCompositeOperation = 'difference'
  38. for (let i = 0; i < 100; i++) {
  39.   const angle = Math.random() * 180 + 180;
  40.   const color = `hsl(${angle}deg, 50%, 50%)`;
  41.   c.fillStyle = color;
  42.   const width = Math.random() * size + 100;
  43.   const height = Math.random() * size + 100;
  44.   const x = Math.random() * canvas.width - width / 2;
  45.   const y = Math.random() * canvas.height - height / 2;
  46.   c.fillRect(
  47.     x, 
  48.     y, 
  49.     width, 
  50.     height);
  51. }
  52.  
  53. save.download = 'big-image';
  54. save.href = dataUriToBlob(canvas.toDataURL());

Weirdly if you try to save a massive data URI to a file (> 15mb) it will just fail. In order to do this properly, you need to convert to a blob first and then save. I encountered this at some point and learned of the solution from user doppelgreener over at stack overflow. Take a look at the post here.

Wobbling Ball With Canvas

  1. // same as yesterday but with canvas instead of svg
  2. const canvas = document.createElement('canvas'),
  3.       c = canvas.getContext('2d');
  4. document.body.appendChild(canvas);
  5. document.body.style.margin = 0;
  6.  
  7. let w = window.innerWidth,
  8.     h = window.innerHeight,
  9.     x = w / 2,
  10.     y = h / 2,
  11.     vx = vy = dx = dy = 0,
  12.     damp = 0.99, div = 8, ticks = 0, 
  13.     wobbleChance = 0.03,
  14.     startTick = 50;
  15.  
  16. function loop() {
  17.  
  18.   w = window.innerWidth;
  19.   h = window.innerHeight;
  20.   radius = w * 0.05;
  21.   diam = radius * 2;
  22.   diam2x = diam * 2;
  23.  
  24.   if (x > w){
  25.     vx *= -1;
  26.     dx *= -1;
  27.     x = w;
  28.   } else if (x < 0){
  29.     vx *= -1;
  30.     dx *= -1;
  31.     x = 0;
  32.   }
  33.  
  34.   if (y > h) {
  35.     vy *= -1;
  36.     dy *= -1;
  37.     y = h;
  38.   } else if (y < 0) {
  39.     vy *= -1;
  40.     dy *= -1;
  41.     y = 0
  42.   } 
  43.  
  44.   if (
  45.     Math.random() < wobbleChance || 
  46.     ticks === startTick) {
  47.       dx += Math.random() * 10 - 5;
  48.       dy += Math.random() * 10 - 5;
  49.   }
  50.  
  51.   dx *= damp;
  52.   dy *= damp;
  53.  
  54.   vx += (dx - vx) / div;
  55.   vy += (dy - vy) / div;
  56.  
  57.   x += vx;
  58.   y += vy;
  59.  
  60.   // in most cases these days you
  61.   // just clear the whole canvas, but for
  62.   // this example we clear a rectangle around 
  63.   // the circle 
  64.   c.clearRect(
  65.     x - diam, 
  66.     y - diam, 
  67.     diam2x, 
  68.     diam2x
  69.   );
  70.  
  71.   // draw the path
  72.   c.fillStyle = 'red'
  73.   c.beginPath();
  74.   c.arc(x, y, radius, 0, Math.PI * 2, false);
  75.   c.fill();
  76.  
  77.   ticks++;
  78.   window.requestAnimationFrame(loop);
  79. }
  80. loop();
  81.  
  82. function resize() {
  83.   canvas.width = window.innerWidth;
  84.   canvas.height = window.innerHeight;
  85. }
  86. resize();
  87. window.addEventListener('resize', resize);

A wobbling ball with canvas.

snippet.zone ~ 2021-24 /// {s/z}