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

Odd Gradient Notation

  1. // "Being clever is not clever"
  2. // -- Bjarne Stroustrup
  3. D = document
  4. ang = {
  5.   '|': 180,
  6.   '-': 90,
  7.   '\\': 135,
  8.   '/': 225
  9. }
  10.  
  11. box = def => {
  12.   def = def.split(/\s+/)
  13.   form = def.length
  14.   I = i => parseInt(def[i], 16)
  15.  
  16.   ;[,,, _=>{x = y = I(0); w = h = I(1); c = def[2]},
  17.     _=>{x = I(0), y = I(1); w = h = I(2);c = def[3]},
  18.     _=>{x = I(0); y = I(1); w = I(2); h = I(3); c = def[4]}
  19.   ][form]()
  20.  
  21.   c = c.split``
  22.  
  23.   ca = c[0]
  24.   ca = ca+ca+ca
  25.   cD = ang[c[1]]
  26.   cb = c[2]
  27.   cb = cb+cb+cb 
  28.  
  29.   D.body.appendChild(
  30.     D.createElement`div`
  31.   ).style = `
  32.     position: absolute; left: ${x}px; top: ${y}px;
  33.     width: ${w}px; height: ${h}px;
  34.     background: linear-gradient(${cD}deg, #${ca}, #${cb})
  35.   `
  36. }
  37.  
  38. const parse = prog => prog.trim()
  39.   .split(/\n+/m)
  40.   .map(line => box(line.trim()))
  41.  
  42. parse(`
  43.   0 64 0/f
  44.   64 64 0\\f
  45.   a0 f0 30 54 f\\0
  46.   0 6f 20 60 0-c
  47.   f 7f 20 60 0|c
  48.   1f 8f 30 30 c/0
  49. `)

Just playing around… odd micro-gradient notation:

  1. '0 64 0/f'
  2. // x=0 y=0 width=0x64 height=0x64
  3. // 0/f = gradient black to white top right to bottom left
  4.  
  5. '64 64 0\\f'
  6. // x=0 y=0 width=0x64 height=0x64
  7. // 0\\f = black to to white gradient top left to bottom right
  8.  
  9. '0 6f 20 60 0-c'
  10. // x=0 y=0x6f width=0x20 height=0x60
  11. // 0-c = gradient black to grey (#ccc) left to right
  12.  
  13. // etc... ( | ) is top to bottom grad
// css // dom // golfed // graphics // hacks // humor // regex // speed-coded

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.

Polar Plots

  1. const Pnt = (x, y, p = { x, y }) => (
  2.   p.add = o => (p.x += o.x, p.y += o.y, p), p
  3. );
  4. Pnt.polar = (rad, t) => Pnt(rad * Math.cos(t), rad * Math.sin(t));
  5.  
  6. const pnts = {};
  7. let index = -1;
  8. const polar = (inc, rad) => {
  9.   index++;
  10.   if (!pnts[index]) pnts[index] = 0;
  11.   return Pnt.polar(rad, (pnts[index] += inc));
  12. };
  13.  
  14. let d = document;
  15. let b = d.body;
  16. with (b.appendChild(
  17.   Object.assign(d.createElement`canvas`, {
  18.     width: 600,
  19.     height: 500,
  20.   })
  21. ).getContext`2d`) {
  22.   canvas.style.transformOrigin = "0 0";
  23.   canvas.style.transform = "scale(.6)";
  24.  
  25.   let p0 = Pnt(80, 100);
  26.   let p1 = Pnt(270, 100);
  27.   let p2 = Pnt(480, 40);
  28.   let p3 = Pnt(170, 180);
  29.   let p4 = Pnt(430, 300);
  30.  
  31.   fillStyle = "black";
  32.  
  33.   function loop() {
  34.     for (let i = 0; i < 20; i++) {
  35.       index = -1;
  36.  
  37.       p0.add(polar(0.2, 4).add(polar(-0.4, 2).add(polar(0.05, 1))));
  38.       fillRect(p0.x, p0.y, 1, 1);
  39.  
  40.       p1.add(
  41.         polar(0.1, 2).add(
  42.           polar(-0.2, 2).add(polar(0.03, 1).add(polar(-0.01, 0.5)))
  43.         )
  44.       );
  45.       fillRect(p1.x, p1.y, 1, 1);
  46.  
  47.       p2.add(polar(0.08, 3).add(polar(-0.2, -12).add(polar(2, 10))));
  48.       fillRect(p2.x, p2.y, 1, 1);
  49.  
  50.       p3.add(polar(0.08, 7).add(polar(-0.2, -12).add(polar(2, 11))));
  51.       fillRect(p3.x, p3.y, 1, 1);
  52.  
  53.       p4 = p4.add(polar(0.025, 2).add(polar(-0.05, 1)));
  54.       fillRect(p4.x, p4.y, 1, 1);
  55.     }
  56.     requestAnimationFrame(loop);
  57.   }
  58.  
  59.   loop();
  60. }

