typewriting effect using generator and yield

huangapple go评论61阅读模式
英文:

typewriting effect using generator and yield

问题

以下是您要的代码部分的翻译:

我正在尝试使用JavaScript创建打字机效果我想先写第一句然后是第二句依此类推

我尝试使用`setTimeout`来实现它它运行得很好但我想添加更多句子并使用`generators`来添加更多句子但我非常难以弄清楚并将我的代码转换为`generator`函数因为`setTimeout`是嵌套的并且在循环中

这是我使用`setTimeout`的代码

```html
<!-- 开始代码片段: js 隐藏: false 控制台: true Babel: false -->

<!-- 语言: lang-js -->
const s1 = `我是句子1`;
const s2 = `我是句子2`;

s1.split('').forEach((ch, i) => {
  setTimeout(c => {
    document.querySelector('h1').textContent += c
  }, i * 70, ch)
});
setTimeout(() => {
  s2.split('').forEach((ch, i) => {
    setTimeout(c => {
      document.querySelector('h2').textContent += c
    }, i * 100, ch)
  });
}, s1.length * 70)

<!-- 语言: lang-html -->
<h1></h1>
<h2></h2>

<!-- 结束代码片段 -->

请帮助我使用generator来实现,谢谢!


<details>
<summary>英文:</summary>

I am trying to create a typewriter effect using javascript, I want to write the first sentence first, then second sentence and so on.

I tried doing it using using `setTimeout` and it is working fine, but I want to add more sentences and do it using `generators` to add more sentences, but I am having really hard time to figure it out and translate my code to `generator` function because `setTimeouts` are nested and are in loops.

This is my code using `setTimeout`:

&lt;!-- begin snippet: js hide: false console: true babel: false --&gt;

&lt;!-- language: lang-js --&gt;

    const s1 = `I am sentence 1`;
    const s2 = `I am sentence 2`;

    s1.split(&#39;&#39;).forEach((ch, i) =&gt; {
      setTimeout(c =&gt; {
        document.querySelector(&#39;h1&#39;).textContent += c
      }, i * 70, ch)
    });
    setTimeout(() =&gt; {
      s2.split(&#39;&#39;).forEach((ch, i) =&gt; {
        setTimeout(c =&gt; {
          document.querySelector(&#39;h2&#39;).textContent += c
        }, i * 100, ch)
      });
    }, s1.length * 70)

&lt;!-- language: lang-html --&gt;

    &lt;h1&gt;&lt;/h1&gt;
    &lt;h2&gt;&lt;/h2&gt;

&lt;!-- end snippet --&gt;

Please help me doing it using `generator`, thank you!



</details>


# 答案1
**得分**: 3

```javascript
不使用生成器,而是创建一个setTimeout的Promise包装器,并将代码放在一个异步方法中。这样,您可以像同步代码一样编写您的代码(当然它不是)。

function delay(ms){
return new Promise(res => setTimeout(res, ms));
}

async function typewriter() {
let sentences = ["...", "...", ...]

for (let s of sentences){
let e = document.querySelector(...); //找到正确的元素
for (let c of s){
e.textContent += c;
await delay(50); //每个字符后等待
}

await delay(100); //在句子之间等待 

}
}


这只是基础部分。不知道您将如何找到每个句子的相应DOM元素。我只是假设您有某种方式,元素将存在(如果不存在,这段代码将抛出错误)。
英文:

I'd not do it with a generator, but create a promise wrapper for setTimeout and place the code in an async method. This way you can write your code like it was synchronous (but of course it isn't)

function delay(ms){ 
  return new Promise(res =&gt; setTimeout(res, ms));
}

async function typewriter() {
  let sentences = [&quot;...&quot;, &quot;...&quot;, ...]

  for (let s of sentences){
    let e = document.querySelector(...); //find the correct element 
    for (let c of s){
      e.textContent += c;
      await delay(50); //wait after each character
    }

    await delay(100); // wait between sentences 
  }
}

This is just the basics. Don't know how you will find the respective DOM element for each sentence. I just assumed you have some way and the elements will exit ( thus this code will throw an error if it doesn't)

答案2

得分: 3

使用 generator 的实现可能如下所示:

function* generator(str) {
    yield* str;
}

const addSentence = (element, sentence, done) => {
    const gen = generator(sentence);
    const el = document.querySelector(element);
    const interval = setInterval(() => {
        const ch = gen.next().value;
        if (!ch) {
            clearInterval(interval);
            if (done) {
                done();
            }
            return;
        }
        el.textContent += ch;
    }, 100);
}

addSentence('h1', 'Sentence 1', () => {
    addSentence('h2', 'Sentence 2');
});
<h1></h1>
<h2></h2>

请让我知道这是否有帮助。

英文:

The implementation using generator may look like this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function* generator(str) {
    yield* str;
}

const addSentence = (element, sentence, done) =&gt; {
  const gen = generator(sentence);
  const el = document.querySelector(element);
  const interval = setInterval(() =&gt; {
    const ch = gen.next().value;
    if (!ch) {
      clearInterval(interval);
      if (done) {
        done();
      }
      return;
    }
    el.textContent += ch;
  }, 100);
}
addSentence(&#39;h1&#39;, &#39;Sentence 1&#39;, () =&gt; {
  addSentence(&#39;h2&#39;, &#39;Sentence 2&#39;);
}); 

<!-- language: lang-html -->

&lt;h1&gt;&lt;/h1&gt;
&lt;h2&gt;&lt;/h2&gt;

<!-- end snippet -->

Please let me know if this helps.

huangapple
  • 本文由 发表于 2023年3月8日 15:37:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670385.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定