Progress Bar stopping when tab is not in focus - javascript

I'm using the following code for a progress bar:
<div class="slide-progress-bar">
<div class="progress-bar" id="progress-bar"></div>
<!--progress-bar-->
</div>
<script>
var elem = document.getElementById("progress-bar");
var width = 1;
function progressBar() {
resetProgressBar();
id = setInterval(frame, 300);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
elem.style.width = width +"%";
}
}
}
function resetProgressBar() {
width = 1;
elem.style.width = width;
}
progressBar()
</script>
<style>
.slide-progress-bar {
width: 150px;
background-color:rgba(155, 155, 155, 0.36);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
margin: auto;
width: 100%;
}
.progress-bar {
height: 5px;
background-color: #ff4546;
position: relative;
transition: linear;
}
</style>
It works fine (when the page loads, progress bar starts and completes 300frames) but when I switch the tab or minimizes the window it stops and when I reopen the tab, it resumes. I don't want this top happen. I want the progress bar to continue loading even when not in focus. Is there way to do so ?, cause I saw such progress bars on may other sites.

Set Interval stops when page is minimize. You can use Date object to check how many time pass since progress bar starts loading.
<div class="slide-progress-bar">
<div class="progress-bar" id="progress-bar"></div>
<!--progress-bar-->
</div>
<script>
var animationTimeInMiliseconds = 30000; //30s
var interval = 300;
var elem = document.getElementById("progress-bar");
var beginningDate = new Date().getTime(); // Time in miliseconds
function progressBar() {
resetProgressBar();
id = setInterval(frame, interval);
function frame() {
var milisecondsFromBegin = new Date().getTime() - beginningDate;
var width = Math.floor(milisecondsFromBegin / animationTimeInMiliseconds * 100);
elem.style.width = width + "%";
if (width >= 100) {
clearInterval(id);
}
}
}
function resetProgressBar() {
elem.style.width = 0;
}
progressBar()
</script>
<style>
.slide-progress-bar {
width: 150px;
background-color:rgba(155, 155, 155, 0.36);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
margin: auto;
width: 100%;
}
.progress-bar {
height: 5px;
background-color: #ff4546;
position: relative;
transition: linear;
}
</style>

You can use css3 transitions instead of js animations to solve the problems you are facing.
You can read more about it here
Adding an example for your reference.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
.slide-progress-bar {
width: 150px;
background-color:rgba(155, 155, 155, 0.36);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
margin: auto;
width: 100%;
}
.slide-progress-bar .progress-bar {
height: 5px;
background-color: #ff4546;
position: relative;
transition: linear;
animation: progres 4s infinite linear;
}
#keyframes progres{
0%{
width: 0%;
}
25%{
width: 50%;
}
50%{
width: 75%;
}
75%{
width: 85%;
}
100%{
width: 100%;
}
};
</style>
</head>
<body>
<div class="slide-progress-bar">
<div class="progress-bar"></div>
</div>
</body>
</html>

Related

JS card animation + scss

