Rotating an array of text in a loop with transitions...

Hi there,

I’m trying to get some text to do the following:

  1. slide in from the left

  2. hold for a moment

  3. slide out to the right

  4. select the next text in the array

  5. repeat

I used the example code at https://russian-dima.wixsite.com/meinewebsite/test-1 as a starting point, but that has a few issues that I’m not dealing with:

  1. it does not have any transition effects, instead, it just changes the text

  2. it uses buttons to turn the effect on/off

Here’s what I have so far, but if you try it, you’ll see that it’s not doing quite right. It appears that the change on the array is happening prior to the transition out and then it gets out of sync very fast. In addition, there’s a long delay at page load.

var i = 0 
var counter=0
var myTimerValue = 3000
var myDelayTime = 1500
var myArray = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7"]
 
let myVar = setInterval(myFunction, myTimerValue);
 
let hideOptions = {
    "duration":  myTimerValue,
    "direction" : "right"
};
 
let showOptions = {
    "duration":  myTimerValue,
    "direction" : "left"
};
 
function myFunction() {console.log(counter++)
    $w('#text01').hide()
    $w('#text01').show('slide', showOptions)
 
    if (myArray[i]===undefined) { i = 0,
     $w('#text01').text="Item 0", stopFunction(), console.log("Function stopped")
     setTimeout(()=>{myVar = setInterval(myFunction, myTimerValue)},myDelayTime)
    }
    else {
        return $w('#text01').text=myArray[i], i = i+1
    } 
}; 

function stopFunction() {clearInterval(myVar);};

I’d love to get some thoughts on how to get this to work better.

Thank you in advance for your help,

Michael

Why no transition effects?
What do you see on your screen ?

The same like this … ???

Transition-effects working for me → fade-in + slide-out…

That was a quick modified code…


var i = 0, counter=0, myTimerValue = 3000;
var myArray = ["fast", "expensive", "useful", "a womanizer", "super-fast", "economic"];
let myVar = setInterval(myFunction, myTimerValue);

$w.onReady(function() {
  /*
  //starting the whole interval with a click-action...
  $w('#BTNstart').onClick(()=>{
    $w('#BTNstop').enable(), myVar = setInterval(myFunction, myTimerValue);
  });
  */
  
  $w('#BTNstop').enable(), myVar = setInterval(myFunction, myTimerValue);
 
  $w('#BTNstop').onClick(()=>{
    $w('#text1').hide('fade'); $w('#BTNstop').disable(), stopFunction(), setTimeout(()=>{myVar},100);
  });
});
 
async function myFunction() {console.log(counter++)
    await $w('#text1').show('fade')
    await $w('#text1').hide('slide')
    
    $w('#BTNstop').enable()
    if (myArray[i]===undefined) { i = 0,
     $w('#text1').text="END", stopFunction(), console.log("Function stopped")
     setTimeout(()=>{myVar = setInterval(myFunction, myTimerValue)},1000)
 
    }
    else {
        return $w('#text1').text=myArray[i], i = i+1} $w('#BTNstop').disable()}
 
function stopFunction() {clearInterval(myVar);}

Surely this can be improved!

So, again… No buttons. Also, I want it to come in from the right and go out to the left.

After I removed the buttons and added direction control, I’m still seeing a ridiculous lag before it starts to loop and before it ends.

Here’s the current code:

var i = 0, counter=0, myTimerValue = 3000;
var myArray = ["array00", "array01", "array02", "array03", "array04", "array05"];
let myVar = setInterval(myFunction, myTimerValue);

let hideOptions = {
    "direction" : "right"
};

let showOptions = {
    "direction" : "left"
};
 
async function myFunction() {console.log(counter++)

    await $w('#text01').show('slide', hideOptions)
    await $w('#text01').hide('slide', showOptions)
    
    if (myArray[i]===undefined) { i = 0,
     $w('#text01').text="end word", stopFunction(), console.log("Function stopped")
     setTimeout(()=>{myVar = setInterval(myFunction, myTimerValue)}) 
 
    }
    else {
        return $w('#text01').text=myArray[i], i = i+1} 
    }
 
function stopFunction() {clearInterval(myVar);}

$w.onReady(function () {

   
});

Still not doing what it should.

So, again… No buttons.
No buttons were used in my second provided version (except the STOP-Button).
Greyed-out code-parts are inactive while runtime.

   
/*
  //starting the whole interval with a click-action...
  $w('#BTNstart').onClick(()=>{
    $w('#BTNstop').enable(), myVar = setInterval(myFunction, myTimerValue);
  });
  */

Also, I want it to come in from the right and go out to the left.
Which animations you are using and how you want to animate, it’s on you…
EXAMPLE:

