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

Wiggly Line on Canvas 2

  1. const canvas = document.body.appendChild(
  2.   document.createElement('canvas')
  3. );
  4. const c = canvas.getContext('2d');
  5. document.body.style.margin = 0;
  6.  
  7. function resize() {
  8.   canvas.width = innerWidth * 2;
  9.   canvas.height = innerHeight * 2;
  10.   canvas.style.width = innerWidth + 'px';
  11.   canvas.style.height = innerHeight + 'px';
  12. }
  13. addEventListener('resize', resize);
  14. resize();
  15.  
  16. const PAD = 50;
  17. const RAD = 2;
  18. const SPEED = 200;
  19. const TWO_PI = Math.PI * 2;
  20.  
  21. let mode = 'draw';
  22.  
  23. let t = Math.random() * TWO_PI, 
  24.     x = canvas.width / 2, 
  25.     y = canvas.height / 2,
  26.     vx = 0, vy = 0, ta = 0;
  27.  
  28. let solid = false;
  29. let dotMod = 3;
  30. function loop() {
  31.   if (Math.random() < .01) solid = !solid;
  32.   if (Math.random() < .01) dotMod = [2, 3, 6][Math.floor(Math.random() * 3)]
  33.  
  34.   for (var i = 0; i < SPEED; i++) {
  35.     t = Math.sin(ta) * TWO_PI;
  36.     vx = RAD * Math.cos(t);
  37.     vy = RAD * Math.sin(t);
  38.     ta += Math.random() * 0.1 - 0.05;
  39.     x += vx;
  40.     y += vy;
  41.  
  42.     if (Math.random() < 0.005) {
  43.       mode = 'no draw';
  44.     } else if (Math.random() < 0.005) {
  45.       mode = 'draw';
  46.     }
  47.  
  48.     if (mode === 'draw' && (solid || i % dotMod === 0)) {
  49.       c.fillStyle = 'black';
  50.       c.fillRect(x, y, 2, 2);
  51.     }
  52.  
  53.     if (x < -PAD) {
  54.       x = canvas.width + PAD;
  55.     } else if (x > canvas.width + PAD) {
  56.       x = -PAD;
  57.     }
  58.     if (y < -PAD) {
  59.       y = canvas.height + PAD;
  60.     } else if (y > canvas.height + PAD) {
  61.       y = -PAD;
  62.     }
  63.   }
  64.  
  65.   requestAnimationFrame(loop);
  66. }
  67. loop();

This is a variation on a post from awhile back. I was posting it over on dev.to and realized I wanted it to look a bit different.

Canvas Particle

  1. const canvas = document.createElement('canvas'),
  2.   c = canvas.getContext('2d');
  3.  
  4. canvas.width = 500;
  5. canvas.height = 500;
  6.  
  7. document.body.appendChild(canvas);
  8.  
  9. c.fillStyle = 'black';
  10. c.fillRect(0, 0, canvas.width, canvas.height);
  11.  
  12. let a = 0.29, b = 0.22;
  13.  
  14. function f(x, y) {
  15.   if (Math.random() < 0.001) b = Math.random();
  16.   return Math.cos((x + Math.sin(x) * 0.01 + Math.cos(x * a)) * b);
  17. }
  18.  
  19. let x = 1, y = 0;
  20.  
  21. setInterval(() => {
  22.   if (Math.random() < 0.03) {
  23.     x = 1;
  24.     y = 0;
  25.   }
  26.   if (Math.random() < 0.001) a = Math.random();
  27.   for (let i = 0; i < 1e3; i++) {
  28.     x = x + f(y);
  29.     y = y + f(x);
  30.     c.save();
  31.     c.translate(150, 250);
  32.     c.scale(0.5, 0.5);
  33.     c.fillStyle = 'rgba(255, 255, 255, 0.01)';
  34.     c.fillRect(x, y, 5, 5);
  35.     c.restore();
  36.   }
  37. }, 20);