My idea is to create a smooth animation of the appearance of the card from anywhere on the screen to the center. I already have an attractive animation with simultaneous zoom and rotation. It remains to make sure that on click the card from any center of the screen moves smoothly to the center, when closed, to its original position. It is advisable to do this in pure js. It is possible with the connection of libraries, it will also be useful
JS:
card = document.querySelector(".card");
front = document.querySelector(".front");
back = document.querySelector(".back");
exit = document.querySelector(".back-exit");
// //data of screen
// pageWidth = document.documentElement.scrollWidth;
// pageHeight = document.documentElement.scrollHeight;
// //date for front part
// heightOfBlock = front.offsetHeight;
// widthOfBlock = front.clientWidth;
// //date for back part
// heightOfBlock2 = back.offsetHeight;
// widthOfBlock2 = back.clientWidth;
front.addEventListener("click", function () {
front.classList.add("active");
back.classList.add("active");
back.classList.add("scale");
function background() {
card.classList.add("active");
}
// front.style.top = (pageHeight / 2) - (heightOfBlock / 2) + 'px';
// front.style.left = (pageWidth / 2) - (widthOfBlock / 2) + 'px';
// back.style.top = (pageHeight / 2) - 300 + 'px';
// back.style.left = (pageWidth / 2) - 500 + 'px';
setTimeout(background, 500);
});
exit.addEventListener("click", function () {
front.classList.remove("active");
back.classList.remove("active");
back.classList.remove("scale");
card.classList.remove("active");
// front.style.top = 0 + 'px';
// front.style.left = 0 + 'px';
// back.style.top = 0 + 'px';
// back.style.left = 0 + 'px';
});
* {
margin: 0;
padding: 0;
font-family: Roboto, sans-serif;
}
body {
overflow: hidden;
}
.card {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.card.active {
background-color: rgba(0, 0, 0, 0.8);
transition: background 1s;
}
.front,
.back {
cursor: pointer;
width: 298px;
height: 199px;
overflow: hidden;
backface-visibility: hidden;
position: absolute;
transition: transform 0.5s linear;
border-radius: 30px;
background-color: #111;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
.front {
transform: perspective(600px) rotateY(0deg);
transition: 0s ease;
}
.back {
transform: perspective(600px) rotateY(540deg);
background-color: rgb(70, 70, 70);
transition: 0s ease;
&-exit {
position: absolute;
top: 20px;
right: 20px;
color: rgb(126, 19, 19);
&:hover {
text-decoration: underline;
}
}
}
.front.active {
transform: perspective(600px) rotateY(-540deg);
transition: 1.2s ease;
animation: 1s linear scale;
}
.back.active {
transform: perspective(600px) rotateY(0deg);
transition: 1.2s ease;
font-size: 3rem;
.back-exit {
font-size: 1.3rem;
}
/* Запускать анимацию, когда класс активный */
animation: 1s linear scale;
}
.back.scale {
width: 1000px;
height: 600px;
}
/* Написать анимацию */
#keyframes scale {
from {
width: 298px;
height: 199px;
}
to {
width: 1000px;
height: 600px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./style.css">
<title>Document</title>
</head>
<body>
<div class="card">
<div class="front">
Hello It's me!
</div>
<div class="back">
<div class="back-exit">close</div>
Bye!
</div>
</div>
<!-- <h1>По клику блок выровняется.</h1>
<h2>Можно проскролить и кликнуть где-нибудь внизу.</h2>
<div id="testBlock"></div> -->
<script src="./script.js"></script>
</body>
</html>
The code is a little incorrect because of what I'm doing in sass

Making a progressbar to load from 0 to 100% in 10 seconds with JavaScript

I am trying to make a simple progressbar to load for 10 seconds always when the JavaScript function is called. I don't want to use jQuery or any library. I want it to be on clean JavaScript. The only think I don't understand is how to make the progressbar load from 0 to 100% in 10 seconds. I am providing code with what I have done until now. Any suggestions?
var elem = document.getElementById("slide-progress-bar");
var width = 1;
function progressBar() {
resetProgressBar();
id = setInterval(frame, 100);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
}
}
}
function resetProgressBar() {
width = 1;
elem.style.width = width + '%';
}
.slide-progress-bar {
width: 1118px;
background-color: rgba(155, 155, 255, 0.36);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
}
.progress-bar {
height: 5px;
background-color: #aff;
width: 1%;
position: relative;
transition: linear;
}
<div class="slide-progress-bar">
<div class="progress-bar" id="progress-bar"></div>
<!--progress-bar-->
</div>
<!--slide-progress-bar-->
I think you just have to change the element that you are increasing in width. Not sure if this is the behaviour you expected:
var elem = document.getElementById("progress-bar");
var width = 1;
var interval;
function progressBar() {
resetProgressBar();
interval = setInterval(frame, 100);
function frame() {
if (width >= 100) {
clearInterval(interval);
} else {
width++;
elem.style.width = width + '%';
}
}
}
function resetProgressBar() {
width = 1;
clearInterval(interval)
elem.style.width = width + '%';
}
.slide-progress-bar {
width: 1118px;
background-color: rgba(155, 155, 255, 0.36);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
}
.progress-bar {
height: 5px;
background-color: #aff;
width: 1%;
position: relative;
transition: linear;
}
<div class="slide-progress-bar">
<div class="progress-bar" id="progress-bar"></div>
<!--progress-bar-->
</div>
<button onclick="progressBar()">Start</button>
<!--slide-progress-bar-->
as far I understood I think you are looking for this. the progress-bar will be completed 100% after 10s
var elem = document.getElementById("progress-bar");
var width = 1;
function progressBar() {
resetProgressBar();
id = setInterval(frame, 1000);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width+=10;
elem.style.width = width + '%';
}
}
}
function resetProgressBar() {
width = 1;
elem.style.width = width + '%';
}
progressBar();
.slide-progress-bar {
width: 1118px;
background-color: rgba(255, 0, 255, 0.36);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
}
.progress-bar {
height: 5px;
background-color: #fff2ff;
width: 1%;
position: relative;
transition: linear;
}
<div class="slide-progress-bar">
<div class="progress-bar" id="progress-bar"></div>
<!--progress-bar-->
</div>
let me know if it`s not ok
HI please check below solution
var elem = document.getElementById("progress-bar");
var width = 1;
var id = {};
function progressBar() {
id = setInterval(frame, 100);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
}
}
}
progressBar()
.slide-progress-bar {
width: 1118px;
height: 200px;
background-color: rgba(255, 255, 255, 0.9);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
}
.progress-bar {
height: 20px;
width: 0;
background-color: red;
position: relative;
transition: linear;
}
<div class="slide-progress-bar">
<div class="progress-bar" id="progress-bar"></div>
<!--progress-bar-->
</div>
<!--slide-progress-bar-->
This works for me
I changed the elem to the inner div and removed the width from the CSS
I also changed the speed
Then I actually called the function
var elem = document.getElementById("progress-bar");
var width = 1;
function progressBar() {
resetProgressBar();
id = setInterval(frame, 10);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
elem.style.width = width +"%";
}
}
}
function resetProgressBar() {
width = 1;
elem.style.width = width;
}
progressBar()
.slide-progress-bar {
width: 1118px;
background-color: rgba(155, 155, 155, 0.36);
transition: width 10s linear;
display: inline-block;
vertical-align: middle;
}
.progress-bar {
height: 5px;
background-color: #aff;
position: relative;
transition: linear;
}
<div class="slide-progress-bar">
<div class="progress-bar" id="progress-bar"></div>
<!--progress-bar-->
</div>
<!--slide-progress-bar-->

Execute a function when mouse is over any button

So I have a page where I have replaced my cursor with a div.
The cursor is simply a part of the page that I can animate using CSS.
The main thing I want to achieve is to make this cursor change size when I hover over any button.
I cannot get it to work...
Cursor positioning is handled by a JQuery script but the vanilla one doesn't seem like it wants to work with me...
I can can't fix the error...
// Jquery code that moves the cursor (div element)
$(document).on('mousemove', function(e){
$('#cursor').css({
left: e.pageX - 7,
top: e.pageY - 7
});
});
// Function to be executed when mouse is over a button
document.querySelectorAll('button').addEventListener("mouseover", cursorHovering);
function cursorHovering() {
document.getElementById('object').style = "transform: scale(2);";
}
body {
height: 300px;
width: 300px;
background-color: #ccc;
}
*, body { cursor: none !important; }
#cursor {
position: fixed;
z-index: 20000;
height: 15px;
width: 15px;
background-color: #ffffff;
mix-blend-mode: difference;
border-radius: 50%;
opacity: 0;
transition: 0.3s;
transition-property: transform, opacity;
pointer-events: none;
}
body:hover #cursor {
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div id="cursor"></div>
<button class="button1">Hover over me (1)</button>
<button class="button2">Hover over me (2)</button>
<button class="button3">Hover over me (3)</button>
</body>
You mean something like this?
// Jquery code that moves the cursor (div element)
var c = document.getElementById('cursor');
document.addEventListener('mousemove', (e) => {
c.style.left = e.pageX - 7 + 'px';
c.style.top = e.pageY - 7 + 'px';
});
// Function to be executed when mouse is over a button
document
.querySelectorAll('button')
.forEach(b => {
b.addEventListener("mouseover", () => c.style.transform='scale(2)');
b.addEventListener("mouseout", () => c.style.transform='scale(1)');
});
body {
height: 300px;
width: 300px;
background-color: #ccc;
}
*, body { cursor: none !important; }
#cursor {
position: fixed;
z-index: 20000;
height: 15px;
width: 15px;
background-color: #ffffff;
mix-blend-mode: difference;
border-radius: 50%;
opacity: 0;
transition: 0.3s;
transition-property: transform, opacity;
pointer-events: none;
}
body:hover #cursor {
opacity: 1;
}
<body>
<div id="cursor"></div>
<button class="button1">Hover over me (1)</button>
<button class="button2">Hover over me (2)</button>
<button class="button3">Hover over me (3)</button>
</body>
Here's a vanilla JS solution.
document.addEventListener('mousemove', handleMouseMove, false);
// Cache the elements
const cursor = document.getElementById('cursor');
const buttons = document.querySelectorAll('button');
// For each button add the two event listeners
[...buttons].forEach(button => {
button.addEventListener('mouseover', handleMouseOver, false);
button.addEventListener('mouseout', handleMouseOut, false)
});
function handleMouseMove(e) {
// You need to ensure that you add "px" to the
// end of the value. jQuery does this automatically.
cursor.style.left = `${e.pageX - 7}px`;
cursor.style.top = `${e.pageY - 7}px`;
}
function handleMouseOver() {
cursor.style.transform = 'scale(2)';
}
function handleMouseOut() {
cursor.style.transform = 'scale(1)';
}
body {
height: 300px;
width: 300px;
background-color: #ccc;
}
*,
body {
cursor: none !important;
}
#cursor {
position: fixed;
z-index: 20000;
height: 15px;
width: 15px;
background-color: #ffffff;
mix-blend-mode: difference;
border-radius: 50%;
opacity: 0;
transition: 0.3s;
transition-property: transform, opacity;
pointer-events: none;
}
body:hover #cursor {
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div id="cursor"></div>
<button class="button1">Hover over me (1)</button>
<button class="button2">Hover over me (2)</button>
<button class="button3">Hover over me (3)</button>
</body>

Change transition duration during loop with requestAnimationFrame

I'm trying to change the transition duration in-between the steps of a setTimeout loop.
When the button centre is clicked, setView changes the position of content so that the inner div remains in the centre of the screen. It uses a forEach loop to change the centring using an array of inner divs.
I'd like the transition between the change from alpha inner to bravo inner to take 1s, but once it gets there the transition should be 0s so that is no lag with the centring.
Here's a codepen, then built in is getting an error.
I'm using vanilla ES6.
const content = document.querySelector('.content');
let frame;
function getBounds(div) {
const element = document.getElementById(div);
const body = element.children[0];
const {
x, y, width, height,
} = body.getBoundingClientRect();
return box = {
element, body, x: Math.round(x), y: Math.round(y), width, height,
};
}
function setView(div) {
const centerW = window.innerWidth / 2;
const centerH = window.innerHeight / 2;
const { left, top } = content.getBoundingClientRect();
content.style.left = `${(centerW + left) - (div.x + div.width / 2)}px`;
content.style.top = `${(centerH + top) - (div.y + div.height / 2)}px`;
}
function centreDiv(string) {
const outers = string.split(' ');
outers.forEach(function(outer, index) {
setTimeout(function() {
content.style.transition = 'all 0s linear'; // this works
if (frame) {
cancelAnimationFrame(frame);
}
function tick(now) {
setView(getBounds(outer));
frame = requestAnimationFrame((timestamp) => tick(timestamp, outer));
}
frame = requestAnimationFrame((timestamp) => tick(timestamp, outer));
},
5000 * index);
content.style.transition = 'all 1s linear'; // this isn't working
});
}
document.getElementById('centre').onclick = () => centreDiv(centreText.value.toLowerCase());
* {box-sizing: border-box;}
html,body,div,span {padding: 0; margin: 0; border: 0;}
.controls {
position: absolute;
z-index: 1000;
padding-top: 10px;
padding-left: 20px;
font-family: sans-serif;
color: white;
}
.content {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height:100vh;
background-color: rgb(138,141,143);
transition: all 0s linear;
}
.centre {
position: absolute;
display: block;
width: 5px;
height: 5px;
background-color: white;
}
.outer {
position: absolute;
display: flex;
align-items: center;
justify-content: flex-end;
}
.inner {
display: block;
width: 30px;
height: 30px;
background-color: rgb(37,40,42);
}
.animate {
animation: spin infinite linear;
}
#alpha {
width: 80%;
height: 80%;
background-color: rgb(255,205,0);
animation-duration: 10s;
}
#bravo {
width: 30%;
height: 30%;
background-color: rgb(242,169,0);
animation-duration: 5s;
}
#keyframes spin {
100% {
transform: rotateZ(360deg);
}
}
<div class="controls">
centre: <input id="centreText" type="text" value="alpha bravo"/><button type="button" id="centre">centre</button>
</div>
<div class="content">
<div id="alpha" class="animate outer">
<div class="inner"></div>
</div>
<div id="bravo" class="animate outer">
<div class="inner"></div>
</div>
<div class="centre"></div>
</div>

progress bar is not working

i am trying to made progress bar but its can working plz solve it .
i am using if else for increasing the width but it's not working
var x = document.getElementById("p_bar");
for(var i = 0; i < 100; i++) {
var wid;
wid=1;
if(wid == 800)
break;
else
wid+=8;
x.style.width=wid+"px";
}
document.body.style.background = "#"+((1<<24)*Math.random()|0).toString(16);
#cont {
width: 800px;
height: 30px;
background-color: cornsilk;
position: relative;
}
#p_bar {
width: 8px;
height: 30px;
background-color: red;
position: absolute;
}
<div id="cont">
<div id="p_bar"></div>
</div>
<p id="write"></p>
var x=document.getElementById("p_bar");
var wid = 1;
var it = setInterval(function(){
if(wid <= 800){
wid+=8;
x.style.width=wid+"px";
}else{
clearInterval(it);
}
}, 1000);
document.body.style.background = "#"+((1<<24)*Math.random()|0).toString(16);
#cont{
width: 800px;
height: 30px;
background-color: cornsilk;
position: relative;
}
#p_bar{
width: 8px;
height: 30px;
background-color: red;
position: absolute;
}
<div id="cont">
<div id="p_bar"></div></div>
<p id="write"></p>
If you want to see moving progress bar, You should use setInterval().
If you use just for, you can't see any animation.
Because, computer's calculating is so fast, so you can see only the result of for
I wrote it again using functions, try this shubham:
var x = document.getElementById('p_bar');
var container = document.getElementById('cont');
var write = document.getElementById('write');
var containerWidth = container.offsetWidth;
var currentWidth = x.offsetWidth;
var compeleteProgress = function (step, every) {
currentWidth = Math.min(currentWidth + step, containerWidth);
write.innerHTML = Math.floor((currentWidth / containerWidth) * 100) + '%' // Priniting percentage
x.style.width = currentWidth + 'px'
if (currentWidth < containerWidth) setTimeout(function () {
compeleteProgress(step, every)
}, every)
}
compeleteProgress(8, 300) // When you call this function, everything starts
document.body.style.background = "#"+((1<<24)*Math.random()|0).toString(16);
#cont{
width: 800px;
height: 30px;
background-color: cornsilk;
position: relative;
}
#p_bar{
width: 8px;
height: 30px;
background-color: red;
position: absolute;
}
<div id="cont">
<div id="p_bar"></div>
</div>
<p id="write"></p>
I am not sure what behavior you really expects. The Bar size is usually changed according to any application events (in my example by timeouts). I hope this helps:
document.body.style.background = "#"+((1<<24)*Math.random()|0).toString(16);
var setBarWidthInPercent = function(barId, value){
var bar=document.getElementById(barId);
bar.style.width = value+"%";
}
setTimeout(function(){
setBarWidthInPercent("p_bar",10)
},500)
setTimeout(function(){
setBarWidthInPercent("p_bar",50)
},1500)
setTimeout(function(){
setBarWidthInPercent("p_bar",100)
},3000)
#cont{
width: 800px;
height: 30px;
background-color: cornsilk;
position: relative;
}
#p_bar{
width: 8px;
height: 30px;
background-color: red;
position: absolute;
-webkit-transition: width 1s ease-in-out;
-moz-transition: width 1s ease-in-out;
-o-transition: width 1s ease-in-out;
transition: width 1s ease-in-out;
}
<div id="cont">
<div id="p_bar"></div></div>
<p id="write"></p>

Categories