animatedjs/animated

Support outputRange of strings

browniefed opened this issue · 4 comments

Just capturing this, as it's been brought up before.
It would be great to have custom interpolators for things like SVG paths and what not.

However simple applications like

animated.interpolate({
  inputRange: [0, 1],
  outputRange: ["none", "flex"]
})

Would be very beneficial in animations when things require a View that is absolute or covering another view to be hidden, and not interfere with touches.

Looks like we just need to short circuit the createInterpolationFromStringOutputRange call and mod the pattern check and findRange calls.

PatternCheck will return true if they all match specific pattern, false if they are all different.
Should probably add invariants here when pattern has Numbers vs just Strings.

I'm wondering what to do between the ranges though.

animated.interpolate({
  inputRange: [0, 1],
  outputRange: ["none", "flex"]
})

If in the example you set it to .5 does that stay none? I'd assume yes. Which means I'd need to adjust how the range is discovered. >= as well as < next range (or end of inputRanges)

const validPattern = checkPattern(outputRange);

  if (!validPattern) {
    return (input) => {
      const range = findLowerRange(input, config.inputRange);
      return outputRange[range]
    };
  }
function checkPattern(arr: Array<string>) {
  var pattern = arr[0].replace(stringShapeRegex, '');
  for (var i = 1; i < arr.length; ++i) {
    if (pattern !== arr[i].replace(stringShapeRegex, '')) {
      return false
    }
  }
  return true;
}

function findLowerRange(input: number, inputRange: Array<number>) {
  for (var i = 0; i < inputRange.length - 1; ++i) {
    if (inputRange[i] >= input) {
      break;
    }
  }
  return i;
}

@vjeux Do you have any input on this? Am I over simplifying things here?

@browniefed To me, your example implies that there are valid values between none and flex which we can animate through. Since interpolation in general is about generating new values between some existing, known values, maybe there's room for another method alongside interpolate to handle this? Maybe something like animatedValue.map({ 0: 'none', 1: 'flex' }) or animatedValue.map((value) => value < 1 ? 'none' : 'flex'))?

The reason I chose interpolate is that when to show is not always going to be 1 or a 0 which could be solved with a simple list.
In our case order also matters, and Objects have no set order. This could be solved with a structure like [{ }, { }].

Additionally it could be any floating value. As well as a negative floating values, etc. So a simple map would be difficult to set up like that.

Ideally interpolate would allow for a function and actually building something specific like this wouldn't be necessary, you would just add on top.

So maybe that's the solution? But that would need to be crafted as there are a lot of edge cases as well as use cases.

Thinking about this I'm wondering if leveraging interpolate makes sense vs one of the other proposed methods of building your own custom Animated values.