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

isPowerOfTwo

  1. function isPowerOfTwo(value) {
  2.   return (value & (value - 1)) === 0 && value !== 0;
  3. }
  4.  
  5. for (let i = 0; i < 66; i++) {
  6.   console.log(i, isPowerOfTwo(i));
  7. }

I’ve had the pleasure of using THREE.js quite a bit over the years. The MathUtils file has some great utility functions. This version of isPowerOfTwo comes straight from there. I may post a few more from there in the future…

Lerp

  1. const lerp = (a, b, t) => a + (b - a) * t;
  2.  
  3. console.log(lerp(0, 100, 0.5));
  4. console.log(lerp(0, 100, 0.1));
  5.  
  6. console.log(lerp(50, 100, 0.5));
  7. console.log(lerp(100, 50, 0.5));
  8.  
  9. const c = document.body.appendChild(document.createElement`canvas`)
  10.   .getContext`2d`;
  11. c.canvas.width = c.canvas.height = 100;
  12. c.fillStyle = 'black';
  13. c.fillRect(0, 0, 100, 100);
  14.  
  15. let time = 0;
  16. const loop = () => {
  17.   c.fillStyle = 'rgba(255, 255, 255, .5)';
  18.  
  19.   time += 0.01;
  20.  
  21.   if (time < 1) {
  22.     c.fillRect(lerp(10, 55, time), lerp(10, 90, time), 5, 5);
  23.   }
  24.   window.requestAnimationFrame(loop);
  25. };
  26. loop();

Flower of Life Canvas

  1. ((
  2.   d = document,
  3.   b = d.body,
  4.   rad = (innerWidth * 1.9) / 6,
  5.   theta = 0,
  6.   thetaSpeed = 0.03,
  7.   cx = innerWidth / 4,
  8.   cy = innerHeight / 4,
  9.   ox = 0,
  10.   oy = 0,
  11.   offTheta,
  12.   x, y, ang, step, blur,
  13.   _
  14. ) => {
  15.   Object.assign(b.style, {
  16.     background: 'black',
  17.     margin: 0
  18.   }) 
  19.  
  20.   blur = Object.assign(d.createElement`canvas`, {
  21.     width: innerWidth * 2,
  22.     height: innerHeight * 2
  23.   }).getContext`2d`
  24.  
  25.   with (Math) {
  26.     with (b.appendChild(
  27.       Object.assign(d.createElement`canvas`, {
  28.         width: innerWidth * 2,
  29.         height: innerHeight * 2
  30.       })
  31.     ).getContext`2d`) {
  32.       Object.assign(canvas.style, {
  33.         width: '100%',
  34.         height: '100%'
  35.       })
  36.  
  37.       onresize = () => {
  38.         blur.canvas.width = canvas.width = innerWidth * 2
  39.         blur.canvas.height = canvas.height = innerHeight * 2
  40.         rad = (innerWidth * 2.5) / 6
  41.         cx = innerWidth
  42.         cy = innerHeight
  43.         fillStyle = '#000'
  44.         fillRect(0, 0, canvas.width, canvas.height)
  45.       }
  46.       onresize()
  47.  
  48.       step = (PI * 2) / 6
  49.  
  50.       _ = t => {
  51.         ang = ~~(t / 500) % 7
  52.  
  53.         globalAlpha = 0.23
  54.         fillStyle = '#fff'
  55.  
  56.         if (ang > 0) {
  57.           offTheta = step * ang
  58.           ox = rad * cos(offTheta)
  59.           oy = rad * sin(offTheta)
  60.         } else {
  61.           ox = 0
  62.           oy = 0
  63.         }
  64.  
  65.         for (i = 0; i < 20; i++) {
  66.           x = ox + cx + rad * cos(theta)
  67.           y = oy + cy + rad * sin(theta)
  68.           theta += thetaSpeed
  69.  
  70.           fillRect(x, y, 4, 4)
  71.         }
  72.  
  73.         blur.drawImage(canvas, 0, 0)
  74.  
  75.         globalAlpha = 0.05
  76.         drawImage(blur.canvas, 0, 2)
  77.  
  78.         requestAnimationFrame(_)
  79.       }
  80.       _()
  81.     }
  82.   }
  83. })()

Speed coded animated flower of life on canvas

SVG getScreenCTM

  1. const el = document.body.appendChild(
  2.   document.createElement`div`
  3. );
  4. el.innerHTML = `
  5. <svg width="200" height="200" viewBox="0 0 200 200">
  6.   <rect 
  7.     class="rect"
  8.     transform="translate(50, 50) scale(1.2) rotate(25)"
  9.     fill="purple"
  10.     x="0" y="0" width="50" height="50" />
  11. </svg>
  12. `;
  13.  
  14. const box = document.body.appendChild(
  15.   document.createElement`div`
  16. );
  17.  
  18. Object.assign(box.style, {
  19.   position: 'absolute',
  20.   left: 0, top: 0,
  21.   width: '50px',
  22.   height: '50px',
  23.   transformOrigin: '0 0',
  24.   outline: '5px solid red'
  25. });
  26.  
  27. const rect = document.querySelector('.rect');
  28. const {a, b, c, d, e, f} = rect.getScreenCTM()
  29.  
  30. box.style.transform = `
  31.   matrix(${[a, b, c, d, e, f]})
  32. `;

The transformation matrix of an SVG element can be obtained using getScreenCTM or getCTM. The latter of which will be relative to the SVG coordinate space, vs the coordinate space of the page.

Here we take the matrix data from getScreenCTM and use it on a div to place a border over an SVG rect node. This is great for layering HTML on top of SVG.

// dom // javascript // math // matrix // svg // tricks // ui

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

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