0

I'm attempting to build a JavaScript interface to configure an easing function, similar to what's commonly seen in software like After Effects or Blender.

enter image description here

While I've made some progress, I'm not entirely satisfied with the results. I've experimented with various calculations, drawing inspiration from Bezier curves, but haven't achieved the desired outcome. I've set up a StackBlitz environment to showcase my current implementation .

As you can observe, the control handles' influence is not up to par; although I've occasionally achieved better results for one or the other, there's always an issue.

This is the best result I'm able to achieve. The handle in the upper-right corner behaves as I'd like, but the handleA in the bottom-left corner appears to respond only to its Y position; its X axis has no effect:

const interpCurve = (t) => {
  const A = [0, 1];
  const B = [handlePosA.value.x, handlePosA.value.y];
  const C = [handlePosB.value.x, handlePosB.value.y];
  const D = [1, 0];

  const AB = interpolateLine(A, B, t);
  const BC = interpolateLine(B, C, t);
  const CD = interpolateLine(C, D, t);

  const ABBC = interpolateLine(AB, BC, t);
  const BCCD = interpolateLine(BC, CD, t);
  const ABBCBCCD = interpolateLine(ABBC, BCCD, t);

  const result = ABBCBCCD[1];
  return result;
};
Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
snoob dogg
  • 2,491
  • 3
  • 31
  • 54
  • what is your concrete question? – Simon Laux Aug 04 '23 at 20:47
  • There is a standard way to apply this type of interface. It's difficult to describe because if it were clear in my mind, I don't think I would need to ask this question. I would like to find this procedure again, and I hope someone here who is more experienced than I am will be able to assist me. – snoob dogg Aug 04 '23 at 20:51
  • We are typically dealing with an ease-in-out type of interface where two handles are accessible to control the curve. This kind of behavior can be found in many software applications – snoob dogg Aug 04 '23 at 20:54
  • This is pretty much what SVG is for. A path with a single `C`, and two circles with touch/mouse handling JS. No need for any interpolation. It does the drawing for you. – Mike 'Pomax' Kamermans Aug 04 '23 at 21:08
  • No, SVGs are not my use case. I want to be able to retrieve the calculated values for this curve. – snoob dogg Aug 04 '23 at 21:11
  • I could achieve it with SVGs, we agree, or even with Three.js or pure CSS, but that's not the aim of my question. – snoob dogg Aug 04 '23 at 21:12
  • ... you know SVG is just another HTML element, right? You use an event listener for the SVG "circle" handles, then you update the SVG accordingly and get the resultant curve basically for free. That said, whether you do this with SVG or not, show a ([mcve]) runnable snippet in your post (and no need for the example images from other applications, web devs know what a curve control looks like =) – Mike 'Pomax' Kamermans Aug 04 '23 at 21:13
  • and how I get the precises values for each `t` I want? I mean, I want `y` value when `x` is 0.23, how do I do with SVG ? I don't think it will works – snoob dogg Aug 04 '23 at 21:15
  • [like this, using JS](https://pomax.github.io/bezierinfo/#yforx), which doesn't really involve interpolation of any sort, but it does involve a bit of math because it's going to have to, since you're working with a non-linear curve mapping. (because weird as it may seem, this is actually - mathematically speaking - not a trivial problem. By fixing the start and end point, and restricting the control domain, we made it easier, but we only made it "easier", not "easy"). – Mike 'Pomax' Kamermans Aug 04 '23 at 21:16
  • @snoobdogg why does result only return the y value? Assuming I understand the code properly. – Jordan Aug 04 '23 at 21:24
  • @jordan, I tried to use a norm like `Math.sqrt(ABBCBCCD[0]*ABBCBCCD[0]+ABBCBCCD[1]*ABBCBCCD[1])` but then I've got a bell curve : ( – snoob dogg Aug 04 '23 at 21:27
  • @Mike'Pomax'Kamermans Why did you remove my reproduction on StackBlitz? I made the effort to provide one, and it's not enough? Now, I have to spend three hours learning how to do the same thing on Stack Overflow. Thank you for your help, but please move on to the next question and let me rollback my question. – snoob dogg Aug 04 '23 at 21:28
  • Ah, probably caught in the deleting of the app screenshots (it was a number-linked link instead of a normal inline link). Let me put that back. (edit: nvm, looks like you restored it yourself). – Mike 'Pomax' Kamermans Aug 04 '23 at 21:34
  • @Mike'Pomax'Kamermans ha, ok sorry then – snoob dogg Aug 04 '23 at 21:35
  • @Mike'Pomax'Kamermans https://pomax.github.io/bezierinfo/#yforx is exaclty what I'm looking for – snoob dogg Aug 04 '23 at 21:43
  • Good to hear. Just note that there's a whole bunch of posts [on SO for finding Y for X in a bezier curve](https://www.google.com/search?q=y+for+x+bezier+stackoverflow+site:stackoverflow.com) though, so that definitely makes this a duplicate =D – Mike 'Pomax' Kamermans Aug 04 '23 at 21:48
  • 1
    @Mike'Pomax'Kamermans Sorry for getting frustrated, but Stack Overflow is full of jerks, and that's actually how we learn on Stack Overflow - by encountering jerks empirically. So, we gradually build trigger warnings that make us unsure if we'll end up dealing with a jerk whenever we ask a new question and aren't sure if we've phrased it correctly. When you edited my question to remove my StackBlitz, I was 100% sure I had encountered another jerk. – snoob dogg Aug 04 '23 at 21:49
  • @snoobdogg The issue is that the Bezier curve is sharing both it's x value and t value, which will not produce a true Bezier curve. I made changes to two functions to make it behave properly drawInterpCurve: `... for (let i = 0; i < 200; i++) { const normT = i / 200; const interpVal = interpCurve(normT); const x = interpVal[0] * 200; const y = 200 - (1 - interpVal[1]) * 200; curve.lineTo([x, y]); } ...` interpCurve: `... return ABBCBCCD;` – Jordan Aug 04 '23 at 21:50
  • @snoobdogg can't argue with that. – Mike 'Pomax' Kamermans Aug 04 '23 at 21:51
  • @Jordan thank you : ) – snoob dogg Aug 04 '23 at 21:56
  • @Jordan it works like a charm ^^ – snoob dogg Aug 04 '23 at 22:33

0 Answers0