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

valueOf for Shorter Function Calls

  1. r={valueOf:_=>Math.random()}
  2. console.log(+r)
  3. console.log(+r)
  4. console.log(+r)

Use valueOf to shorten function calls. I learned this trick over at stackexchange codegolf here from user cyoce.

Exponential Notation JavaScript

  1. console.log(1e1); // 10
  2. console.log(1e2); // 100
  3. console.log(1e3); // 1000
  4. console.log(1e4); // 10000
  5. console.log(12e3); // 12000

This can be helpful when you need big numbers like 100000.

Responsive Radial Gradient Animation

  1. function rect(x1, y1, x2, y2, col, blur=.1) {
  2.   const dx = x1 - x2;
  3.   const dy = y1 - y2;
  4.   const dist = Math.sqrt(dx * dx + dy * dy);
  5.   return `radial-gradient(circle at ${x1}% ${y1}%, ${col} 0, ${col} ${dist}%, transparent ${dist +
  6.     blur}%)`;
  7. }
  8.  
  9. const NUM = 8; 
  10.  
  11. let rects = [];
  12. const colors = ['rgba(0, 0, 0, 0.2)', 'white', 'black'];
  13.  
  14. let x = 0;
  15. let y = 0;
  16. let t = 8;
  17. function loop() { 
  18.   rects = [];
  19.  
  20.   for (let i = 0; i < NUM; i++) { 
  21.     x = 50 + 30 * Math.sin(t + i / 2);
  22.     y = 50 + 30 * Math.cos(t * 1.5 * i / 10);
  23.     rects.push(rect(x, y, x + 5, y + 5, 'rgba(255, 255, 255, 1)', 1));
  24.     rects.push(rect(x, y, x + 5, y + 5, 'rgba(0, 0, 0, 0.4)', 
  25.       8 + 6 * Math.cos(y / 10)));
  26.   }
  27.   t += .04;
  28.   document.body.style.backgroundImage = rects.join(', ');
  29.   window.requestAnimationFrame(loop);
  30. }
  31. loop()
  32.  
  33. document.body.innerHTML += `
  34.   <style>
  35.     body, html {
  36.       height: 100%;
  37.       background: #ccc;
  38.       margin: 0;
  39.       background-repeat: no-repeat;
  40.       width: 100%;
  41.     }
  42.   </style>
  43. `;

Animated variation on yesterdays post – many animating circles with no divs or canvas, just radial-gradients…

// animation // css // dom // graphics // hacks // javascript // math