A single particle moves around and leaves a trail

Some Boxes

  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 resize() {
  8.   canvas.width = innerWidth;
  9.   canvas.height = innerHeight;
  10.   c.fillStyle = '#ccc';
  11.   c.fillRect(0, 0, canvas.width, canvas.height);
  12. }
  13. resize();
  14. addEventListener('resize', resize);
  15.  
  16. const cols = ['#555', 'white', 'gray', '#a4c3eb', '#75879e'];
  17.  
  18. const getCol = () => cols[Math.floor(Math.random() * cols.length)];
  19.  
  20. function rect() {
  21.   let x = Math.random() * innerWidth;
  22.   let y = Math.random() * innerHeight;
  23.   let dx = x;
  24.   let dy = y;
  25.   let size = Math.min(innerWidth, innerHeight);
  26.   let width = size * Math.random() * Math.random() + 30;
  27.   let height = size * Math.random() * Math.random() + 30;
  28.   let halfWidth = width / 2;
  29.   let halfHeight = height / 2;
  30.   let col = getCol();
  31.   let damp = 5 + Math.random() * 70;
  32.   let alpha = 0.2 + Math.random() * 0.4;
  33.  
  34.   function move() {
  35.     if (Math.random() < 0.5) {
  36.       dy = y;
  37.       dx += Math.random() * Math.random() * size - size / 2;
  38.     } else {
  39.       dx = x;
  40.       dy += Math.random() * Math.random() * size - size / 2;
  41.     }
  42.   }
  43.  
  44.   return () => {
  45.     if (Math.random() < 0.01) {
  46.       move();
  47.     }
  48.  
  49.     if (x < halfWidth) {
  50.       dx = innerWidth - width;
  51.     }
  52.  
  53.     if (y < halfHeight) {
  54.       dy = innerHeight - height;
  55.     }
  56.  
  57.     if (x > innerWidth + halfWidth) {
  58.       dx = width;
  59.     }
  60.  
  61.     if (y > innerHeight + halfHeight) {
  62.       dy = height;
  63.     }
  64.  
  65.     x += (dx - x) / damp;
  66.     y += (dy - y) / damp;
  67.  
  68.     c.globalAlpha = alpha;
  69.     c.fillStyle = col;
  70.     c.fillRect(x - halfWidth, y - halfHeight, width, height);
  71.   };
  72. }
  73.  
  74. let rects = [];
  75. let NUM = 30;
  76. for (let i = 0; i < NUM; i++) {
  77.   rects.push(rect());
  78. }
  79.  
  80. function loop() {
  81.   c.globalCompositeOperation = 'source-over';
  82.   c.globalAlpha = 0.01;
  83.   c.fillStyle = '#ccc';
  84.   c.fillRect(0, 0, canvas.width, canvas.height);
  85.  
  86.   c.globalCompositeOperation = 'hard-light';
  87.   for (let i = 0; i < NUM; i++) {
  88.     rects[i]();
  89.   }
  90.   requestAnimationFrame(loop);
  91. }
  92. loop();

Extremely Golfed Canvas

  1. d = document
  2. b = d.body
  3. with(
  4.   b.appendChild(Object.assign(
  5.   d.createElement`canvas`, { width: 100, height: 100 })
  6.   ).getContext`2d`) {
  7.  
  8.   fillStyle = 'red'
  9.   fillRect(5, 5, 20, 20)
  10. }
  11.  
  12. // slightly more complex example
  13. with(
  14.   b.appendChild(Object.assign(
  15.   d.createElement`canvas`, { width: 200, height: 200 })
  16.   ).getContext`2d`) {
  17.  
  18.   fillStyle = '#555', strokeStyle = '#fff', fillRect(0, 0, 200, 200)
  19.   for (i = 0; i < 10; i++) 
  20.     beginPath(), moveTo(20, 20), lineTo(i * 20 + 10, 190), stroke()
  21. }