$w('#text01').show('slide', {direction: "left", duration: 500, delay: 0});
$w('#text01').show('float', {direction: "top", duration: 300, delay: 0});
$w('#text01').show(fade', {duration: 300, delay: 0});

Try this improved one…

const txtElementID = "#text1"

$w.onReady(function() {
  const intervalClocking = 1500; 
  const restartInterval = 3000; 
  const hideOptions = {"direction":"right", duration:500, delay:0};
  const showOptions = {"direction":"left", duration:500, delay:0};
  const myArray = ["TEXT-1", "TEXT-2", "TEXT-3", "TEXT-4", "TEXT-5", "TEXT-6"];

  let i = 0, myVar = setInterval(myFunction, intervalClocking);

  async function myFunction() {show_Values();
    if (myArray[i]===undefined) {i = 0, stopFunction();
      $w(txtElementID).text= await "End-Run", 
      setTimeout(()=>{
        myVar=setInterval(myFunction, intervalClocking)
      },restartInterval);
    } else {return $w(txtElementID).text=myArray[i], i = i+1} 
  }
  function stopFunction() {clearInterval(myVar);}

  async function show_Values() {
    await $w('#text1').show('slide', hideOptions);
    await $w('#text1').hide('slide', showOptions);
  }
});

So, I see that we’ve got it running through, but there are issues with a few things still:

  1. There is still a delay at both the load and repeat.

  2. The speed is super fast and changing the delay or duration gets things out of sync.

  3. I don’t understand what the relationships are between intervalClocking, restartInterval, and the effect’s duration and delay.

I assume that (a) intervalClocking is the time between animating out, switching, and animating in; and (b) restartInterval is the time that it takes the function to repeat.

Duration and delay are obvious, but the script doesn’t seem to respect the time that is put in there, so it gets out of sync.

Can you please explain (either in prose or by commenting the code) what your expectations of the intervals are meant to do? It’s not obvious to me at all and each time I try to make changes, it screws up the timing/sync.

You have an INTERVAL → which is clocking a specific preseted amount of time.
Let us say → ClockRate would be → 1000 msecs. (1-sec.).

const intervalClocking=1000; // ----> 1ces.

That means you have running an INTERVAL which is doing something every second. In this case → myFunction() get fired every second.

This functions looks like this…

async function myFunction() {show_Values();
    if (myArray[i]===undefined) {i = 0, stopFunction();
      $w(txtElementID).text = await "End-Run", 
       setTimeout(()=>{
         myVar = setInterval(myFunction, intervalClocking);
       },restartInterval);
    } else {return $w(txtElementID).text=myArray[i], i = i+1} 
  }

When ARRAY runs out of values → when the last one is reached, the interval gets stopped, but will be restarted again after a certain amount of time.

And this is your …

const restartInterval = 3000;

That means → between END and RESTART you will loose 3secs. until a new INTERVAL starts again.

Another thing to take attention at is → the duration time of your animations.
You have to calculate your total animations-time and set a related CLOCKING-TIME to make sure everything will work well.

Example: You have 2x animations running one after another → 2x500msecs = 1000
That means you should not set your INTERVAL-CLOCK-RATE under 1000msecs.

You should give it even some more timing space → 1500msecs, this way you make sure, that your animations will end before a new CLOCKING of the INTERVAL starts.

Of course you can also make all that more dynamic → so you won’t need to calculate all timings and clockings by your own.

But this will be your own task.

Improve your CODE and make somethign great of this example.
Perhaps you will show us the result when you are done with your UPGRADES :wink:

BTW: In my example, everything works just well…

https://russian-dima.wixsite.com/login-system

That’s helpful. thank you.

Here’s my final commented code for anyone interested in a clean final drop-in version:

$w.onReady(function() {

    // THIS ONLY REQUIRES TIME ADJUSTMENT TO fxDuration & fxDelay
    // AND SETTING THE TEXT ELEMENTS

    // It is best to use a container to hold the text object that loads using animation effects set to:
    // slide, .85 sec, medium intensity and no delay

    // object that switches text
        const txtElementID = "#text1";

    // Effect duration & delay
        const fxDuration = 850;
        const fxDelay = 50;
    // How quickly does the whole thing restart
        const restartInterval = 0;
              
    // ENTER THE LAST WORD OF THE ARRAY
        const firstWordlastWord = "TEXT-6";
    // Words to switch from second word forward
        const myArray = ["TEXT-1", "TEXT-2", "TEXT-3", "TEXT-4", "TEXT-5"];

    // Transition fx
        const hideOptions = {"direction":"right", duration:fxDuration, delay:fxDelay};
        const showOptions = {"direction":"left", duration:fxDuration, delay:fxDelay};

    // How often the function triggers
        const intervalClocking = ((fxDuration + fxDelay)*2.5); 

    // This sets up the first string and the timing
    let i = 0, myVar = setInterval(myFunction, intervalClocking);

    // Here is the function that rotates the text then restarts
        async function myFunction() {show_Values();
            if (myArray[i]===undefined) {i = 0, stopFunction();
                $w(txtElementID).text= await firstWordlastWord, 
                setTimeout(()=>{
                myVar=setInterval(myFunction, intervalClocking)
                },restartInterval);
            } else {return $w(txtElementID).text=myArray[i], i = i+1} 
        }
  
    function stopFunction() {clearInterval(myVar);}

    // This animates the text in and out
    async function show_Values() {
        await $w('#text1').show('slide', showOptions);
        await $w('#text1').hide('slide', hideOptions);
  }

});

Perhaps you also can show a short video of what you got (which animation) and how the result looks like, when using your code?

Just for the interested ones …

Sure thing…