如何生成随机分布以使字符(在 word/phrase 中)看起来更自然

How to generate a random distribution to make characters (in a word/phrase) appear more naturally

这是我想要达到的效果: http://codepen.io/anon/pen/ENzQem

我正在尝试生成一种效果,其中字符串的字母会逐渐随机显示。请参阅上面的 codepen link 进行演示。

但是,如果我只是简单地分别为每个延迟随机生成数字,我发现很难自然地显示每个字符。

如果我简单地做一个 Math.random() 来为每个字符独立生成一个数字,有时相邻的字母会有相似的延迟数字,因此效果会看起来很厚实,两个字母并排出现率相同。

这是带有独立随机数生成器的简单解决方案:

  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>;
    });
  }

我需要一种算法来生成一个数字数组,无论输入字符串的长度如何,我都可以将其用作每个字符的延迟。

我的第一个想法是使用某种正弦波,加入一些随机性,但我不确定这方面的细节。我相信在数学中有一种更容易被接受的方法来产生看起来自然的噪音。

有人可以为我的用例指出一些著名的算法吗?也许与 Perlin 噪声等有关?

提前致谢。

原来是我想多了

我最终创建了以下函数:

const getRandoms = (length, threshold) => {
  const tooClose = (a, b) => Math.abs(a - b) < threshold;

  const result = [];
  let random;

  for (let i = 0; i < length; i += 1) {
    random = Math.random();
    if (i !== 0) {
      const prev = result[i - 1];
      while (tooClose(random, prev)) {
        random = Math.random();
      }
    }
    result.push(random);
  }
  return result;
};

我最初编写了此函数的一个版本,它使用 reduce 而不是 for 循环,但最终决定 for 循环会更清晰、更简单。

工作原理

此函数在给定所需长度和 "closeness" 阈值的情况下,按程序构建随机数数组。与数组中的前一个数字相比,每个生成的随机数的差值都大于阈值。

  1. 对于数组中的第一项,我们简单地生成一个随机数并将其推入。

  2. 对于数组中的每个后续项目,我们:

    • 生成一个新的随机数,
    • 将这个数字与数组中的前一个数字进行比较,
    • 如果它们太接近(即差异<阈值),则生成一个新的随机数并再次比较,
    • 如果它们不太接近,则将其推入结果数组并继续。

我发现 0.2 的阈值似乎非常适合我的用例。