Easy way to write canvas stuff with very little boilerplate code. with doesn’t work in strict mode.

Cistercian Numerals (semi-golfed)

  1. N = -1
  2. S = 30
  3. H = 90
  4. h = 45
  5. d = document
  6. b = d.body
  7. m = _ => d.createElement(_)
  8. a = _ => b.appendChild(_)
  9.  
  10. with(a(
  11.     Object.assign(
  12.       m`canvas`,
  13.       { width: 80, height: 120 }
  14.     )
  15.   ).getContext`2d`
  16. ) { 
  17.   a(m`br`)
  18.  
  19.   L = (a, b, C, d) => {
  20.     moveTo(a, b)
  21.     lineTo(C, d)
  22.   }
  23.  
  24.   M = _ => L(0, 0, 0, H)
  25.   O = _ => L(0, 0, S, 0)
  26.   W = _ => L(0, S, S, S)
  27.   T = _ => L(0, 0, S, S)
  28.   F = _ => L(0, S, S, 0)
  29.   X = _ => L(S, 0, S, S)
  30.  
  31.   D = [
  32.     _ => {},
  33.     O, W, T, F, 
  34.     [O,F],
  35.     X,
  36.     [O,X],
  37.     [W,X],
  38.     [O,W,X]
  39.   ]
  40.  
  41.   n = s => {
  42.     [...s].reverse().map((l, i) => {
  43.       save()
  44.       translate(S+9, h+9)
  45.       scale(N**i, N**~~(i/2))
  46.       translate(0, -h)
  47.       M() ;[D[l]].flat().map(x => x && x())
  48.       restore()
  49.     })
  50.   }
  51.  
  52.   a(m`input`).oninput = e => {
  53.     clearRect(0, 0, 80, 120)
  54.     beginPath()
  55.     n(~~e.target.value+'')
  56.     stroke()
  57.   }
  58. }

Type any number from 0-9999 into the input field and see the corresponding Cistercian Numeral. This snippet is partially golfed, I left the canvas commands intact to make things a bit easier to understand.

Simpler SVG Version

This one hardcodes all numbers 0-9 as paths, unlike the canvas version which only defines 1,2,3,4 and 6 as paths and then combines them to create 5,7,8 and 9.

  1. h='innerHTML'
  2. C='children'
  3.  
  4. document.body[h]=`
  5. <svg id=G width=99 viewBox="0 0 80 120" 
  6.   style="stroke:black;fill:none;overflow:visible">
  7.   <g transform="translate(30,2)">
  8.     <path d="M0 0L 30 0"/>
  9.     <path d="M0 30L 30 30"/>
  10.     <path d="M0 0L 30 30"/>
  11.     <path d="M0 30L30 0"/>
  12.     <path d="M0 30L30 0 0 0"/>
  13.     <path d="M30 0L30 30"/>
  14.     <path d="M30 30L30 0 0 0"/>
  15.     <path d="M0 30L30 30 30 0"/>
  16.     <path d="M0 30L30 30 30 0 0 0"/>
  17.   </g>
  18.   <g transform=translate(30,2)scale(-1,1)></g>
  19.   <g transform=translate(30,92)scale(1,-1)></g>
  20.   <g transform=translate(30,92)scale(-1,-1)></g>
  21.   <path id=m d="M 30 2 L 30 92"/>
  22. </svg>
  23. <style>path:not(#m){opacity:0}</style><br>
  24. <input id=I>`
  25.  
  26. c=G[C]
  27. p=c[0][h] 
  28.  
  29. n = s => 
  30.   [...s].reverse().map((l, i) => 
  31.    l-1>-1 && (c[i][C][l-1].style.opacity=1))
  32.  
  33. I.oninput = e => {
  34.   for(i=0;i<4;i++)c[i][h]=p
  35.   n(~~e.target.value+'')
  36. }
snippet.zone ~ 2021-24 /// {s/z}