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

Pass a Class

  1. function callMethods(evt) {
  2.   const e = new evt
  3.   e.one()
  4.   e.two()
  5. }
  6.  
  7. callMethods(class {
  8.   one() {
  9.     console.log('one')
  10.   }
  11.  
  12.   two() {
  13.     console.log('two')
  14.   }
  15. })

This is so tempting for something I want to do… but too strange to use probably… maybe…

Destructure in Every Function

  1. // read through the comments of this snippet...
  2.  
  3. function dist1(x1, y1, x2, y2) {
  4.   const dx = x1 - x2
  5.   const dy = y1 - y2
  6.   return Math.sqrt(dx**2 + dy**2)
  7. }
  8.  
  9. function dist2({x1, y1, x2, y2}) {
  10.   const dx = x1 - x2
  11.   const dy = y1 - y2
  12.   return Math.sqrt(dx**2 + dy**2)
  13. }
  14.  
  15. // What's the difference here... well
  16. dist1(50, 50, 100, 100)
  17.  
  18. // vs
  19.  
  20. dist2({ x1: 50, y1: 50, x2: 100, y2: 100 })
  21.  
  22. // so what?
  23.  
  24. // With `dist2` the order of the arguments doesn't matter
  25. // and the arguments are named now as a result of being keys
  26. // in an object
  27.  
  28. // How many times have you changed a core function or method as you're
  29. // working on a project?
  30.  
  31. // Let's see another example:
  32.  
  33. // circle(100, 200, 300, 'red', 'blue', 0, 0)
  34.  
  35. // Can you guess what those arguments are? It's not really a big deal
  36. // and editors help with this, typescript helps with this... but what about:
  37.  
  38. circle({ 
  39.   x: 10, 
  40.   y: 110, 
  41.   radius: 120, 
  42.   fill: 'red', 
  43.   stroke: 'blue', 
  44.   velocityX: 0, 
  45.   velocitY: 0
  46. })
  47.  
  48. // how about...
  49. circle({ radius: 50, fill: 'blue' })
  50.  
  51. // or...
  52. circle({ stroke: 'green', x: 40, velocityX: 1 })
  53.  
  54. // etc...
  55. circle({ 
  56.   radius: 50,
  57.   stroke: 'black', x: 200, 
  58.   fill: 'teal',
  59.   velocityY: 1, velocityX: -1 })
  60.  
  61. // In combination with default arguments we end up with a very easy pattern for functions/methods
  62. // with a complex argument signature. gsap (aka TweenLite/TweenMax) has used this pattern for many
  63. // years. I've seen similar things in many languages...
  64.  
  65. // How does the circle function look?
  66.  
  67. function circle({ 
  68.   x = 0, y = 0, 
  69.   radius = 30, 
  70.   fill = 'black', 
  71.   stroke = 'transparent', 
  72.   velocityX = 0, velocityY = 0}) {
  73.  
  74.   const diam = radius * 2;
  75.  
  76.   const circle = document.body.appendChild(
  77.     Object.assign(
  78.       document.createElement('div'), 
  79.       { style: `
  80.         position: absolute;
  81.         left: ${x}px;
  82.         top: ${y}px;
  83.         width: ${diam}px;
  84.         height: ${diam}px;
  85.         background: ${fill};
  86.         border: 3px solid ${stroke};
  87.         border-radius: 100%;
  88.       `
  89.       }
  90.     )
  91.   )
  92.   if (velocityX != 0 || velocityY != 0) {
  93.     setInterval(() => {
  94.       x += velocityX
  95.       y += velocityY
  96.       circle.style.left = `${x}px`
  97.       circle.style.top = `${y}px`
  98.     }, 16)
  99.   }
  100.   return circle
  101. }
  102.  
  103.  
  104. // here is a golfed distance function - for no reason
  105. d=(a,b,c,d,e=a-c,f=b-d)=>Math.sqrt(e*e+f*f)
  106. console.log(
  107.   dist1(0, 0, 140, 140) ===
  108.   d(0, 0, 140, 140)
  109. )

Object Key Order and Reflect.ownKeys

  1. const obj = { 11: 'eleven', 23: 'twenty-three', 1: 'one', 2: 'two', '-1': 'negative 1' };
  2.  
  3. console.log(Reflect.ownKeys(obj))

I noticed that for in.. over an object was giving me weirdly consistent results across all browsers the other day and stumbled upon this.

Great news, but it’s Reflect.ownKeys for me… now that IE11 is dying/dead.

