Home > Software design >  Backwards typing effect
Backwards typing effect

Time:12-03

I am trying to get a backwards typing effect with my code. So the <P> will say "Coming Soon" then type backwards. Then type forwards into "SeaDogs.com.eu.as"

This is what I have so far, for some reason it type coming soon backwards twice??? Which is my first hurtle I'm trying to overcome. And trying to delay it so it shows the word "Coming soon" for a few seconds.

var str = 'Coming Soon';
var remove = false;
var i = str.length;
var isTag;
var text;

(function type() {
  if (!remove) {
    text = str.slice(0, --i);
    if (text === str) return;
  }

  if (!isTag) {
    document.getElementById("demo").innerHTML = text;
  }



  setTimeout(type, 520);

}());
<p id="demo"></p>

CodePudding user response:

It's much cleaner to code the logic directly with async/await rather than to fiddle with timeouts:

function delay(time) {
    return new Promise(r =>
        setTimeout(r, time))
}

async function typeAnimation(div, rtl, text, time) {
    for (let i = 1; i <= text.length; i  ) {
        div.innerText = text.slice(0, rtl ? -i :  i)
        await delay(time)
    }
}

async function main() {
    let div = document.querySelector('h1')
    await typeAnimation(div, true, 'Coming soon...', 100)
    await typeAnimation(div, false, 'and here it comes!', 100)
}

main()
<h1></h1>

CodePudding user response:

I would create two functions with a promise

const demo = document.querySelector('#demo')

const initial = "Coming Soon"
const later = "SeaDogs.com.eu.as"

remove(initial).then(() => add(later))

function remove(text) {
  let i = text.length
  return new Promise(r => {
    removeCharacter()

    function removeCharacter() {
      if (i < 0) {
        r()
        return
      }
      const copy = text.slice(0, i)
      demo.textContent = copy

      setTimeout(removeCharacter, 100)
      i -= 1
    }
  })
}

function add(text) {
  let i = 0
  return new Promise(r => {
    removeCharacter()

    function removeCharacter() {
      if (i > text.length) {
        r()
        return
      }
      const copy = text.slice(0, i)
      demo.textContent = copy

      setTimeout(removeCharacter, 100)
      i  = 1
    }
  })
}
<p id="demo"></p>

CodePudding user response:

Your exit clause is incorrect - you check if substring of str == str - which it never will.

You get it twice because of the way .slice works with a negative index

  • .slice(0, 8) -> start to 8th character
  • .slice(0, -2) -> start to 2 characters from the end

You can change the exit clause from if (text === str) return to

if (text === "") return;

or

if (i === 0) return;

Depending on when you want it to end - as your exit clause is before the output, this will leave the last character, so instead:

if (i<0) return;

var str = 'Coming Soon';
var remove = false;
var i = str.length;
var isTag;
var text;

(function type() {
  if (!remove) {
    text = str.slice(0, --i);
    //console.log(i, text)
    if (i < 0) return;
  }

  if (!isTag) {
    document.getElementById("demo").innerHTML = text;
  }

  setTimeout(type, 150);

}());
<p id="demo"></p>

However, I expect there's some mix up between remove and !remove as you have not-remove (ie add) with --i. So when adding, you do need to check text==str

CodePudding user response:

Here is a modified version of your code that should achieve the desired effect:

var str = 'Coming Soon';
var delay = 5000; // delay in milliseconds before typing backwards
var remove = false;
var i = str.length;
var isTag;
var text;

(function type() {
  if (!remove) {
    text = str.slice(0, --i);
    if (text === str) {
      // wait for the delay before typing backwards
      setTimeout(function() {
        remove = true;
        i = 0;
      }, delay);
      return;
    }
  } else {
    text = str.slice(0,   i);
    if (text === str) {
      // typing forwards is done, append the rest of the text
      document.getElementById("demo").innerHTML  = ".com.eu.as";
      return;
    }
  }
  if (!isTag) {
    document.getElementById("demo").innerHTML = text;
  }
  setTimeout(type, 520);
}());
<p id="demo"></p>

  • Related