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

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.

Raphaël Easing Equations

  1. var ef = R.easing_formulas = {
  2.     linear: function (n) {
  3.         return n;
  4.     },
  5.     "<": function (n) {
  6.         return pow(n, 1.7);
  7.     },
  8.     ">": function (n) {
  9.         return pow(n, .48);
  10.     },
  11.     "<>": function (n) {
  12.         var q = .48 - n / 1.04,
  13.             Q = math.sqrt(.1734 + q * q),
  14.             x = Q - q,
  15.             X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
  16.             y = -Q - q,
  17.             Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
  18.             t = X + Y + .5;
  19.         return (1 - t) * 3 * t * t + t * t * t;
  20.     },
  21.     backIn: function (n) {
  22.         var s = 1.70158;
  23.         return n * n * ((s + 1) * n - s);
  24.     },
  25.     backOut: function (n) {
  26.         n = n - 1;
  27.         var s = 1.70158;
  28.         return n * n * ((s + 1) * n + s) + 1;
  29.     },
  30.     elastic: function (n) {
  31.         if (n == !!n) {
  32.             return n;
  33.         }
  34.         return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
  35.     },
  36.     bounce: function (n) {
  37.         var s = 7.5625,
  38.             p = 2.75,
  39.             l;
  40.         if (n < (1 / p)) {
  41.             l = s * n * n;
  42.         } else {
  43.             if (n < (2 / p)) {
  44.                 n -= (1.5 / p);
  45.                 l = s * n * n + .75;
  46.             } else {
  47.                 if (n < (2.5 / p)) {
  48.                     n -= (2.25 / p);
  49.                     l = s * n * n + .9375;
  50.                 } else {
  51.                     n -= (2.625 / p);
  52.                     l = s * n * n + .984375;
  53.                 }
  54.             }
  55.         }
  56.         return l;
  57.     }
  58. };
  59. ef.easeIn = ef["ease-in"] = ef["<"];
  60. ef.easeOut = ef["ease-out"] = ef[">"];
  61. ef.easeInOut = ef["ease-in-out"] = ef["<>"];
  62. ef["back-in"] = ef.backIn;
  63. ef["back-out"] = ef.backOut;

Another fun chunk of code directly from the Raphaël source. Makes me think of the Penner easing equations.

Polar Forking Tweak

  1. const FOUR_PI = 6 * Math.PI;
  2. const { cos, sin } = Math;
  3.  
  4. const canvas = document.body.appendChild(
  5.   document.createElement('canvas')
  6. );
  7. const c = canvas.getContext('2d');
  8.  
  9. function resize() {
  10.   canvas.width = window.innerWidth;
  11.   canvas.height = window.innerHeight;
  12. }
  13.  
  14. let inc = 0;
  15. function draw() { 
  16.   c.fillStyle = 'rgba(0, 0, 0, .3)'
  17.   c.fillRect(0, 0, canvas.width, canvas.height)
  18.   c.fillStyle = 'white';
  19.  
  20.   const halfWidth = window.innerWidth / 2;
  21.   const halfHeight = window.innerHeight / 2;
  22.   let theta = 0,
  23.     a = 20 * Math.min(window.innerWidth, window.innerHeight) * 0.005,
  24.     x,
  25.     y;
  26.  
  27.   c.save();
  28.   c.translate(halfWidth, halfHeight)
  29.  
  30.   let b = 5 * cos(inc);
  31.   inc += .02;
  32.  
  33.   for (let i = 0; theta < FOUR_PI; i++) {
  34.     let rad = a * (b + 10 * sin(theta / 3));
  35.     // randomly speed-coded and tweaked... leaving as is :D
  36.     x = rad * cos(theta + b / 10) * cos(b / 10 +theta * 2) * cos(theta * 2);
  37.     y = rad * sin(theta * 2) * cos(theta + b / 3) * cos(theta * 2);
  38.     c.fillRect(x,y, 2, 2);
  39.     theta += 0.04;
  40.   }
  41.   c.restore();
  42.  
  43.   requestAnimationFrame(draw)
  44. }
  45.  
  46. resize();
  47. addEventListener('resize', resize);
  48.  
  49. draw();

Just randomly futzing with sin/cos…

