Calculated values
Opened this issue · 3 comments
What are you guys thinking about calculated values? Something like Behaviors
in FRP terms or spreadsheet-like dataflow.
Main question is why do we need them?
Ok - let's explain we have transitions between scenes, and main value for all transition is progress
- this is value changed by time for 0 to 1. In scene we want to change text opacity and some position.
const Scene = (width, height, progress) =>
<View style={{position: "absolute",
height: height,
width: width,
backgroundColor "blue"}}
<Text style={{fontSize: 16,
opacity: progress < 0.5 ? (1 - (progress * 2)) : 0,
marginLeft: progress < 0.5 ? (progress * 2 * 250 * -1) : 0}} />
</View>
But I want to use calculated values, smth like this:
class AnimatedCell {
constructor() {
this._subscribers = [];
}
push(value) {
this._subscribers.forEach(next => next.call(null, value));
}
subscribe(next) {
this._subscribers.push(next);
}
}
const bind = (cell, fn) => {
const newCell = new AnimatedCell();
cell.subscribe(val => newCell.push(fn.call(null, val))
}
const bindToAnimated = (cell, initialValue) =>
const newAnimated = new AnimatedValue(initialValue || 0);
cell.subscribe(val => newAnimated.setValue(val));
return newAnimated;
}
And use it in scene:
const Scene = (width, height, progress) => {
const opacity = bind(progress, progress => progress < 0.5 ? (1 - (progress * 2)) : 0);
const marginLeft = bind(progress, progress => progress < 0.5 ? (progress * 2 * 250 * -1) : 0);
return (
<View style={{position: "absolute",
height: height,
width: width,
backgroundColor "blue"}}
<Text style={{fontSize: 16,
opacity: bindToAnimated(opacity, 1),
marginLeft: bindToAnimated(marginLeft, 0)}} />
</View>
);
}
Every time when progress is changed, opacity and margin-left recalculated and refresh Animated.
What do you think?
If you guys familiar with ClojureScript you can see it in action on my experiment with react native navigation https://github.com/savelichalex/experiment-navigation-react-native/tree/cell-proposal
I also think being able to implement this bind()
make Animated more powerful and interesting (myself, I prefer to call it map()
but whatever). Also allow to extend Animated in third party library.
I remember we had a discussion here in the past: animatedjs/interactive-docs#5
is this ~ the same topic or am I out of subject?
I think the main problem we evoked, is that it is hard for React Native to implement Animations in an another thread (like in ObjC / Java side) if animated object are not serializable, which is the case when you use
newValue = bind(value, aJSFunction)
.
Yeah, this is possible to extend in third party library, but maybe we can create smth interesting if it'll be in core. I'm trying to say, that we also can extend behavior of few core methods. For example if Animated.timing
get computed value, then they just push
on it and update all dependent values.