I have made a progress bar with decrease from width 100 to 0 using setInterval function. So basically every 20ms my width decrease from 1. Then when the width arrives at 0, I set the width to 100 to run the progress bar again. At every loop, I change the text inside my progress bar. What I'd like to do now is change the time interval (the 20ms) at every loop.
Si in my code, when I increase from one, my 20 is replaced by interval[i]... but I am stack to put setInterval inside a loop...
The code below works to change the text at every loop, but don't know how to improve it to change the time interval at every iteration of i...
function move() {
var message = ['test', 'test2', 'test3'];
var interval = [10, 20, 30]
var elem = document.getElementById("myBar");
var width = 100;
var i = 0;
var id = setInterval(frame, 20);
function frame() {
width = width - 1;
elem.style.width = width + "%";
elem.textContent = message[i];
if (width == 0 && i < 3) {
width = 100;
i++;
}
if (i == 3) {
clearInterval(id);
}
}
}
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 100%;
height: 30px;
background-color: #4CAF50;
}
<h1>JavaScript Progress Bar</h1>
<div id="myProgress">
<div id="myBar"> </div>
</div>
<br>
<button onclick="move()">Click Me</button>
<html>
<style>
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 100%;
height: 30px;
background-color: #4CAF50;
}
</style>
<body>
<h1>JavaScript Progress Bar</h1>
<div id="myProgress">
<div id="myBar"> </div>
</div>
<br>
<button onclick="move()">Click Me</button>
<script>
function move() {
var message = ['test','test2','test3'];
var interval = [10,20,30]
var elem = document.getElementById("myBar");
var width = 100;
var i = 0;
var id = setInterval(frame, interval[i]);
function frame() {
width = width - 1;
elem.style.width = width + "%";
elem.textContent = message[i];
if (width == 0 && i < 3) {
width = 100;
i++;
clearInterval(id);
id = setInterval(frame, interval[i]);
}
if (i == 3) {
clearInterval(id);
}
}
}
</script>
</body>
</html>
You could declare a variable outside function move that holds the iteration time step, like:
let iterationStep = 0;
Then inside
let iterationStep = 0;
function move() {
//...blabla
var id = setInterval(frame, interval[iterationStep]);
function frame() {
// blablabla
if (width == 0 && i < 3) {
width = 100;
i++;
// HERE
iterationStep = i;
}
//blablabla
}
}
So each time you are increasing i you are also increasing the value of iterationStep by i value. And it is the value that will be used to access the postition inside the array of intervals of the iteration once you click in move().
Related
I'm looking at setting a 2-3 second delay on a sprite animation. How do I pause the end of each interval and then continue from 0? I used the code below to run only an interval with no delay at the end.
var imgWidth = 48;
var numImgs = 60;
var cont = 0;
var animation = setInterval(function() {
var position = -1 * (cont * imgWidth);
$('#container').find('img').css('margin-left', position);
cont++;
if (cont == numImgs) {
cont = 0;
}
}, 18);
#container {
width: 48px;
height: 48px;
display: block;
overflow: hidden;
}
#container img {
width: 2880px;
height: 48px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<img src="https://visualcraftsman.com/doh/rdWaitAll.png" alt="My super animation" />
</div>
fiddle
One idea is to use setTimeout() recursively and change the delay depending on the animation's frame number.
// define variables
const $img = $('#container').find('img');
const imgWidth = 48;
const numImgs = 60;
var cont = 0;
var delay = 18;
function advance() {
// increment frame number, loop back to zero
cont = cont == numImgs ? 0 : cont + 1;
// calculate positioning margin
let position = -1 * (cont * imgWidth);
// calculate viewing time for this frame
let delay = cont == 0 ? 1000 : 18;
// position the image
$img.css('margin-left', position);
// schedule next frame advance
setTimeout(advance, delay);
}
// initiate the recursive loop
advance();
#container {
width: 48px;
height: 48px;
display: block;
overflow: hidden;
}
#container img {
width: 2880px;
height: 48px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<img src="https://visualcraftsman.com/doh/rdWaitAll.png" alt="My super animation" />
</div>
I've been trying to add 1% to the width of the div using JS. I want to make it so that the bar's width increases in a smooth way ( I thought about using animations but it didn't work cause I need to specify conditions).
window.onload = function(){
for (let i = 0; i < 5; i++) {
const bar = document.querySelectorAll(".child-bar")[i];
for (let j = 0; j < 82; j++) {
//alert("j" + j);
console.log("bar width: "+ bar.style.width)
bar.style.width += '1%';
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="skill">
<label for="HTML">HTML</label>
<div class="parent-bar">
<span class="child-bar"></span>
<h4>82%</h4>
</div>
</div>
Maybe this example will help you?
window.onload = function() {
document.querySelectorAll(".parent-bar").forEach((el) => {
const barNode = el.querySelector(".child-bar");
const valueNode = el.querySelector("h4");
const max = 82;
const duration = 100;
let value = 0;
const tick = () => {
barNode.style.width = `${value}%`;
valueNode.innerHTML = `${value}%`;
if (value++ < max) setTimeout(tick, duration);
}
tick();
})
}
.child-bar {
display: block;
background: black;
height: 1rem;
width: 0;
transition: 0.1s 0s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="skill">
<label for="HTML">HTML</label>
<div class="parent-bar">
<span class="child-bar"></span>
<h4></h4>
</div>
<div class="parent-bar">
<span class="child-bar"></span>
<h4></h4>
</div>
<div class="parent-bar">
<span class="child-bar"></span>
<h4></h4>
</div>
</div>
Here's a solution with verbose code and commentary for clarity, using setInterval.
(Note that span elements have display: inline by default, which is why setting their width has no effect.)
// Sets options and calls main function
const myOptions = {
MAX_WIDTH_PERCENT: 82,
FRAME_COUNT: 100,
FRAME_DURATION: 20
};
animateBars(myOptions);
// Defines main function
function animateBars(options){
const
// Destructures options object to make local variables
{ MAX_WIDTH_PERCENT, FRAME_COUNT, FRAME_DURATION } = options,
// Defines function to increment width
increment = (value) => value += MAX_WIDTH_PERCENT / FRAME_COUNT,
// Defines function to update bar (after incrementing width)
incrementAndupdateBar = (bar, oldWidth, timerId) => {
newWidth = Math.min(increment(oldWidth), MAX_WIDTH_PERCENT);
bar.style.width = newWidth + "%";
bar.nextElementSibling.textContent = Math.floor(newWidth) + "%"; // (For demo)
// Stops repeating the setInterval's function
if(newWidth == MAX_WIDTH_PERCENT){
clearInterval(timerId);
}
return newWidth; // Returns updated value
};
// Loops through bars
for(let bar of document.querySelectorAll(".child-bar")){
// Repeatedly updates current bar, keeping track of width as we go
let
width = 0, // Initializes width for the current bar
timerId; // ID for use by setInterval & clearInterval
timerId = setInterval( // (Returns an ID for later use)
// Takes 2 args: a func and a duration (in ms) to delay inbetween
function(){width = incrementAndupdateBar(bar, width, timerId);},
FRAME_DURATION
);
}
}
.parent-bar{ width: 300px; border: 1px dotted grey; }
/* spans ignore "width" by default; "inline-block" solves this */
.child-bar{ display: inline-block; height: 1em; background-color: lightgreen; }
h4{ margin: 0; text-align: center; }
<div class="parent-bar">
<span class="child-bar"></span>
<h4></h4>
</div>
I'm trying to create a progress bar with a percentage text using only Javascript, but I don't know what value I need set in the function to limit the incrementation. The bar and the text keep increasing.
Need create 4 skills bar with 30% / 50% / 70% and 90%.
Help, plz! Accept any suggestions!
Here is my code.
<div class="progress">
<div class="progress-bar"></div>
<p value="30" class="text">30</p>
</div>
<script>
function update() {
let element = document.querySelector(".progress-bar");
let counter = document.querySelector(".text");
var width = 1;
var identity = setInterval(scene, 10);
function scene() {
if (width >= counter.value) {
clearInterval(identity);
} else {
width++;
element.style.width = width + '%';
counter.innerHTML = width * 1 + '%';
}
}
}
</script>
I am not sure if I am following the issue you are experiencing. I see your code can be improved and would solve some problems. Here what I suggest:
function update() {
let element = document.querySelector(".progress-bar");
let counter = document.querySelector(".text");
let width = 1;
setTimeout(scene, 1);
function scene() {
if (width < 100) {
width++;
element.style.width = width + '%';
counter.innerHTML = width * 1 + '%';
setTimeout(scene, 1);
} else {
//Complete action here
}
}
}
Welcome to Stackoverflow! Below you can see a working example of your code with minimal changes. I just defined that when the percenteage comes up to 100, it clears the interval on the page.
function update() {
let element = document.querySelector(".progress-bar");
let counter = document.querySelector(".text");
var percenteage = 0;
var identity = setInterval(scene, 50);
function scene() {
if (percenteage < 100) {
percenteage++;
element.style.width = percenteage + '%';
counter.innerHTML = percenteage + ' %';
} else {
clearInterval(identity);
console.log("Cleared!");
}
}
}
update();
.progress-bar {
height: 10px;
background-color: red;
}
<div class="progress">
<div class="progress-bar"></div>
<p value="30" class="text">30</p>
</div>
I want to make two progress bars working on load. But the code which I write makes only one loading. Also those two progress bars has to be different in length when loaded. I don't want to repeat code, so I am adding arrays. But I am not quite sure that this is the best solution. Maybe in body tag it is possible to write two different functions, or only one can be onload? If it is possible with several functions onload, then the number array shouldnt't be used. My code below. Maybe anyone knows the solution?
<style>
.myProgress {
width: 100%;
background-color: #000000;
}
#myBar1, #myBar2 {
width: 1%;
height: 30px;
background-color: #4CAF50;
}
</style>
<body onload="move()">
<div class="myProgress">
<div id="myBar1"></div>
</div>
<div class="myProgress">
<div id="myBar2"></div>
</div>
<script>
function move() {
var ids = ["myBar1", "myBar2"];
var number = [60, 90]
var length = ids.length;
for(i = 1; i<=length; i++){
var elem = document.getElementById("myBar"+i);
var width = 1;
var id = setInterval(frame, 10);
function frame() {
if (width >= number[i-1]) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
}
}
}
}
</script>
The problem was caused because you were mixing loops with async operations which usually doesn't turn out well. If you want to do that you should use let instead of var or do the operation in another function. Moreover you can set the width in the html element and read all the progress bars.
function move() {
for (var item of document.querySelectorAll(".myProgress")) {
loading(item.firstElementChild, +item.getAttribute("width") || 100); // replace 100 with default
}
}
function loading(bar, maxWidth) {
var width = 0;
var intervalId = setInterval(function() {
if (width >= maxWidth) clearInterval(intervalId);
else bar.style.width = ++width + '%';
}, 10);
}
.myProgress {
width: 100%;
background-color: #000000;
}
#myBar1,
#myBar2 {
width: 1%;
height: 30px;
background-color: #4CAF50;
}
<body onload="move()">
<div class="myProgress" width="60">
<div id="myBar1"></div>
</div>
<div class="myProgress" width="90">
<div id="myBar2"></div>
</div>
</body>
How do you make JavaScript animation scroll both to the bottom of an element and back to the top? I am still learning about JavaScript and found an example code from w3schools, which, when I modified it to scroll back to the top, worked in the Tryit Editor, using the exact same code for the myUP function I have below. Though I know that in its current state, combined with the other function, this same code is not currently working.
I have a hunch that there was something not good about the code, even when it worked fine by itself in the Tryit Editor. I feel that in the future it would not work properly. Am I right to assume this, and, if so, what should I be doing to achieve this in JavaScript instead?
<html>
<style>
#myContainer {
width: 500px;
height: 500px;
position: relative;
background: black;
}
#tester {
width: 500px;
height: 50px;
position: absolute;
background-color: gray;
}
</style>
<body>
<p>
<button onmousedown="myMove()">DOWN</button>
</p>
<p>
<button onmousedown="myUP()">UP</button>
</p>
<div id ="myContainer">
<div id ="tester"></div>
</div>
<script>
function myMove() {
var elem = document.getElementById("tester");
var pos = 0;
var id = setInterval(frame, 20);
function frame() {
if (pos == 500) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
}
}
}
function myUP() {
var elem = document.getElementById("tester");
var pos = 0;
var id = setInterval(frame, 20);
function frame() {
if (pos == 500) {
clearInterval(id);
} else {
pos++;
elem.style.bottom = pos + 'px';
}
}
}
</script>
</body>
Check the working code now,
Your code were making problem in UP function.
function myUP() {
var elem = document.getElementById("tester");
var pos = 500;// Changed the max position.
var id = setInterval(frame, 20);
function frame() {
console.log(pos);
if (pos == 0) { //reverse condition to 0
clearInterval(id);
} else {
pos--; // reverse the position
elem.style.top = pos + 'px'; // that should be back to top
}
}
}
<html>
<style>
#myContainer {
width: 500px;
height: 500px;
position: relative;
background: black;
}
#tester {
width: 500px;
height: 50px;
position: absolute;
background-color: gray;
}
</style>
<body>
<p>
<button onmousedown="myMove()">DOWN</button>
</p>
<p>
<button onmousedown="myUP()">UP</button>
</p>
<div id ="myContainer">
<div id ="tester"></div>
</div>
<script>
function myMove() {
var elem = document.getElementById("tester");
var pos = 0;
var id = setInterval(frame, 20);
function frame() {
if (pos == 500) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
}
}
}
function myUP() {
var elem = document.getElementById("tester");
var pos = 500;
var id = setInterval(frame, 5);
function frame() {
console.log(pos);
if (pos == 0) {
clearInterval(id);
} else {
pos--;
elem.style.top = pos + 'px';
}
}
}
</script>
</body>