Some polar plots…

WebGL Particles in Sphere

  1. (() => {
  2.   const m = new Float32Array([
  3.     0, 0, 0, 0, 
  4.     0, 0, 0, 0, 
  5.     0, 0, 0, 0, 
  6.     0, 0, 0, 0])
  7.  
  8.   const pointSize = Math.max(Math.min(30, ~~(innerWidth / 70)), 3)
  9.  
  10.   const vert = `
  11.     attribute vec3 vec;
  12.     uniform mat4 mat;
  13.     void main(void) {
  14.       gl_Position = mat * vec4(vec, 1.0);
  15.       gl_PointSize = ${pointSize}.0;
  16.     }
  17.   `
  18.  
  19.   const frag = `
  20.     void main(void) {
  21.       gl_FragColor = vec4(1., 1., 1., .25);
  22.     }
  23.   `
  24.  
  25.   document.body.style.background = '#232323'
  26.   const gl = document.body
  27.     .appendChild(document.createElement('canvas'))
  28.     .getContext('webgl', {
  29.       preserveDrawingBuffer: true,
  30.       powerPreference: 'high-performance'
  31.     })
  32.  
  33.   Object.assign(gl.canvas.style, {
  34.     position: 'absolute',
  35.     left: '50%',
  36.     top: '50%',
  37.     transform: 'translate(-50%, -50%)',
  38.     outline: '1px solid gray'
  39.   })
  40.  
  41.   with (gl) {
  42.     const NUM = 4000
  43.     const radius = 0.7
  44.     const verts = []
  45.  
  46.     for (let i = 0; i < NUM; i += 3) {
  47.       let xp = Math.random() * 2 - 1
  48.       let yp = Math.random() * 2 - 1
  49.       let zp = Math.random() * 2 - 1
  50.       let dist = Math.sqrt(xp * xp + yp * yp + zp * zp)
  51.       // normalize and scale x,y,z
  52.       verts[i] = (xp / dist) * radius
  53.       verts[i + 1] = (yp / dist) * radius
  54.       verts[i + 2] = (zp / dist) * radius
  55.  
  56.     }
  57.     const overts = verts.concat()
  58.     const leng = verts.length / 3
  59.  
  60.     bindBuffer(ARRAY_BUFFER, createBuffer())
  61.     bufferData(ARRAY_BUFFER, new Float32Array(verts), STATIC_DRAW)
  62.  
  63.     const vs = createShader(VERTEX_SHADER)
  64.     shaderSource(vs, vert)
  65.     compileShader(vs)
  66.  
  67.     const fs = createShader(FRAGMENT_SHADER)
  68.     const sp = createProgram()
  69.  
  70.     shaderSource(fs, frag)
  71.     compileShader(fs)
  72.     attachShader(sp, vs)
  73.     attachShader(sp, fs)
  74.     linkProgram(sp)
  75.     useProgram(sp)
  76.  
  77.     const vec = getAttribLocation(sp, 'vec')
  78.     vertexAttribPointer(vec, 3, FLOAT, false, 0, 0)
  79.     enableVertexAttribArray(vec)
  80.  
  81.     const matLoc = getUniformLocation(sp, 'mat')
  82.  
  83.     function rot(x, y, z) {
  84.       // https://wikimedia.org/api/rest_v1/media/math/render/svg/a8e16f4967571b7a572d1a19f3f6468512f9843e
  85.  
  86.       const sinA = Math.sin(x)
  87.       const cosA = Math.cos(x)
  88.       const sinB = Math.sin(y)
  89.       const cosB = Math.cos(y)
  90.       const sinY = Math.sin(z)
  91.       const cosY = Math.cos(z)
  92.  
  93.       m[0] = cosA * cosB
  94.       m[1] = cosA * sinB * sinY - sinA * cosY
  95.       m[2] = cosA * sinB * cosY + sinA * sinY
  96.       m[3] = 0
  97.  
  98.       m[4] = sinA * cosB
  99.       m[5] = sinA * sinB * sinY + cosA * cosY
  100.       m[6] = sinA * sinB * cosY - cosA * sinY
  101.       m[7] = 0
  102.  
  103.       m[8] = -sinB
  104.       m[9] = cosB * sinY
  105.       m[10] = cosB * cosY
  106.       m[11] = m[12] = m[13] = 0
  107.       m[15] = 1
  108.  
  109.       uniformMatrix4fv(matLoc, false, m)
  110.     }
  111.  
  112.     onresize = () => {
  113.       const { canvas } = gl
  114.       const size = Math.min(innerWidth, innerHeight) - 20
  115.       canvas.width = canvas.height = size
  116.       viewport(0, 0, size, size)
  117.     }
  118.  
  119.     onresize()
  120.  
  121.     let rx = 0,
  122.       ry = 0,
  123.       rz = 0
  124.     let t = 0
  125.  
  126.     function loop() {
  127.       rx += 0.01
  128.       ry += 0.01
  129.       rot(rx, ry, rz)
  130.  
  131.       disable(DEPTH_TEST)
  132.       enable(BLEND)
  133.       blendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
  134.  
  135.       clearColor(0, 0, 0, 1)
  136.  
  137.       clear(COLOR_BUFFER_BIT)
  138.  
  139.       for (let i = 0; i < verts.length; i += 3) {
  140.         let tof = i * 0.001 + t;
  141.         verts[i] = Math.sin(tof) * overts[i]
  142.         verts[i + 1] = Math.sin(tof) * overts[i + 1]
  143.         verts[i + 2] = Math.sin(tof) * overts[i + 2]
  144.       }
  145.  
  146.       t += 0.01
  147.  
  148.       bufferSubData(ARRAY_BUFFER, 0, new Float32Array(verts))
  149.  
  150.       drawArrays(POINTS, 0, leng)
  151.       window.requestAnimationFrame(loop)
  152.     }
  153.     loop()
  154.   }
  155. })()