Freeth’s Nephroid Animated

  1. const FOUR_PI = 4 * Math.PI;
  2. const { cos, sin } = Math;
  3.  
  4. const canvas = document.body.appendChild(
  5.   document.createElement('canvas')
  6. );
  7. const c = canvas.getContext('2d');
  8.  
  9. function resize() {
  10.   canvas.width = window.innerWidth;
  11.   canvas.height = window.innerHeight;
  12. }
  13.  
  14. let inc = 0;
  15. function draw() {
  16.   c.clearRect(0, 0, canvas.width, canvas.height);
  17.   c.fillStyle = 'blue';
  18.  
  19.   const halfWidth = window.innerWidth / 2;
  20.   const halfHeight = window.innerHeight / 2;
  21.   let theta = 0,
  22.     a = 20 * Math.min(window.innerWidth, window.innerHeight) * 0.005,
  23.     x,
  24.     y;
  25.  
  26.   c.save();
  27.   c.translate(halfWidth, halfHeight)
  28.  
  29.   // Freeth's Nephroid
  30.   // https://mathshistory.st-andrews.ac.uk/Curves/Freeths/
  31.   // r = a(1 + 2sin(θ / 2))
  32.   let b = 2 * cos(inc);
  33.   inc += .01;
  34.  
  35.   for (let i = 0; theta < FOUR_PI; i++) {
  36.     let rad = a * (b + 2 * sin(theta / 2))
  37.     x = rad * cos(theta);
  38.     y = rad * sin(theta);
  39.     c.fillRect(x, y, 2, 2);
  40.     theta += 0.05;
  41.   }
  42.   c.restore();
  43.  
  44.   requestAnimationFrame(draw)
  45. }
  46.  
  47. resize();
  48. window.addEventListener('resize', resize);
  49.  
  50. draw()

It’s always fun to play with curves from here Famous Curves Index

Hermit Crab Curves

  1. // six white geometric figures (outlines) superimposed on a black wall.
  2. d = document
  3. b = d.body
  4. S = 600
  5. hs = S / 2
  6. with(Math) {
  7. with(
  8.   b.appendChild(Object.assign(
  9.   d.createElement`canvas`, { width: S, height: S })
  10.   ).getContext`2d`) {
  11.  
  12.     fillRect(0, 0, S, S)
  13.     strokeStyle = '#fff'
  14.  
  15.     canvas.style.transformOrigin = '0 0'
  16.     canvas.style.transform = 'scale(.5)'
  17.  
  18.     lineWidth = 8
  19.  
  20.     H = (
  21.       s = S * .5,
  22.       yp = hs, xp = hs,
  23.       a = 1.234,
  24.       d = 0.1678,
  25.       o = 3.9
  26.       ) => {
  27.         beginPath()
  28.         for (t = 0; t < 6.28; t+=.2) {
  29.           r = sqrt(a ** PI % sin(d * (t ** 2 * a) + o)) * s
  30.           x = xp + r * sin(t);
  31.           y = yp + r * cos(t);
  32.           t === 0 ? moveTo(x, y) : lineTo(x, y)
  33.         }
  34.         closePath()
  35.         stroke()
  36.         fill()
  37.     }
  38.  
  39.     tick = 0
  40.     loop = _ => {
  41.       fillStyle = 'rgba(0, 0, 0, 0.5)'
  42.       fillRect(0, 0, S, S)
  43.       save()
  44.       translate(S/2, S/2)
  45.       scale(.5, .5)
  46.       rotate(tick * 20)
  47.       translate(-S/2, -S/2)
  48.       tick += .0001
  49.       globalAlpha = .8;
  50.       H(S, hs, hs, 1 + tick)
  51.       H(S, hs, hs, 1.1 + tick)
  52.       H(S, hs, hs, 1.2 + tick)
  53.       globalAlpha = 1;
  54.       H(S * .3, hs-S/4, hs, 1, tick)
  55.       H(S * .2, hs+S/4, hs, 1.2, tick, 1.8)
  56.       H(S * .2, hs, hs - S/4, cos(tick), -tick, 5)
  57.       restore()
  58.       requestAnimationFrame(loop)
  59.     }
  60.     loop()
  61.   }
  62. }

Another thing for #genuary2022Sol LeWitt Wall Drawing

snippet.zone /// {s/z}