Raphaël Easing Equations How To

  1. const { pow, PI } = Math;
  2.  
  3. // mostly unedited code from Raphaël
  4. var ef = {
  5.   linear: function(n) {
  6.     return n;
  7.   },
  8.   '<': function(n) {
  9.     return pow(n, 1.7);
  10.   },
  11.   '>': function(n) {
  12.     return pow(n, 0.48);
  13.   },
  14.   '<>': function(n) {
  15.     var q = 0.48 - n / 1.04,
  16.       Q = Math.sqrt(0.1734 + q * q),
  17.       x = Q - q,
  18.       X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
  19.       y = -Q - q,
  20.       Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
  21.       t = X + Y + 0.5;
  22.     return (1 - t) * 3 * t * t + t * t * t;
  23.   },
  24.   backIn: function(n) {
  25.     var s = 1.70158;
  26.     return n * n * ((s + 1) * n - s);
  27.   },
  28.   backOut: function(n) {
  29.     n = n - 1;
  30.     var s = 1.70158;
  31.     return n * n * ((s + 1) * n + s) + 1;
  32.   },
  33.   elastic: function(n) {
  34.     if (n == !!n) {
  35.       return n;
  36.     }
  37.     return pow(2, -10 * n) * Math.sin(((n - 0.075) * (2 * PI)) / 0.3) + 1;
  38.   },
  39.   bounce: function(n) {
  40.     var s = 7.5625,
  41.       p = 2.75,
  42.       l;
  43.     if (n < 1 / p) {
  44.       l = s * n * n;
  45.     } else {
  46.       if (n < 2 / p) {
  47.         n -= 1.5 / p;
  48.         l = s * n * n + 0.75;
  49.       } else {
  50.         if (n < 2.5 / p) {
  51.           n -= 2.25 / p;
  52.           l = s * n * n + 0.9375;
  53.         } else {
  54.           n -= 2.625 / p;
  55.           l = s * n * n + 0.984375;
  56.         }
  57.       }
  58.     }
  59.     return l;
  60.   }
  61. };
  62. ef.easeIn = ef['ease-in'] = ef['<'];
  63. ef.easeOut = ef['ease-out'] = ef['>'];
  64. ef.easeInOut = ef['ease-in-out'] = ef['<>'];
  65. ef['back-in'] = ef.backIn;
  66. ef['back-out'] = ef.backOut;
  67.  
  68. // create a dot
  69. function dot(x, y, radius, color) {
  70.   const el = document.createElement('div');
  71.   const size = `${radius * 2}px`;
  72.   Object.assign(el.style, {
  73.     position: 'absolute',
  74.     left: `${x}px`,
  75.     top: `${y}px`,
  76.     width: size,
  77.     height: size,
  78.     transform: `translate(${-radius}px, ${-radius}px)`,
  79.     borderRadius: '50%',
  80.     background: color
  81.   });
  82.   el.classList.add('dot');
  83.   document.body.appendChild(el);
  84.   return el;
  85. }
  86.  
  87. const elA = dot(0, 40, 30, 'red');
  88. const elB = dot(0, 110, 30, 'blue');
  89. const elC = dot(0, 160, 20, 'green');
  90.  
  91. // how to use the easing equations:
  92. let t = 0;
  93.  
  94. let start = Date.now();
  95. let time = 0;
  96. let duration = 2; // 2 seconds
  97. function loop() {
  98.   // frame based
  99.   elA.style.left = `${ef.elastic(t) * 50}%`;
  100.   t += 0.005;
  101.  
  102.   // time based
  103.   if (time <= duration) {
  104.     time = (Date.now() - start) / 1000;
  105.     const param = time / duration;
  106.     elB.style.left = `${ef.elastic(param) * 50}%`;
  107.  
  108.     // green bounce example
  109.     elC.style.left = `${ef.bounce(param) * 50}%`;
  110.   }
  111.  
  112.   requestAnimationFrame(loop);
  113. }
  114. loop();

I realized it might not be obvious how to use Raphaël’s easing equations. So I speed coded this example.

If you’d like to learn more about this kind of thing gsap is a great place to start… it is amazing… I highly recommend browsing the source.

Rotate Point Around Point (Golfed)

  1.   rot = (
  2.     cx, cy, X, Y, ang,
  3.     cos = Math.cos(-ang),
  4.     sin = Math.sin(-ang),
  5.     x = cos * (X - cx) + sin * (Y - cy) + cx,
  6.     y = cos * (Y - cy) - sin * (X - cx) + cy) => ({ x, y })

Rotate one point around another… I like to use something like this when speed-coding and golfing…

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