Letter Particles With Keyboard

  1. const Key = {
  2.   LEFT: 37,
  3.   UP: 38,
  4.   RIGHT: 39,
  5.   DOWN: 40,
  6.   disabled: false
  7. };
  8.  
  9. const keyDown = {};
  10.  
  11. function setupKeys() {
  12.   const alph = 'abcdefghijklmnopqrstuvwxyz'.split('');
  13.   const keys = {};
  14.   const aKey = 65;
  15.   alph.forEach((letter, i) => {
  16.     const idx = aKey + i;
  17.     keyDown[idx] = false;
  18.     Key[letter.toUpperCase()] = idx;
  19.   });
  20.  
  21.   keyDown.allLetters = () => {
  22.     const lettersDown = alph.filter(
  23.       letter => keyDown[Key[letter.toUpperCase()]]
  24.     );
  25.     return lettersDown;
  26.   };
  27.  
  28.   document.addEventListener('keydown', e => {
  29.     e.preventDefault();
  30.     if (!Key.disabled) {
  31.       keyDown[e.which] = true;
  32.     }
  33.   });
  34.  
  35.   document.addEventListener('keyup', e => {
  36.     e.preventDefault();
  37.     keyDown[e.which] = false;
  38.   });
  39. }
  40.  
  41. setupKeys();
  42.  
  43. // later:
  44.  
  45. const dots = {};
  46. let id = 0;
  47. function dot(letter = '') {
  48.   const el = document.createElement('div');
  49.   el.innerHTML = letter;
  50.   const size = 20;
  51.   const scale = 1 + Math.random() * 2;
  52.   const vel = (2 - scale / 2) / 4;
  53.   let x = innerWidth / 2 - size;
  54.   let y = innerHeight / 2 - size;
  55.   let vx = Math.random() * 6 - 3;
  56.   let vy = Math.random() * 6 - 3;
  57.   let life = 0;
  58.   let maxLife = Math.floor(50 + Math.random() * 30);
  59.   Object.assign(el.style, {
  60.     position: 'absolute',
  61.     left: 0,
  62.     top: 0,
  63.     transform: `translate3d(${x}px, ${y}px)`,
  64.     borderRadius: '500px',
  65.     background: 'red',
  66.     width: `${size}px`,
  67.     fontFamily: 'sans-serif',
  68.     textAlign: 'center',
  69.     color: 'white'
  70.   });
  71.  
  72.   id++;
  73.  
  74.   let props = {
  75.     el,
  76.     id,
  77.     right() {
  78.       vx += vel;
  79.     },
  80.     left() {
  81.       vx -= vel;
  82.     },
  83.     down() {
  84.       vy += vel;
  85.     },
  86.     up() {
  87.       vy -= vel;
  88.     },
  89.     run() {
  90.       life++;
  91.       if (life === maxLife) {
  92.         document.body.removeChild(dots[props.id].el);
  93.         delete dots[props.id];
  94.       }
  95.       x += vx;
  96.       y += vy;
  97.       vx *= 0.999;
  98.       vy *= 0.999;
  99.       el.style.transform = `translate(${x}px, ${y}px) scale(${scale}) `;
  100.     }
  101.   };
  102.   dots[id] = props;
  103.   document.body.appendChild(el);
  104. }
  105.  
  106. function loop() {
  107.   keyDown.allLetters().forEach(letter => {
  108.     dot(letter);
  109.   });
  110.  
  111.   for (let i in dots) {
  112.     dots[i].run();
  113.   }
  114.  
  115.   if (keyDown[Key.LEFT]) {
  116.     for (let i in dots) {
  117.       dots[i].left();
  118.     }
  119.   }
  120.  
  121.   if (keyDown[Key.DOWN]) {
  122.     for (let i in dots) {
  123.       dots[i].down();
  124.     }
  125.   }
  126.  
  127.   if (keyDown[Key.RIGHT]) {
  128.     for (let i in dots) {
  129.       dots[i].right();
  130.     }
  131.   }
  132.  
  133.   if (keyDown[Key.UP]) {
  134.     for (let i in dots) {
  135.       dots[i].up();
  136.     }
  137.   }
  138.  
  139.   requestAnimationFrame(loop);
  140. }
  141. loop();
  142.  
  143. const info = document.createElement('div')
  144. info.innerHTML = 'click here, then type letters and use arrow keys'
  145. document.body.appendChild(info)

A demo showing how to use the keyboard snippet from yesterday. Also added a function to obtain an array of all currently pressed letter keys

// animation // javascript // keys // math // random // tricks // ui

