This is the effect I am trying to achieve: http://codepen.io/anon/pen/ENzQem
I am trying to generate an effect where the letters of a string get revealed gradually and randomly. See the codepen link above for a demonstration of this.
However, I'm finding it difficult to show each character naturally if I just simply randomly generate numbers for each delay separately.
If I simply do a Math.random()
to generate a number independently for each character, sometimes adjacent letters will have similar delay numbers, and as such the effect will look chunky, with two letters side-by-side appearing at the same rate.
This is the naive solution with separate random number generators:
renderSpans(text) {
const textArray = text.split('');
return textArray.map((letter, index) => {
const transitionTime = 2000;
const delay = parseInt(Math.random() * transitionTime, 10);
const styles = {
opacity: this.props.show ? '1' : '0',
transition: `opacity ${transitionTime}ms`,
transitionDelay: `${delay}ms`,
};
return <span style={styles}>{letter}</span>;
});
}
I need an algorithm to generate an array of numbers that I can use as the delay for each of the characters, regardless of the length of the input string.
My first thought is to use a sinusoidal wave of some sort, with a bunch of randomness put in, but I'm not sure about the specifics on this. I am sure there's a much more well-accepted way to generate natural-looking noise in mathematics.
Can someone point me to some well-known algorithms for my use case? Maybe something to do with Perlin noise or the like?
Thanks in advance.
It turns out I was overthinking the problem.
I ended up creating the following function:
I originally wrote a version of this function that uses reduce rather than a for-loop, but ultimately decided that a for-loop would be clearer and simpler.
How it works
This function procedurally builds up an array of random numbers, given the required length and a "closeness" threshold. Each of the resulting random numbers will have a difference greater than the threshold when compared with the previous number in the array.
For the first item in the array, we simply generate a random number and push it in.
For each of the subsequent items in the array, we:
I have found that a threshold of
0.2
seem to work pretty well for my use case.