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

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. )

Map vs WeakMap

  1. const map = new Map()
  2.  
  3. map.set(1, 'one')
  4.  
  5. console.log(map.get(1))
  6.  
  7. const weakMap = new WeakMap()
  8.  
  9. // this will fail with an error:
  10. // weakMap.set(1, 'one')
  11.  
  12. // console.log(weakMap.get(1))

Noticed this gotcha the other day. For some reason WeakMap can’t have integers as keys. After years of using WeakMap I guess I’ve only ever used objects as keys and assumed it could just have keys of any type. Using a Map instead solves the problem, but you’ll need to be careful to manager your references to properly clear the Map. Anyway, just one of those things… Maybe I’ll write more about it when I have some time to dig deeper.

Toggle a Class

  1. // lazy hack for css
  2. document.body.innerHTML = `
  3.   <style> 
  4.     button { 
  5.       cursor: pointer; 
  6.     }
  7.     .red { 
  8.       background-color: red; 
  9.     } 
  10.   </style>
  11. `
  12.  
  13. const btn = document.body.appendChild(
  14.   Object.assign(
  15.     document.createElement('button'), 
  16.     { innerText: 'click me' }
  17.   )
  18. )
  19.  
  20. btn.addEventListener('click', e => {
  21.   e.target.classList.toggle('red')
  22. })

classList.toggle brings back memories…

// css // dom // ui

Decompose Matrix

  1. const deltaTransformPoint = (matrix, point) => {
  2.   return {
  3.     x: point.x * matrix.a + point.y * matrix.c,
  4.     y: point.x * matrix.b + point.y * matrix.d
  5.   }
  6. }
  7.  
  8. const decomposeMatrix = matrix => {
  9.   let px = deltaTransformPoint(matrix, { x: 0, y: 1 })
  10.   let py = deltaTransformPoint(matrix, { x: 1, y: 0 })
  11.   let skewX = FROM_RADS * Math.atan2(px.y, px.x) - 90
  12.   let skewY = FROM_RADS * Math.atan2(py.y, py.x)
  13.  
  14.   return {
  15.     tx: matrix.e,
  16.     ty: matrix.f,
  17.     scaleX: Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b),
  18.     scaleY: Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d),
  19.     skewX: skewX,
  20.     skewY: skewY,
  21.     rotation: skewX
  22.   }
  23. }

Get the scale, translation, rotationa and skew values from a matrix.

Great stackoverflow answer from user dave

// graphics // math // matrix

Bad JavaScript Poem

  1. with (self) with (Math){ typeof self
  2. with (window) with (sin) if (true) self }

This could be dangerous. Bad js poetry:

With self With Math Type of self With window With sin If true self

:/

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