get the progress with animate() JQUERY - javascript

Here is the spinet:
$('#processing .progress-bar').animate({'width':'60%'},4000);
Is it possible to display how the milliseconds are being countdown by the function?
for instance I want to be able to display:
4000
3000
2000
1000
0000
then the function stops

You can add a step function to the jquery animate, and inside calcualte how much time is left for the animation to finish:
$(function () {
var Now = 0;
var animationDuration = 4000;
var DesiredWidth = "200";
$(".test").animate({
width: DesiredWidth
}, {
easing:"linear",
duration: animationDuration,
//the argument in the step call back function will hold the
// current position of the animated property - width in this case.
step: function (currentWidth,fx) {
Now = Math.round((100/DesiredWidth)*currentWidth);
$(".ms_span").text(Now+"%");
}
});
});
div {
width: 0;
height: 100px;
display: block;
background: purple;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test"></div>
<br/>Percent: <span class="ms_span">

var duration = 4000,
interval = 1000,
pbar = $('#processing .progress-bar');
pbar.text( duration );
var cd = setInterval(function() {
duration -= interval;
pbar.text( duration );
}, interval);
pbar.animate({'width':'60%'}, duration, function() {
clearInterval(cd);
pbar.text( '0000' );
});
.progress-bar {
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="processing">
<div class="progress-bar">pBar</div>
</div>

After looking at #Banana's solution, I realized that I had completely forgotten about the step function and the new(ish) progress function, both of which can be passed to .animate. My updated solution is below, and I have removed the other to avoid confusion.
var $steps = $("#steps");
$('#processing .progress-bar').animate({
'width': '60%'
}, {
duration: 4000,
progress: function(prom, prog, rem) {
$steps.html("Prog: " + prog + "<br/>Rem: " + rem);
}
});
#processing {
width: 80%;
margin: 5%;
border: 2px solid black;
height: 25px;
}
#processing .progress-bar {
height: 100%;
background: lime;
width: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
<div id="processing">
<div class="progress-bar"></div> <span id="steps"></span>
</div>
</div>
As a side-note, depending on what you are planning to use this for, the other thing that you might want to look into is jQuery's .progress method, which handles progress notifications. Note that I am fairly certain that calling .progress on animations themselves won't have any effect unless you use a solution like the above to make progress notifications at each step of the animation. This is done with calls to .notify or .notifyWith but doing this in an animation is a little extreme. Regardless, this can be useful for situations in which you have an asynchronous call running for an indeterminate amount of time.
Docs for deferred.promise.
Docs for deferred.notify.
Docs for deferred.notifyWith.

Related

How do I use throttle with .hover(); jQuery?

I'm trying to find the most concise way to throttle a hover function with jQuery. There are many examples of this but they all seem to not work as intended. For example the use of $.throttle doesn't error but it stops the animation from working altogether. This is the code which I'm trying to throttle:
jQuery(document).ready(function($){
var $navTab = $('.nav-tab-parent');
function moveNavTab(e) {
TweenLite.to($navTab, 0.3, {
css: {
left: e.pageX,
top: e.pageY
}
});
}
$(window).on('mousemove', moveNavTab);
$(".toggle-bars").hover( // this is the .hover() function I need to throttle.
function() {
$(".nav-tab-parent").animate({
opacity: 1
});
$(".nav-tab-parent").delay(10).animate({
width: "36px",
easing: "swing"
});
$(".nav-tab").html("MENU");
$(".nav-tab").delay(350).animate({
opacity: 1
});
}, function() {
$(".nav-tab").animate({
opacity: 0
});
$(".nav-tab-parent").delay(150).animate({
width: "0",
opacity: 0,
easing: "swing"
});
}
);
});
I must be missing something here but can't figure it out. Any help in achieving this would be greatly appreciated!
Changed to use entirely GSAP and relying on .timescale() see the documentation — didn't know the underlying structure so will need some configuring but the basis is there. GSAP has a crazy deep documentation but should be familiar enough to jquery with object animations.
var tl = gsap.timeline().timeScale(-1);
tl.fromTo(".nav-tab-parent", {
autoAlpha: 0,
duration: 1
}, {
autoAlpha: 1,
duration: 1
});
$(".toggle-bars").hover(function() {
tl.timeScale(1);
}, function() {
tl.timeScale(-1);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="toggle-bars">.toggle-bars
<div class="nav-tab-parent">.nav-tab-parent</div>
</div>
I suppose you are trying to achieve something like this. You could try to use .stop() method - it will stop current animation and after that you can run next one. Try to play with arguments to choose what best will suit your case.
let $hover = $('.hover-box'),
$target = $('.animated-box');
function show() {
$target.stop(true, true).animate({
opacity: 1,
})
}
function hide() {
$target.stop(true, true).animate({
opacity: 0
})
}
$hover.hover(show, hide)
.hover-box,
.animated-box {
width: 100px;
height: 100px;
border-radius: 8px;
}
.hover-box {
border: 1px solid #ddd;
display: inline-flex;
align-items: center;
justify-content: center;
text-transform: uppercase;
font-family: sans-serif;
cursor: pointer;
margin-bottom: 16px;
}
.hover-box:hover {
background: #ddd;
}
.animated-box {
opacity: 0;
background: gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='hover-box'>Hover</div>
<div class='animated-box'></div>

Run function at 60fps

I'm currently using setInterval( () => {}, 16 ) to run my code 60fps, but this makes the code run at 62.5fps, which makes the game movements jump forward twice the speed for a few frames per second. Using interval 17 makes the game movement freeze for a frame every once in a while.
How can I run the code truly at 60fps for maximum smoothness?
use Window.requestAnimationFrame([callback])
That way your application will be called when it's time to render, wether the monitor is 30hz, 60hz or 120hz or more.
See this example from https://css-tricks.com/using-requestanimationframe/ on how to use it if the MDN documentation isn't clear enough.
var globalID;
function repeatOften() {
$("<div />").appendTo("body");
globalID = requestAnimationFrame(repeatOften);
}
globalID = requestAnimationFrame(repeatOften);
$("#stop").on("click", function() {
cancelAnimationFrame(globalID);
});
$("#start").on("click", function() {
globalID = requestAnimationFrame(repeatOften);
});
div {
width: 10px;
height: 10px;
background: orange;
float: left;
}
button {
position: absolute;
top: 20px;
left: 20px;
}
#stop {
left: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="start">start</button>
<button id="stop">stop</button>

use jQuery setInterval to decreases the width of element but from only one side (left or right )

here are my codes for decreasing the width of an selected element(class = "life_bar"), but as my attached pictures show, I want it to decrease its width from left or right( let's do left as example), but it always goes from both side, what should I do?
here are jQuery codes
$(function () {
var timmer;
gocount();
function gocount(){
timmer = setInterval(function () {
var life_bar_width = $(".life_bar").width();
life_bar_width -= 100;
$(".life_bar").css( {width: life_bar_width,
left: '-50px'})
},1000);
}
});
here are css codes
.life_bar{
width: 500px;
height: 10px;
background: crimson;
margin: 100px auto;
}
here are html codes
<body>
<div class="life_bar"></div>
</body>
using translate negative on X every interval tick:
$(function () {
var timmer;
gocount();
let counter = 1
function gocount(){
timmer = setInterval(function () {
var life_bar_width = $(".life_bar").width();
life_bar_width -= 100;
$(".life_bar").css({
width: life_bar_width,
left: '-50px',
transform: `translate(${-50*counter}px)`
})
counter++
},1000);
}
});
.life_bar{
width: 500px;
height: 10px;
background: crimson;
margin: 100px auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="life_bar"></div>

Javascript - How to change animation's duration onclick

How can I change the animation duration onclick? This is what I've done, I created two buttons, one with an animationduration of 10s while the other has an animationduration of 20s. The duration regardless of which button I click is the same, 10 seconds, as it is in the class section. How can I get depending on the button I click two different durations? Please use normal Javascript, no Jquery. Thank you! I also need to use the document.GetElementById().classname =""; as it is in the code.
function tenseconds() {
animation();
var sd = document.getElementById('ghost').className = 'earth';
sd.style.animationDuration = "10s";
}
function twentyseconds() {
animation();
var sd = document.getElementById('ghost').className = 'earth';
sd.style.animationDuration = "20s";
}
function animation() {
document.getElementById('ghost').className = 'earth';
}
<!DOCTYPE html>
<html>
<head>
<style>
.earth {
position: relative;
animation: move 10s linear;
background: red;
height: 20px;
width: 20px;
}
#-webkit-keyframes move {
from {
left: 0%;
}
to {
left: 100%;
}
}
</style>
</head>
<body>
<div id="ghost"> </div>
<button onclick="tenseconds();">10 seconds </button>
<button onclick="twentyseconds()"> 20 seconds </button>
</body>
</html>
Updated to use an animation, data attributes etc. Customize as needed. NOT supported in Edge, IE perhaps others. Leave to you to investigate possible ways to fix that. Review OLD edit for the original "fix"
I added another element and button so you could see how it might be used.
var myAnimation = {
keyframes: [
// keyframes
{
transform: 'translateX(0px)'
},
{
transform: 'translateX(300px)'
}
],
options: {
// timing options
// ms of duration default 1 second
duration: 1000,
iterations: 1, //forever would be Infinity
easing: "linear"
}
};
function animation(target, duration, visual) {
let sd = document.getElementById(target);
sd.className = visual;
myAnimation.options.duration = duration * 1000;
sd.animate(myAnimation.keyframes, myAnimation.options,visual);
}
function setup() {
let classThings = document.getElementsByClassName("animate-button");
let myFunction = function() {
let duration = this.dataset.duration;
let visual = this.dataset.visual;
let target = this.dataset.target;
animation(target, duration, visual);
};
for (var i = 0; i < classThings.length; i++) {
classThings[i].addEventListener('click', myFunction, false);
}
}
(function() {
setup();
})();
<!DOCTYPE html>
<html>
<head>
<style>
.fire {
position: relative;
background: red;
height: 20px;
width: 20px;
}
.water {
position: relative;
background: blue;
height: 20px;
width: 20px;
}
</style>
</head>
<body>
<div id="ghost"></div>
<div id="billy"></div>
<button class="animate-button" data-duration="10" data-target="ghost" data-visual="fire">10 seconds</button>
<button class="animate-button" data-duration="20" data-target="ghost" data-visual="fire">20 seconds</button>
<button class="animate-button" data-duration="5" data-target="billy" data-visual="water">5 seconds billy</button>
</body>
</html>
I created a little function that takes the animation time in seconds as an argument. Read the comments in the code for explanation.
function animation(duration) {
// select whatever element you are trying to animate
let target = document.getElementById('ghost');
// change the animationduration before starting to animate
target.style.animationDuration = `${duration}s`;
// add the animating class and start the animation
target.classList.add('animating');
// create a timeout to remove the animating class from your animated element
setTimeout(() => {
target.classList.remove('animating');
}, `${duration*1000}`);
}
#ghost{
position: relative;
background: red;
height: 20px;
width: 20px;
}
.animating {
animation: move 10s linear;
}
#-webkit-keyframes move {
from {
left: 0%;
}
to {
left: 100%;
}
}
<!DOCTYPE html>
<div id="ghost"> </div>
<button onclick="animation(10);">10 seconds </button>
<button onclick="animation(20);"> 20 seconds </button>

How can I make an element on hover?

All I'm trying to do is something like this mechanism:
Here is what I've tried so far:
$(document).ready(function(){
$('a').bind('mouseenter', function() {
var self = $(this);
this.iid = setInterval(function() {
var tag_name = self.text(),
top = self.position().top + self.outerHeight(true),
left = self.position().left;
self.append("<div class='tag_info'>Some explanations about"+tag_name+"</div>")
$(".tag_info").css({top: top + "px", left: left + "px"}).fadeIn(200);
}, 525);
}).bind('mouseleave', function(){
this.iid && clearInterval(this.iid);
});
});
body{
padding: 20px;
}
a {
color: #3e6d8e !important;
background-color: #E1ECF4;
padding: 2px 5px;
}
.tag_info{
position: reletive;
width: 130px;
height: 30px;
display:none;
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a>tag1</a>
<a>tag2</a>
As you see, it will be repeated every time. How can I execute it once per hover? And why the position doesn't apply?
Also is what I'm doing a right algorithm for such thing?
Thank you.
I am not sure why you are using setInterval but I think this should work. I removed setInterval and everytime the mouseenter event occurs we can append <div class='tag_info'> and every time mouseleave event occurs we can remove the the appended div.
$(document).ready(function(){
$('#test').bind('mouseenter', function() {
var self = $(this);
var tag_name = self.text(),
top = self.position().top + self.outerHeight(true),
left = self.position().left;
self.append("<div class='tag_info'>Some explanations about"+tag_name+"</div>")
$(".tag_info").css({top: top + "px", left: left + "px"}).fadeIn(200);
}).bind('mouseleave', function(){
$(this).children('.tag_info').remove();
});
});
body{
padding: 20px;
}
a {
color: #3e6d8e !important;
background-color: #E1ECF4;
padding: 2px 5px;
}
.tag_info{
position: reletive;
width: 130px;
height: 30px;
display:none;
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="test">tag1</a>
Like Dij said:
What you're doing:
setInterval - (repeats your function every 525ms)
What you want:
setTimeout - (executes your function once after 525ms delay)
Read more:
setInterval https://www.w3schools.com/jsref/met_win_setinterval.asp
setTimeout https://www.w3schools.com/jsref/met_win_settimeout.asp

Categories

Resources