Playing around with animating points…

WebGL Points and Rotation

  1. (() => {
  2.   const m = new Float32Array([
  3.     0, 0, 0, 0, 
  4.     0, 0, 0, 0, 
  5.     0, 0, 0, 0, 
  6.     0, 0, 0, 0
  7.   ])
  8.  
  9.   const pointSize = Math.max(Math.min(10, ~~(innerWidth / 70)), 3);
  10.  
  11.   const vert = `
  12.     attribute vec3 vec;
  13.     uniform mat4 mat;
  14.     void main(void) {
  15.       gl_Position = mat * vec4(vec, 1.);
  16.       gl_PointSize = ${pointSize}.;
  17.     }
  18.   `
  19.  
  20.   const frag = `
  21.     void main(void) {
  22.       gl_FragColor = vec4(1., 1., 1., .4);
  23.     }
  24.   `
  25.  
  26.   document.body.style.background = '#333'
  27.   const gl = document.body
  28.     .appendChild(document.createElement('canvas'))
  29.     .getContext('webgl')
  30.  
  31.   Object.assign(gl.canvas.style, {
  32.     position: 'absolute',
  33.     left: '50%',
  34.     top: '50%',
  35.     transform: 'translate(-50%, -50%)',
  36.     outline: '1px solid gray'
  37.   })
  38.  
  39.   with (gl) {
  40.     const NUM = 600
  41.     const verts = []
  42.  
  43.     for (let i = 0; i < NUM; i++) {
  44.       verts.push(
  45.         Math.random() * 1 - 0.5,
  46.         Math.random() * 1 - 0.5,
  47.         Math.random() * 1 - 0.5
  48.       )
  49.     }
  50.  
  51.     const leng = verts.length / 3
  52.     bindBuffer(ARRAY_BUFFER, createBuffer())
  53.     bufferData(ARRAY_BUFFER, new Float32Array(verts), STATIC_DRAW)
  54.  
  55.     const vs = createShader(VERTEX_SHADER)
  56.     shaderSource(vs, vert)
  57.     compileShader(vs)
  58.  
  59.     const fs = createShader(FRAGMENT_SHADER)
  60.     const sp = createProgram()
  61.  
  62.     shaderSource(fs, frag)
  63.     compileShader(fs)
  64.     attachShader(sp, vs)
  65.     attachShader(sp, fs)
  66.     linkProgram(sp)
  67.     useProgram(sp)
  68.  
  69.     const vec = getAttribLocation(sp, 'vec')
  70.     vertexAttribPointer(vec, 3, FLOAT, false, 0, 0)
  71.     enableVertexAttribArray(vec)
  72.  
  73.     const matLoc = getUniformLocation(sp, 'mat')
  74.  
  75.     function rot(x, y, z) {
  76.       // https://wikimedia.org/api/rest_v1/media/math/render/svg/a8e16f4967571b7a572d1a19f3f6468512f9843e
  77.  
  78.       const sinA = Math.sin(x)
  79.       const cosA = Math.cos(x)
  80.       const sinB = Math.sin(y)
  81.       const cosB = Math.cos(y)
  82.       const sinY = Math.sin(z)
  83.       const cosY = Math.cos(z)
  84.  
  85.       m[0] = cosA * cosB
  86.       m[1] = cosA * sinB * sinY - sinA * cosY
  87.       m[2] = cosA * sinB * cosY + sinA * sinY
  88.       m[3] = 0
  89.  
  90.       m[4] = sinA * cosB
  91.       m[5] = sinA * sinB * sinY + cosA * cosY
  92.       m[6] = sinA * sinB * cosY - cosA * sinY
  93.       m[7] = 0
  94.  
  95.       m[8] = -sinB
  96.       m[9] = cosB * sinY
  97.       m[10] = cosB * cosY
  98.       m[11] = m[12] = m[13] = 0
  99.       m[15] = 1
  100.  
  101.       uniformMatrix4fv(matLoc, false, m)
  102.     }
  103.  
  104.     onresize = () => {
  105.       const { canvas } = gl
  106.       const size = Math.min(innerWidth, innerHeight) - 20
  107.       canvas.width = canvas.height = size
  108.       viewport(0, 0, size, size)
  109.     }
  110.  
  111.     onresize()
  112.  
  113.     let ry = 0, rz = 0
  114.  
  115.     disable(DEPTH_TEST)
  116.     enable(BLEND)
  117.     blendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
  118.  
  119.     function loop() {
  120.       rot(0, ry -= 0.03, rz += 0.001)
  121.  
  122.       clearColor(0, 0, 0, 1)
  123.       clear(COLOR_BUFFER_BIT)
  124.       drawArrays(POINTS, 0, leng)
  125.       window.requestAnimationFrame(loop)
  126.     }
  127.     loop()
  128.   }
  129. })()

Some WebGL points with rotation… I couldn’t resist using with here…

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