简体   繁体   中英

Vanilla Javascript information ticker with setTimeout delay infinite loop

I'm trying to display an information ticker using purely just vanilla JS (no jQuery etc).

I have a div <div class="postcode-panel"></div> with some text saying:

Latest information for XXX - This is to be displayed for 3 seconds

This div then fades out of view and displays the next div <div class="rating-panel"></div> with the text saying:

Rating 5.4 - This is to be displayed for 15 seconds.

Once the div .rating-panel has been viewed for 15 seconds then the first div .postcode-panel then loops back and displays for 3 seconds and this then just loops infinitely. I'm controlling the fade out animations with CSS, but I'm having difficulty getting all the different timeouts to work in the JS.


Update: I've managed to update my code to get the code to show and hide but I can't get it to it within the correct timings.

Here is a JS Fiddle .

And below is my code

 function postcode () { var postcodePanel = document.querySelector(".postcode-panel"); var ratingPanel = document.querySelector(".rating-panel"); var activeClass = 'active'; function start() { setTimeout(function() { setTimeout(function(){ postcodePanel.classList.remove(activeClass); ratingPanel.classList.add(activeClass); }, 3000); setTimeout(function(){ start(); }, 15000); postcodePanel.classList.add(activeClass); ratingPanel.classList.remove(activeClass); },100); } start(); } window.addEventListener('load', postcode);
 .info-panel { position:relative; background:blue; color:white; padding:20px; font-size:20px; }.postcode-panel { display:block; position:absolute; opacity: 0; }.postcode-panel.active { animation:ticker-pc 3s; }.rating-panel { opacity: 0; }.rating-panel.active { animation:ticker-rr 12s; } @keyframes ticker-pc { 0% { opacity: 0; -webkit-transform:translateY(30px); transform:translateY(30px); } 10% { opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 50% { opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 90% { opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 100% { opacity: 0; -webkit-transform:translateY(-30px); transform:translateY(-30px); } } @keyframes ticker-rr { 0% { opacity: 0; -webkit-transform:translateY(30px); transform:translateY(30px); } 2% { opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 50% { opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 97% { opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 100% { opacity: 0; -webkit-transform:translateY(-30px); transform:translateY(-30px); } }
 <div class="info-panel"> <div class="postcode-panel active"> <span class="latest-info"> Latest information for <span class="postcode-info"> XXX </span> </span> </div> <div class="rating-panel"> <span class="rating"> Rating <span class="score">5.4</span> </span> </div> </div>

You were using the setTimeout out a bit inaccurately. I have provided a solution using promises which is a bit more readable. Working fiddle: https://jsfiddle.net/jdc91xt/73dchfax/23/

function postcode() {
  var postcodePanel = document.querySelector(".postcode-panel");
  var ratingPanel = document.querySelector(".rating-panel");
  var activeClass = 'active';
  let elapsedTime = new Date().getTime();

  function showPostCodePanel() {
    let currentTime = new Date().getTime();
    console.log("showing postcode panel after ms", currentTime - elapsedTime)
    elapsedTime = currentTime
    postcodePanel.classList.add(activeClass);
    ratingPanel.classList.remove(activeClass);
  }

  function showRatingPanel() {
    let currentTime = new Date().getTime();
    console.log("showing postcode panel after ms", currentTime - elapsedTime)
    elapsedTime = currentTime
    postcodePanel.classList.remove(activeClass);
    ratingPanel.classList.add(activeClass);
  }

  function start() {
    showPostCodePanel()

    let wait3Seconds = new Promise((res) => setTimeout(res, 3000));
    wait3Seconds.then(() => {
      showRatingPanel()
      let wait15Seconds = new Promise((res) => setTimeout(res, 15000));
      wait15Seconds.then(() => {

        start();
      });

    })

  }
  start();
}
window.addEventListener('load', postcode);

If you check the console you will see almost accurate times logged:)

Here is a javascript code to show the first div for 3 sec and the next for 15 sec and then repeat this. The solution here is purely javascript based, and so I have removed the css related animations.

Javascript code ->

function postcode () {
        var postcodePanel = document.querySelector(".postcode-panel");
        var ratingPanel = document.querySelector(".rating-panel");
        var activeClass = 'active';
        
        
        
        function next(timer){
            alert("in next after 15 sec")
            postcodePanel.style.display = "none";
            ratingPanel.style.display = "block";
            setTimeout(function(){
                 seq();
                }, timer);
        }
        
        function seq(){
                postcodePanel.style.display = "block";
                ratingPanel.style.display = "none";
                setTimeout(function(){
                next(15000)
                },3000)
        
        }
        seq();
}
    window.addEventListener('load', postcode);

The jsfiddle link ->

https://jsfiddle.net/4ur5dpoa/1/

You don't specially need JavaScript for this. You can have two animations, as you do now, but both lasting 18 seconds and with percentages set so that the relevant text shows for 3 seconds or 15 seconds.

You get a lot of fine control with keyframes and you may like to play around with the percentages to get exactly what you want, but without needing JS to run your animations you should find that the user's GPU is invoked and does the work for you.

 .info-panel { position:relative; background:blue; color:white; padding:20px; font-size:20px; }.postcode-panel { display:block; position:absolute; opacity: 0; animation:ticker-pc 18s infinite; animation-fill-mode: forwards; }.rating-panel { opacity: 0; animation:ticker-rr 18s infinite; animation-fill-mode: forwards; } @keyframes ticker-pc { 0% { opacity: 0; -webkit-transform:translateY(30px); transform:translateY(30px); } 1.66666% {/* gets into view at full opacity after 0.3seconds */ opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 16.66666% {/* stays there for 3 seconds - 0.3 seconds */ opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 18.33332% {/* goes out at the top and fades away after 0.3 seconds */ opacity: 0; -webkit-transform:translateY(-30px); transform:translateY(-30px); } 100% { opacity: 0; -webkit-transform:translateY(-30px); transform:translateY(-30px); } } @keyframes ticker-rr { 0% { opacity: 0; -webkit-transform:translateY(30px); transform:translateY(30px); } 16.6667% { /* wait for 3 seconds */ opacity: 0; -webkit-transform:translateY(30px); transform:translateY(30px); } 18.33332% {/* get into view at full opacity after 0.3seconds */ opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 98.33334% {/* stay in full view for rest of time -0.3 seconds */ opacity: 1; -webkit-transform:translateY(0); transform:translateY(0); } 100% { opacity: 0; -webkit-transform:translateY(-30px); transform:translateY(-30px); } }
 <div class="info-panel"> <div class="postcode-panel"> <span class="latest-info"> Latest information for <span class="postcode-info"> XXX </span> </span> </div> <div class="rating-panel"> <span class="rating"> Rating <span class="score">5.4</span> </span> </div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM