【问题标题】:How can I create animated letter increments of a given word similar to the way animated number counters work?如何创建给定单词的动画字母增量,类似于动画数字计数器的工作方式?
【发布时间】:2016-10-19 22:32:42
【问题描述】:

我正在创建一个“动画字母增量器”,它采用任何给定的单词并从 A 开始递增该单词的每个字母。

例子:

Word = Dog

D - Increments from A to D [A, B, C, D]
O - Increments from A to O [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O]
G - Increments from A to G [A, B, C, D, E, F, G]

我想要达到的效果类似于jQuery animated number counter,除了我将增加字母而不是计数数字。此外,单词的每个字母都应该独立递增,但它们都应该同时到达目标字母。

JS:

var wordToIncrement = 'DOG';
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '.split('');

for (var i = 0, len = wordToIncrement.length; i < len; i++) {

    var letterToIncrementTo = wordToIncrement[i];

    var arrayLength = alphabet.length;
    for (var z = 0; z < arrayLength; z++) {

        var alphabetLetter = alphabet[z];

        if (alphabetLetter == letterToIncrementTo) {

            console.log('MATCH FOUND!');
            console.log('Word Letter: ' + letterToIncrementTo);
            console.log('Alphabet Letter: ' + alphabetLetter);

            alphabetPositionValue = z;
            console.log('VALUE: ' + alphabetPositionValue);

            function incrementToLetter(letterToIncrementTo,alphabetPositionValue) {

                // This is where I'm stuck

                var div = document.getElementById('#word_block');
                div.innerHTML = div.innerHTML + 'Extra stuff';


            }

        }

    }

}

HTML:

<div id="work_block"></div>

如何完成上面的代码以实现与动画数字计数器示例类似的功能并通过单词的每个字母递增?我正在寻找基于 javascript 的解决方案。

【问题讨论】:

    标签: jquery jquery-animate increment letters alphabet


    【解决方案1】:

    我会构建一个字母对象来维护字母和时间。这样您就可以在对象上提供简单的更新功能,并且对象本身会确保它产生正确的当前字母。

    例如:

    function Letter(table, letter, duration) {
      this.table = table;                          // lookup-table
      this.letter = letter;                        // target letter
      this.current = 0;                            // index in table
      this.delay = duration / tbl.indexOf(letter); // ms
      this.time = Date.now();                      // current (start) time
      this.done = false;                           // status
    }
    

    然后是一个通用原型update()方法:

    Letter.prototype.update = function() {
      if (this.done) return;                       // if done, do no more
      var time = Date.now();                       // get current time
      if (time - this.time >= this.delay) {        // exceeded delay?
        this.time = time;                          // store current time
        if (this.letter === this.table[this.current] || 
            this.current === this.table.length) {  // target reached? unknown letter
          this.done = true;                        // we're done
        }
        else {
          this.current++;                          // next in table
        }
      }
    };
    

    然后我们可以从字符串中生成对象:

    var letters = [];
    word.toUpperCase().split("").forEach(function(l) {
      letters.push(new Letter(tbl, l, 2500));  // 2.5s duration
    });
    

    然后对其进行动画处理:

    (function loop() {
       var txt = "", isDone = true;
       letters.forEach(function(l) {
         l.update();
         if (!l.done) isDone = false;
         txt += l.table[l.current];
       });
    
       // output txt
       if (!isDone) requestAnimationFrame(loop);
       else { /* done */ }
    })();
    

    演示

    function Letter(table, letter, duration) {
      this.table = table;
      this.letter = letter;
      this.current = 0;
      this.delay = duration / tbl.indexOf(letter);   // ms
      this.time = Date.now();
      this.done = false;
    }
    Letter.prototype.update = function() {
      if (this.done) return;
      var time = Date.now();
      if (time - this.time >= this.delay) {
        this.time = time;
        if (this.letter === this.table[this.current] || 
            this.current === this.table.length) {
          this.done = true;
        }
        else {
          this.current++;
        }
      }
    };
    
    var word = "hello there";
    var tbl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var letters = [];
    word.toUpperCase().split("").forEach(function(l) {
      letters.push(new Letter(tbl, l, 2500))
    });
    
    (function loop() {
      var txt = "", isDone = true;
      letters.forEach(function(l) {
        l.update();
        if (!l.done) isDone = false;
        txt += l.table[l.current];
      });
    
      // output txt
      d.innerHTML = txt;
      
      if (!isDone) requestAnimationFrame(loop);
      else { /* done */ }
    })();
    #d {font:bold 32px monospace}
    &lt;div id=d&gt;&lt;/div&gt;

    杂项

    如果延迟低于 16.7 毫秒,它的增量可能不够快。它可以通过将当前相对时间除以持续时间来解决。将此归一化值与表中目标字母的索引相乘,得到一个电流,只需将结果四舍五入为整数值。

    您可以提供不同的表格来获得随机性/变异性。

    【讨论】:

    • 感谢您的出色解决方案!完美运行!
    • 如果字符串有空格怎么办?我怎样才能忽略那些未定义的空间?再次感谢您的帮助!
    • @cpcdev 对于空格只需将空格(以及您想要支持的任何其他字符)添加到表中。您可以使用 jQuery 向显示文本的元素添加动画。要为每个字母设置动画,您可以简单地修改 Letter 对象以支持这一点(例如颜色/不透明度)并使用当前时间与持续时间来计算进度(t=[0,1] x 效果)。
    • 我忘了说 requestAnimationFrame 确实提供了时间戳,但旧的 Safari/Opera/IE 不支持它。如果这些不重要,则可以将 Date.now() 替换为此时间戳。虽然在这里不是那么重要,但我想为未来的读者提一下。
    • 感谢您的回复。我像您提到的那样在表格中添加了空格并且它有效,但是如果您在递增期间添加两个单词,例如“hi there”,它会显示为一个单词,直到递增完成。有什么办法可以在递增期间显示空间?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多