I'm pretty new to javascript and I have a question. I'm currently trying to make a loading bar change color and reset after it has reached 100%, but the main issue is, or at least I think my if statement is invalid. Anyway to test for color and width of an element? Thanks.
function upg_01() {
if (cash >= priceUpg_01) {
var width = 0;
width = width + 20;
a.style.width = width + '%';
priceUpg_01 = priceUpg_01 * 10;
multiplier_01 = multiplier_01 * 3;
}
if (document.getElementById('upg_01c').style.color === "green" &&
document.getElementById('upg_01c') === 100 + '%') {
document.getElementById('upg_01c').style.color = "yellow";
document.getElementById('upg_01c').style.width = 0 + '%';
}
const timer = setInterval( () => {
// select the progress bar element
const progressBar = document.getElementById('progress-bar');
// get the innerHTML of the progess bar
// doubling as our progress state/value
let progress = parseInt( progressBar.innerHTML );
// arbitrary addition/growth of the progress
progress += 3;
// check if progress has met or exceeded 100%
if( progress >= 100 ){
// this is just for the setInterval to stop it
// from continually executing
clearInterval( timer );
// add a new class to the progress bar (keeping
// the CSS separate from the JavaScript -- there's
// a lot of opinions on this, do what you feel
// comfortable with
progressBar.className = 'yellow';
}
// Update the progress value inside the progress
// bar
progressBar.innerHTML = progress;
// Update the width of the progress bar by setting
// the css style value
progressBar.style.width = progress + '%';
// timed loop that will trigger every 100 miliseconds
}, 100 );
#progress-bar{
color: transparent;
font-size: 0px;
width: 0%; height: 3px;
overflow: hidden;
background-color: green;
transition: all 0.5s;
}
#progress-bar.yellow{ background-color: yellow; }
#loader-wrapper{
padding: 5%;
width: 90%;
border: solid 1px black;
border-radius: 5px;
}
<div id="loader-wrapper">
<div id="progress-bar">0</div>
</div>
Related
I have a little mouse speed detector (which is far from perfect) which gives me the current mouse speed every 100ms in the variable window.mouseSpeed.t.
I only implemented it because I want to have a funny animation on the bottom edge of the screen with a bar that grows with higher speeds and shrinks with lower speeds.
I want it to be animated with Element.animate().
The only problem is: How can I change the Animation's end keyframe (I only give an end frame so the browser assumes the current status as the first frame) while the animation is running?
I want to achieve that the bar smoothly changes its length.
// The code I want to have animated is below this function.
// Mouse speed tracker (I hope this isn't too horrible code):
document.addEventListener('DOMContentLoaded', mausgeschwindigkeitVerfolgen, {once:true});
function mausgeschwindigkeitVerfolgen() { // "Mausgeschwindigkeit verfolgen" means "track mouse speed" in German
var speedX = NaN;
var speedY = NaN;
var posX = NaN;
var posY = NaN;
var speed = NaN;
document.addEventListener("mousemove", function(ev){
speedX += Math.abs(ev.movementX);
speedY += Math.abs(ev.movementY);
speed = 10*Math.sqrt(ev.movementX**2+ev.movementY**2);
window.mousePosition = {x:posX = ev.clientX,y:posY = ev.clientY};
}, false);
setInterval(function(){
[window.mouseSpeed, window.mousePosition] = [{x:speedX,y:speedY,t:speed}, {x:posX,y:posY}]; // Werte in window.mouseSpeed und window.mouseDistance speichern
speed = totalX = totalY = 0;
}, 100);
window.mausgeschwindigkeitVerfolgen = () => {return {speed:window.mouseSpeed, pos:window.mousePosition};};
return {speed:window.mouseSpeed, pos:window.mousePosition};
}
// --- This is the code I want to have animated: ---
setInterval(() => {
document.querySelector('div#mouseSpeedIndicator').style.width = window.mouseSpeed.t+'px';
//document.querySelector('div#mouseSpeedIndicator').animate({width:'0px'}, {duration:1000,iterations:1}); // This just keeps the bar at width 0, I want it to slowly change to any newly set width
}, 100);
div#mouseSpeedIndicator {
position: fixed;
bottom: 0px;
left: 0px;
height: 33px;
background-color: green;
max-width: 100vh;
border: 0px solid green;
border-top-right-radius: 10px;
}
<!-- What I currently have -->
<div id="mouseSpeedIndicator"></div>
First, something as simple as one additional line of the transition CSS property like e.g. ...
transition: width 1s ease-out;
... already does the job; no need for more JavaScript based computation and DOM manipulation.
But of cause the OP's script could be dramatically simplified with or even without the support of an external helper method like throttle (lodash _.throttle or underscorejs _.throttle) where the latter would create a delayed executed version of the passed function which for the OP's example-script is the 'mousemove'-handler.
This handler before being throttled (or even not throttled) could be created as a bound version of the function which actually computes the speed value and updates the indicator-node's appearance.
function handleMouseSpeedIndicatorUpdateFromBoundData(evt) {
const { movementX, movementY } = evt;
const { rootNode, timeoutId } = this;
// prevent indicator nullification at time.
clearTimeout(timeoutId);
// compute `speed`.
const speed = 10 * Math.sqrt(movementX**2 + movementY**2);
// update indicator appearance.
rootNode.style.width = `${ speed }px`;
// trigger delayed indicator nullification.
this.timeoutId = setTimeout(() => rootNode.style.width = 0, 110);
}
function initialzeMouseSpeedIndicator() {
document
.addEventListener(
'mousemove',
// create throttled version of the just created bound handler.
_.throttle(
// create handler function with bound contextual data.
handleMouseSpeedIndicatorUpdateFromBoundData.bind({
rootNode: document.querySelector('#mouseSpeedIndicator'),
timeoutId: null,
}), 100
),
false
);
}
// - no need for `'DOMContentLoaded'`
// in order to initialize the indicator.
initialzeMouseSpeedIndicator();
div#mouseSpeedIndicator {
position: fixed;
top: 0px;
left: 0px;
height: 33px;
background-color: green;
max-width: 100vh;
border: 0px solid green;
border-bottom-right-radius: 10px;
/* proposed change(s) */
transition: width 1s ease-out;
/* transition: width .5s ease-in; */
/* transition: width .5s ease-in-out; */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<div id="mouseSpeedIndicator"></div>
I have a 11500x11500 div that consists of 400 images, that obviously overflows the viewport.
I would like to pan around the whole div programmatically.
I want to generate an animation and by the time the animation is over, the whole of the div must have been panned across the viewport, top to bottom, left to right.
Right now, I am "splitting" my 11500x1500 div into tiles. The maximum width and height of each tile is the width and height of the viewport.
I store the coordinates of each tile and then I randomly choose one, pan it left-to-right and then move on to the next one.
I would like to know:
whether my method is correct or whether I am missing something in my calculations/approach and it could be improved. Given the size, it is hard for me to tell whether I'm actually panning the whole of the div after all
whether I can make the panning effect feel more "organic"/"natural". In order to be sure that the whole div is eventually panned, I pick each tile and pan it left-to-right, move on to the next one etc. This feels kind of rigid and too formalised. Is there a way to pan at let's say an angle or with a movement that is even more random and yet be sure that the whole div will eventually be panned ?
Thank in advance for any help.
This is the jsfiddle and this is the code (for the sake of the example/test every "image" is actually a div containing its index as text):
function forMs(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, time)
})
}
let container = document.getElementById('container')
let {
width,
height
} = container.getBoundingClientRect()
let minLeft = window.innerWidth - width
let minTop = window.innerHeight - height
let i = 0
while (i < 400) {
// adding "image" to the container
let image = document.createElement('div')
// add some text to the "image"
// to know what we're looking at while panning
image.innerHTML = ''
let j = 0
while (j < 100) {
image.innerHTML += ` ${i + 1}`
j++
}
container.appendChild(image)
i++
}
let coords = []
let x = 0
while (x < width) {
let y = 0
while (y < height) {
coords.push({
x,
y
})
y += window.innerHeight
}
x += window.innerWidth
}
async function pan() {
if (!coords.length) {
return;
}
let randomIdx = Math.floor(Math.random() * coords.length)
let [randomCoord] = coords.splice(randomIdx, 1);
console.log(coords.length)
container.classList.add('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
// move to new yet-unpanned area
container.style.top = Math.max(-randomCoord.y, minTop) + 'px'
container.style.left = Math.max(-randomCoord.x, minLeft) + 'px'
// wait (approx.) for transition to end
await forMs(2500)
container.classList.remove('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
//pan that area
let newLeft = -(randomCoord.x + window.innerWidth)
if (newLeft < minLeft) {
newLeft = minLeft
}
container.style.left = newLeft + 'px'
// wait (approx.) for transition to end
await forMs(4500)
// move on to next random area
await pan()
}
pan()
html,
body {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
* {
margin: 0;
padding: 0;
}
#container {
position: absolute;
top: 0;
left: 0;
text-align: left;
width: 11500px;
height: 11500px;
transition: all 4s ease-in-out;
transition-property: top left;
font-size: 0;
}
#container.fast {
transition-duration: 2s;
}
#container div {
display: inline-block;
height: 575px;
width: 575px;
border: 1px solid black;
box-sizing: border-box;
font-size: 45px;
overflow: hidden;
word-break: break-all;
}
<div id="container"></div>
I think following improvements can be made:
Hide overflow on html and body so user can not move scrollbar and disturb the flow.
Calculate minLeft and minTop every time to account for window resizing. You might need ResizeObserver to recalculate things.
Increase transition times to avoid Cybersickness. In worse case RNG will pick bottom right tile first so your container will move the longest in 2seconds! Maybe, you can zoom-out and move then zoom-in then perform pan. Or use any serpentine path which will make shorter jumps.
Performance improvements:
Use transform instead of top, left for animation.
Use will-change: transform;. will-change will let browser know what to optimize.
Use translate3D() instead of translate(). ref
Use requestAnimationFrame. Avoid setTimeout, setInterval.
This is an old but good article: https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
Modified code to use transform:
function forMs(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, time)
})
}
let container = document.getElementById('container')
let stat = document.getElementById('stats');
let {
width,
height
} = container.getBoundingClientRect()
let minLeft = window.innerWidth - width
let minTop = window.innerHeight - height
let i = 0
while (i < 400) {
// adding "image" to the container
let image = document.createElement('div')
// add some text to the "image"
// to know what we're looking at while panning
image.innerHTML = ''
let j = 0
while (j < 100) {
image.innerHTML += ` ${i + 1}`
j++
}
container.appendChild(image)
i++
}
let coords = []
let x = 0
while (x < width) {
let y = 0
while (y < height) {
coords.push({
x,
y
})
y += window.innerHeight
}
x += window.innerWidth
}
let count = 0;
async function pan() {
if (!coords.length) {
stat.innerText = 'iteration: ' +
(++count) + '\n tile# ' + randomIdx + ' done!!';
stat.style.backgroundColor = 'red';
return;
}
let minLeft = window.innerWidth - width
let minTop = window.innerHeight - height
let randomIdx = Math.floor(Math.random() * coords.length);
randomIdx = 1; //remove after debugging
let [randomCoord] = coords.splice(randomIdx, 1);
stat.innerText = 'iteration: ' +
(++count) + '\n tile# ' + randomIdx;
console.log(coords.length + ' - ' + randomIdx)
container.classList.add('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
// move to new yet-unpanned area
let yy = Math.max(-randomCoord.y, minTop);
let xx = Math.max(-randomCoord.x, minLeft);
move(xx, yy);
// wait (approx.) for transition to end
await forMs(2500)
container.classList.remove('fast')
// update style in new thread so new transition-duration is applied
await forMs(10)
//pan that area
let newLeft = -(randomCoord.x + window.innerWidth)
if (newLeft < minLeft) {
newLeft = minLeft
}
xx = newLeft;
//container.style.left = newLeft + 'px'
move(xx, yy);
// wait (approx.) for transition to end
await forMs(4500)
// move on to next random area
await pan()
}
pan()
function move(xx, yy) {
container.style.transform = "translate3D(" + xx + "px," + yy + "px,0px)";
}
html,
body {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#container {
text-align: left;
width: 11500px;
height: 11500px;
transition: all 4s ease-in-out;
transition-property: transform;
font-size: 0;
will-change: transform;
}
#container.fast {
transition-duration: 2s;
}
#container div {
display: inline-block;
height: 575px;
width: 575px;
border: 1px solid black;
box-sizing: border-box;
font-size: 45px;
overflow: hidden;
word-break: break-all;
}
#stats {
border: 2px solid green;
width: 100px;
background-color: lightgreen;
position: fixed;
opacity: 1;
top: 0;
left: 0;
z-index: 10;
}
<div id=stats>iteration: 1 tile# 11</div>
<div id="container"></div>
Note I haven't implemented everything in above snippet.
I am working on my portfolio website and I am a complete beginner in Javascript.
I would like a button which has its position fixed, to slowly fade in when I scroll down (suppose when I scroll to >=20px from the top of the document, it should fade in) and when I scroll back up to the original position, it should gradually fade out.
I have already tried my hand and written a code for this. It is working perfectly when you scroll down and up. But when you quickly scroll and stop scrolling in the mid-way, it behaves pretty abnormally (suddenly appears or disappears).
HTML:
<div class="a_large_page">
<div class="enclose bordar black" id="bottomtoup">hello</div>
</div>
JS:
mybutton = document.getElementById("bottomtoup")
// initially, the button stays hidden
visible = false
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
if (!visible) { // if the button is not visible,
unfade(mybutton); // function to gradually fadein button
visible = true; // button is visible so, set visible = false to true.
}
} else {
if (visible) { // if the button is visible,
fade(mybutton); // function to gradually fadeout button
visible = false; // set visible = true back to false
}
}
}
function unfade(element) {
var op = 0.1; // initial opacity
element.style.display = 'flex';
var timer = setInterval(function() {
if (op >= 1) {
clearInterval(timer);
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1;
}, 10);
}
function fade(element) {
var op = 1; // initial opacity
var timer = setInterval(function() {
if (op <= 0.1) {
clearInterval(timer);
element.style.display = 'none';
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op -= op * 0.1;
}, 50);
}
Here is the fiddle: https://jsfiddle.net/P0intMaN/Lmp6u5ft/23/
My code is pretty substandard for sure. That's why it is behaving in this way. Hence, I am looking for an efficient way to achieve this. I have seen people making use of JQuery to do this, but I don't know JQuery at all. So, it would be much appreciated if the code is in pure JS.
I've changed your code and removed setInterval usage. This can be solved with it but may be harder to understand for newer coders.
There are also flags to keep track of whether you are currently fading or unfading to ensure you do not stack or "overlap" timeout/intervals.
mybutton = document.getElementById("bottomtoup")
// initially, the button stays hidden
var visible = false
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
var threshold = 20;
var below_threshold = document.body.scrollTop > threshold || document.documentElement.scrollTop > threshold;
if (below_threshold) {
if (!visible) { // if the button is not visible,
unfade(mybutton); // function to gradually fadein button
}
return;
}
if (visible) { // if the button is visible,
fade(mybutton); // function to gradually fadeout button
}
}
var current_opacity = 0.1;
var is_unfading = false;
var is_fading = false;
function unfade(element) {
if(!visible){
element.style.display = 'flex';
visible = true;
}
is_fading = false;
is_unfading = true;
unfade_step(element);
}
function unfade_step(element){
element.style.opacity = current_opacity;
element.style.filter = 'alpha(opacity=' + current_opacity * 100 + ")";
if (current_opacity >= 1){
// end
is_unfading = false;
current_opacity = 1;
return;
}
current_opacity += 0.01;
if(is_unfading){
setTimeout(function(){
unfade_step(element);
}, 10);
}
}
function fade(element) {
if(!visible){
return;
}
is_fading = true;
is_unfading = false;
fade_step(element);
}
function fade_step(element) {
element.style.opacity = current_opacity;
element.style.filter = 'alpha(opacity=' + current_opacity * 100 + ")";
if (current_opacity <= 0.001){
// end
is_fading = false;
visible = false;
current_opacity = 0.1;
element.style.display = 'none';
return;
}
current_opacity -= 0.01;
if(is_fading){
setTimeout(function(){
fade_step(element);
}, 10);
}
}
There is no need to have so much JS when you can do in so little:
If you feel to change the timing of
// Set a function onscroll - this will activate if the user scrolls
window.onscroll = function() {
// Set the height to check for
var appear = 20
if (window.pageYOffset >= appear) {
// If more show the element
document.getElementById("bottomtop").style.opacity = '1'
document.getElementById("bottomtop").style.pointerEvents = 'all'
} else {
// Else hide it
document.getElementById("bottomtop").style.opacity = '0'
document.getElementById("bottomtop").style.pointerEvents = 'none'
}
}
.a_large_page{
background-color: gray;
height: 2000px;
}
.enclose{
height: 40px;
width: 40px;
position:fixed;
margin-right: 20px;
margin-bottom: 20px;
right:0;
bottom:0;
pointer-events:none;
opacity:0;
justify-content: center;
align-items: center;
color:white;
/* This determines how fast animation takes place, you can change it as per your choice. */
transition:all 0.6s;
}
.enclose:hover{
cursor: pointer;
}
<div class="a_large_page">
<div class="enclose bordar black" id="bottomtop">hello</div>
</div>
There is no need to sense the scroll event in more modern browsers as you can use IntersetionObserver to tell you when scrolling has gone past 20px;
You can do this by placing a tiny element at the top of the page with height 20px. You then ask the system to tell you when this has gone out of, or comes back into, the viewport. At these points you can set the opacity of the Hello to 1 or 0 as appropriate.
The extra bonus is that you get rid of a lot of code and there isn't the possible clash between set intervals as we use transition on the opacity to do the gradual fade in/out.
// See MDN for more info on IntersectioObserver
let callback = (entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
mybutton.style.opacity = 0;
} else {
mybutton.style.opacity = 1;
}
});
};
const mybutton = document.getElementById("bottomtoup")
const observer = new IntersectionObserver(callback);
const observed = document.getElementById("observed");
observer.observe(observed);
.a_large_page {
background-color: gray;
height: 2000px;
position: relative;
}
#observed {
position: absolute;
top: 0;
left: 0;
height: 20px;
width: 10px;
z-index: -999;
}
.enclose {
height: 40px;
width: 40px;
position: fixed;
margin-right: 20px;
margin-bottom: 20px;
right: 0;
bottom: 0;
justify-content: center;
align-items: center;
color: white;
opacity: 0;
transition: opacity 1s linear;
}
<div class="a_large_page">
<div id="observed"></div>
<div class="enclose bordar black" id="bottomtoup">hello</div>
</div>
I want to create a loadingbar/ progressbar that loads as a value (var) increases. I cant figure out how to go around this.I have the tools. e.g. a dynamic chaning value extracted from my Firebase DB that increments on based off of a certain action. however im unsure how to go around to creating this progressbar and how to have it load based off of the dynamic incrementing value.
Any tips?
You can use something like below:
function increaseWidth(percent) {
let containerWidth = document.getElementById('progressBarContainer').clientWidth; // get the container width
let amount = Math.round(containerWidth * percent/100); // get amount of pixels the bars width needs to increase
let barWidth = document.getElementById('bar').offsetWidth; // get the current bar width
// if the bar width + amount of pixels to increase exceeds the container's width, reduce it accordingly
if(barWidth + amount > containerWidth) {
amount = containerWidth - barWidth;
clearInterval(bar); // we reached 100% so clear the interval
}
let totalPercent = Math.round((barWidth + amount) * 100/ containerWidth); // calculate the total percent finished
document.getElementById('bar').style.width = barWidth + amount + "px"; // increase bar width
document.getElementById('text').innerHTML = totalPercent + "%"; // update the percentage text
}
// this is just to mimic generating "work done" percentage
var bar = setInterval(function() {
let percentage = Math.floor(Math.random() * 10 + 1); // generate a percentage of work done
increaseWidth(percentage);
}, 1000)
#progressBarContainer {
position: relative;
float:left;
width: 200px;
height: 20px;
border: 1px solid #09f;
background-color: #000;
}
#bar {
position: relative;
float:left;
width: 0;
height: 20px;
background-color: #f00;
}
#text {
position: absolute;
height: 20px;
width: 200px;
top: 0px;
left: 0px;
color: #fff;
text-align:center;
line-height:20px;
}
<div id="progressBarContainer">
<div id="bar">
<div id="text"></div>
</div>
</div>
If you don't mind using JQuery, try using the JQuery UI Progressbar Widget. You have to first add the JQUERY UI library to your website using a <script> tag in the header:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha256-KM512VNnjElC30ehFwehXjx1YCHPiQkOPmqnrWtpccM=" crossorigin="anonymous"></script>
Then initialize the progress bar with a maximum value; if you want to use percentages, that should be 100.
$("#progressbarElementID").progressbar({
max: 100
});
Then update by writing a percent:
$("#progressbarElementID").progressbar({
value: 74 // Or whatever percent you want...
});
Repeat the update function as necessary to change the progress bar.
For a more in-depth tutorial you can refer to the API docs for this feature.
I have an text element (HTML) that plays an animation when the page loads and I'm trying to create a script to change the original text to a different one and then play the same animation. Here is part of my code:
setTimeout(function typewriter() {
let txt;
let themes = document.getElementById("themes");
txt = "Games";
themes.innerText = txt;
themes.classList.add("changer");
}, 4000);
.typewriter h1 {
color: #ffffff;
background-color: #000000a8;
border-radius: 5px;
padding: 10px;
font-family: monospace;
font-size: 35px;
overflow: hidden; /* Ensures the content is not revealed until the animation */
border-right: .15em solid #333333; /* The typwriter cursor */
white-space: nowrap; /* Keeps the content on a single line */
margin: 0 auto; /* Gives that scrolling effect as the typing happens */
animation:
typing 2s steps(30, end),
blink-caret .5s step-end infinite;
}
.changer {
animation: typing 2 s steps(30, end),blink - caret .5 s step - end infinite;
}
/* The typing effect */
#keyframes typing {
from { width: 0 }
to { width: 100% }
}
/* The typewriter cursor effect */
#keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: #333333 }
}
<div class="typewriter">
<h1 id="themes">Science</h1>
</div>
The problem is that after 4 seconds when the text changes I can't play the animation again. Can anyone help me, please? Thank you.
First, you are using setTimeout (This is wrong)
If you want it to repeat the function, you should use setInterval.
Second, you are changing the same "Text" every time you call the function, which is "Games". If you want it to change to a certain text, you need to store it first in an array,
var texts = [];
//Add a counter
var curr = 0;
//Store in array
texts.push("Games");
texts.push("Science");
setInterval(function() {
let txt;
//Change the texts array value with curr variable (the Counter)
txt = texts[curr];
let themes = document.getElementById("themes");
themes.innerText = txt;
themes.classList.add("changer");
//Change the counter variable
curr += 1;
//Change the counter to the start of the array
if(curr >= texts.length) curr = 0;
}, 4000);
In my case, the animation doesn't work. But if you want to change the text for every 4s, this code will help you.
You can add any number of text that you want.
I found a solution using JavaScript to increase the width of the element from 1% to 100%!
Here is my JavaScript code:
var texts = [];
//Add a counter
var curr = 0;
//Store in array
texts.push("Games");
texts.push("Science");
setInterval(function() {
let txt;
//Change the texts array value with curr variable (the Counter)
txt = texts[curr];
let themes = document.getElementById("themes");
themes.innerText = txt;
var width = 0;
var id = setInterval(frame,10);
function frame(){
if(width >= 100){
clearInterval(id);
} else {
width++;
themes.style.width = width + "%";
}
}
//Change the counter variable
curr += 1;
//Change the counter to the start of the array
if(curr >= texts.length) curr = 0;
}, 4000);
Thank you for the help!