Interesting Color Picker

  1. document.addEventListener('touchmove', e => e.preventDefault(), {
  2.   passive: false
  3. });
  4.  
  5. document.body.innerHTML += `
  6. <style>
  7.   * {
  8.     -moz-user-select: none;
  9.     -webkit-user-select: none;
  10.     -ms-user-select: none;
  11.     user-select: none;
  12.   }
  13.   body {
  14.     background: #333;
  15.   }
  16.   .select-box {
  17.     border: 1px solid white;
  18.     outline: 1px solid black;
  19.   }
  20.   .swatch {
  21.     border: none;
  22.     outline: none;
  23.   }
  24. </style>
  25. `;
  26.  
  27. const col = document.body.appendChild(document.createElement('div'));
  28. Object.assign(col.style, {
  29.   position: 'absolute',
  30.   left: 0,
  31.   top: 0,
  32.   width: '100%',
  33.   height: '200px',
  34.   background:
  35.     `linear-gradient(0, black 0%, transparent 50%, transparent 50%, white 100%), 
  36.      linear-gradient(90deg, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)`
  37. });
  38.  
  39. const swatches = document.body.appendChild(document.createElement('div'));
  40. Object.assign(swatches.style, {
  41.   position: 'absolute',
  42.   top: '200px',
  43.   left: 0,
  44.   width: '100%'
  45. });
  46.  
  47. function box(x, y, cls = 'select-box', parent = document.body) {
  48.   const box = parent.appendChild(document.createElement`div`);
  49.   box.classList.add(cls);
  50.   Object.assign(box.style, {
  51.     position: 'absolute',
  52.     left: `${x}%`,
  53.     top: `${y}px`,
  54.     width: '40px',
  55.     height: '40px',
  56.     background: 'none',
  57.     transform: 'translate(-50%, -50%)',
  58.     cursor: 'pointer',
  59.  
  60.     color: 'white'
  61.   });
  62.   return box;
  63. }
  64.  
  65. function touch(e) {
  66.   let x = e.clientX;
  67.   let y = e.clientY;
  68.   if (e.touches != null && e.touches.length > 0) {
  69.     x = e.touches[0].clientX;
  70.     y = e.touches[0].clientY;
  71.   }
  72.   return { x, y };
  73. }
  74.  
  75. document.addEventListener('touchstart', onDown);
  76. document.addEventListener('touchmove', onMove);
  77. document.addEventListener('touchend', onUp);
  78. document.addEventListener('mousedown', onDown);
  79. document.addEventListener('mousemove', onMove);
  80. document.addEventListener('mouseup', onUp);
  81.  
  82. let down = false;
  83. let currBox;
  84. let currSwatch;
  85. let swatchHeight = 30;
  86. let id = 0;
  87.  
  88. function toHSL(x, y) {
  89.   let deg = x * 360;
  90.   return `hsl(${deg}deg, 100%, ${100 - y / 2}%)`;
  91. }
  92.  
  93. function onDown(e) {
  94.   let { x, y } = touch(e);
  95.   down = true;
  96.   let hPercent = x / innerWidth;
  97.   let color = toHSL(hPercent, y);
  98.   if (e.target.classList.contains('swatch')) {
  99.     e.target.style.outline = '2px solid red';
  100.     e.target.style.zIndex = 999;
  101.     down = false;
  102.     setTimeout(() => {
  103.       if (confirm('Would you like to remove this swatch?')) {
  104.         currBox = document.querySelector(
  105.           `.select-box[data-id="${e.target.dataset.id}"]`
  106.         );
  107.  
  108.         if (currBox != null) {
  109.           currBox.parentNode.removeChild(currBox);
  110.           e.target.parentNode.removeChild(e.target);
  111.         }
  112.       } else {
  113.         e.target.style.outline = null;
  114.         e.target.style.zIndex = null;
  115.       }
  116.     }, 250);
  117.   } else if (e.target.classList.contains('select-box')) {
  118.     currBox = e.target;
  119.     c = document.querySelector(`.swatch[data-id="${currBox.dataset.id}"]`);
  120.   } else {
  121.     currBox = box(hPercent * 100, y);
  122.     currBox.dataset.id = id++;
  123.     currSwatch = box(0, 0, 'swatch', swatches);
  124.     currSwatch.dataset.id = currBox.dataset.id;
  125.     Object.assign(currSwatch.style, {
  126.       width: '100%',
  127.       position: 'relative',
  128.       height: `${swatchHeight}px`,
  129.       transform: 'none',
  130.       background: color
  131.     });
  132.   }
  133. }
  134.  
  135. function onMove(e) {
  136.   if (down) {
  137.     let { x, y } = touch(e);
  138.     let hPercent = x / innerWidth;
  139.     let color = toHSL(hPercent, y);
  140.     Object.assign(currBox.style, {
  141.       left: `${hPercent * 100}%`,
  142.       top: `${y}px`
  143.     });
  144.     currSwatch.style.background = color;
  145.   }
  146. }
  147.  
  148. function onUp(e) {
  149.   down = false;
  150.   currBox = null;
  151. }

Click anywhere on the spectrum to add a color… color boxes can be dragged, color swatches can be deleted by clicking on them…

Just something that popped into my head awhile back so figured I’d do a speed-coded prototype. I’d like to revisit this and add more to it.

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