3

I want my 5 texts to disappear using transition and then appear - using transition again, so like a small animation.

You can see my snippet here: https://codepen.io/makiwara/pen/abOVKBP

or here:

<h1>text1</h1>

h1{
  opacity: 1;
}

.hide {
  opacity: 0;
  transition: opacity 1000ms;
}

let i=0;
setInterval(function(){

var myArray = [
  "text1",
  "text2",
   "text3",
   "text4",
   "text5"
]

i=i+1;
if (i>4){
    i=0;
}

let name = myArray[i];
document.querySelector("h1").innerText=name;
document.querySelector("h1").classList.add="hide";
},3000);

And this is the snippet where I see the solution, however no matter how hard I try, I just can't implement that: https://codepen.io/zvona/pen/LVxxjM

Thank you very much if you have any ideas! I feel hopeless now! Have a nice day!

Temani Afif
  • 245,468
  • 26
  • 309
  • 415

2 Answers2

0

Your way of adding class to classlist is incorrect.

Replace it with this line of code:

document.querySelector("h1").classList.add("hide");

Though it is not exactly how you want it to work, but the transition effect is getting applied.

Shruti B
  • 128
  • 1
  • 9
0

You could do something like this:

Version 1: using transitionend event

const myArray = [
        "text1",
        "text2",
        "text3",
        "text4",
        "text5"
      ],
     container = document.querySelector("h1"),
     transitionEndEvent = whichTransitionEvent();
let i = 0;

(function loop() {
  // Add the "hide" class
  setTimeout(()=> container.classList.add('hide'), 0);
  // Wait for the animation to end
  addEventListenerOnce(container, transitionEndEvent, () => {
    // Change the text
    container.innerHTML = myArray[i];
    // Remove the class
    container.classList.remove('hide');
    // Wait for the animation to end
    addEventListenerOnce(container, transitionEndEvent, () => {
      i = ++i % myArray.length;
      // Show the text for 1 second and continue
      setTimeout(loop, 1000);
    });
  });
})();

// Just a utility function to trigger an event handler once
function addEventListenerOnce(el, eventName, callback) {
  el.addEventListener(eventName, handler);
  function handler() {
    el.removeEventListener(eventName, handler);
    callback.call(el);
  }
}

// The name of the event depends on the browser
function whichTransitionEvent(){
  var t, el = document.createElement("fakeelement");

  var transitions = {
    "animation"      : "transitionend",
    "OAnimation"     : "oTransitionEnd",
    "MozAnimation"   : "transitionend",
    "WebkitAnimation": "webkitTransitionEnd"
  }

  for (t in transitions){
    if (el.style[t] !== undefined){
      return transitions[t];
    }
  }
}
h1{
  opacity: 1;
  transition: opacity 300ms;
}

.hide {
  opacity: 0;
}
<h1></h1>

About the whichTransitionEvent function

Browsers have different names for the transitionend event. This utility function will select the right one for the current browser. I found the inspiration for it here.

About the loop function

As you can see, that function is wrapped in (function loop() {...})();. That is called an IIFE (Immediately-Invoked Function Expression). We call the function as we're declaring it. In this case, it will also call itself recursively.

About the i = ++i % myArray.length; line

Here, we're using the modulo operator to make things shorter. But it's equivalent to this:

i++;
if (i >= myArray.length) { i = 0; }

Version 2: using setTimeout

Unlike the version above, you'll need to manually edit the animation duration in the JS if you do change it in the CSS. But it removes a lot of code:

const myArray = [
        "text1",
        "text2",
        "text3",
        "text4",
        "text5"
      ],
     container = document.querySelector("h1"),
     animationDuration = 300; // in milliseconds
let i = 0;

(function loop() {
  // Add the "hide" class
  container.classList.add('hide');
  // Wait for the animation to end
  setTimeout(function() {
    // Change the text
    container.innerHTML = myArray[i];
    // Remove the class
    container.classList.remove('hide');
    // Wait for the animation to end
    setTimeout(function() {
      i = ++i % myArray.length;
      // Show the text for 1 second and continue
      setTimeout(loop, 1000);
    }, animationDuration);
  }, animationDuration);
})();
h1{
  opacity: 1;
  transition: opacity 300ms;
}

.hide {
  opacity: 0;
}
<h1></h1>
blex
  • 24,941
  • 5
  • 39
  • 72
  • Thank you blex! It works perfectly and your knowledge is fascinating! However to be honest I don't understand every line of your code yet, I am a newbie in JS unfortunately, but I will analyize it. The other codepen snippet could solve this a little more simple - maybe that solution is a lot worse than yours, but I would feel more comfortable to edit that. Can this problem be solved using that codepen method as well? I couldn't find a way but if this is possible, just give me a little hope and I will keep up trying. –  Mar 07 '20 at 22:14
  • That solution is actually using both solutions you mentioned. But to join together the animation and the loop, it takes some code :-) (you need to wait for transitions to end) – blex Mar 07 '20 at 22:28
  • @makiwara I made a simpler version, is that better? – blex Mar 07 '20 at 22:43
  • You are my hero! I can't tell you how happy I am now! Thank you very much! :D –  Mar 08 '20 at 08:45