I am trying to add a simple javascript progress bar to my website, I found a few scripts, but I always encounter the same problem - I am able to intialize the loader and set it to increment to a given value, but cannot do it in steps. Here is a simple example - https://jsfiddle.net/kimmobrunfeldt/k5v2d0rr/
At the end there is:
bar.animate(1.0);
How can i have it animated in steps? Lets say first to 50% then (after 2 secs) to 75% and then 100%. I've tried
bar.animate(0.5);
bar.animate(0.75);
bar.animate(1);
as well as:
setTimeout(function(){bar.animate(0.5)}, 2000);
setTimeout(function(){bar.animate(0.75)}, 2000);
setTimeout(function(){bar.animate(1)}, 2000);
but it always chooses the last (highest) value, instead of being animated in steps. Any advice appreicated.
bar.animate(0.5);
bar.animate(0.75);
bar.animate(1);
The above code runs simultaneously, and the last one overrides the others.
setTimeout(function(){bar.animate(0.5); console.log("animate")}, 2000);
console.log('timeout 1 called');
setTimeout(function(){bar.animate(0.75); console.log("animate")}, 2000);
console.log('timeout 2 called');
setTimeout(function(){bar.animate(1); console.log("animate")}, 2000);
console.log('timeout 3 called');
Soon as the first timeout is set, it doesn't wait for the delay before setting the next. Check the logs on the console to see what happens.
The problem is that those scripts run simultaneously. Do something like this (or something better):
bar.animate(0.5); // Number from 0.0 to 1.0
setTimeout(function () {
bar.animate(0.75);
}, 2000);
setTimeout(function () {
bar.animate(1.0);
}, 4000);
If you wanted to just animate the bar in sequences for the sake of it, you can do keyframes with CSS too.
The problem is that you're, essentially, queuing up all of your steps to happen simultaneously. Instead, you want to pass a callback to the animate function so when it finishes, you can tell it to move to the next step.
// progressbar.js#1.0.0 version is used
// Docs: http://progressbarjs.readthedocs.org/en/1.0.0/
var bar = new ProgressBar.Line(container, {
strokeWidth: 4,
easing: 'easeInOut',
duration: 1400,
color: '#FFEA82',
trailColor: '#eee',
trailWidth: 1,
svgStyle: {
width: '100%',
height: '100%'
},
text: {
style: {
// Text color.
// Default: same as stroke color (options.color)
color: '#999',
position: 'absolute',
right: '0',
top: '30px',
padding: 0,
margin: 0,
transform: null
},
autoStyleContainer: false
},
from: {
color: '#FFEA82'
},
to: {
color: '#ED6A5A'
},
step: (state, bar) => {
bar.setText(Math.round(bar.value() * 100) + ' %');
}
});
// Keep track of the current value
var value = 0;
setTimeout(function increment() {
value += 0.1;
bar.animate(value, function() {
// Animation has completed, queue up another step
if (value < 1) {
setTimeout(increment, 500);
}
});
}, 1000);
#container {
margin: 20px;
width: 400px;
height: 8px;
position: relative;
}
<script src="https://rawgit.com/kimmobrunfeldt/progressbar.js/1.0.0/dist/progressbar.js"></script>
<div id="container"></div>
Related
I switched from anime.js to velocity.js and try to defnine a simple animation with delayed opacity. For this I use the stagger.
But if I put a function for the stagger delay in it, I have no delayed stag animation. every elemenet is popping up but not animated and delayed.
In the first i tried what I have used for the animation with anime.js and the second one is directly from the github issue.
Here is also my jsbin:
https://jsbin.com/firetuh/edit?html,css,js,output
var greenElem = $('.pointGreen');
var yellowElem = $('.pointYellow');
var redElem = $('.pointRed');
setInterval(function() {
greenElem
.velocity({
fill: '#5cb83f',
opacity: 1
}, { stagger:
function(elem, index) {
return index * 500
}
});
yellowElem
.velocity({
fill: '#feb65c',
opacity: 1
}, { stagger:
function(elementIndex, element) {
return 1000 * (0.85 - Math.exp(-elementIndex/10));
}
});
redElem
.velocity({
fill: '#d43f3a',
opacity: 1
}, { stagger: 500 });
});
It looks like this could be either an intentional oversight or a bug with velocity. It looks like from the code that stagger only works if the first value passed in is a pre-canned effect like fadeIn or transition.slideLeftIn - it doesn't look like it is supported for other animation types. You could, in theory, achieve this on your own with something like
yellowElem
.each(function(index, element) {
$(element).velocity({
fill: '#feb65c',
opacity: 1
},{
delay: index * 500
});
});
Also, you will want to change your setInterval to setTimeout
I need to get a picture crawling smoothly without slowing down at the start and finish.
setInterval(function runIt() {
$(".bffffg").animate({
backgroundPositionX: 300
}, 8000);
$(".bffffg").animate({
backgroundPositionX: 0
}, 0);
}, 1);
.bffffg {
display: block;
position: absolute;
width: 100%;
height: 100%;
background: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div class="bffffg"></div>
How to apply a linear effect to the animation?
And even apply different effects to it?
If you are looking for setting easing parameter, you may pass it as a separate argument like here:
$('your-selector').animate({
'your-property': 'value'
}, 8000, 'linear');
...or with options object like here:
$('your-selector').animate({
'your-property': 'value'
}, {
duration: 8000,
easing: 'linear'
});
Here is DOC for jQuery .animate() :)
I am trying to achieve a situation where an animation is triggered if an element has a particular background = url(" "). I am using velocity.js as the animation plugin and am able to achieve this no problem on all browser except IE, in which it fails to recognise the background url in the if statement.
I have two examples in the code below.
The first one (the orange square) uses -
if (box.style.background == "orange")
{ run(); }
to determine whether to run the animation. IE is fine with this.
However the second (the pink triangle) uses -
if (triangle.style.background == "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat")
{ runTriangle(); }
to determine whether to run the animation. IE is the only browser not to run this.
Does anyone have any idea where I'm going wrong here.
JS Fiddle example
HTML
<div id="box"></div>
<div id="triangle"></div>
CSS
#box {
width: 100px;
height: 100px;
position: absolute; }
#triangle {
width: 200px;
height: 100px;
top: 120px;
position: absolute;
z-index: 4; }
JS
window.setInterval(function runAll() {
var box = document.getElementById('box');
box.style.background = "orange";
function run() {
Velocity(box, {left: 300}, {easing: "easeInOutQuad", duration: 1000, delay: 0});
Velocity(box, {left: 10}, {easing: "easeInOutQuad", duration: 1000, delay: 0});
}
if (box.style.background == "orange")
{ run(); }
var triangle = document.getElementById('triangle');
triangle.style.background = "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat";
function runTriangle() {
Velocity(triangle, {left: 300}, {easing: "easeInOutQuad", duration: 1000, delay: 200});
Velocity(triangle, {left: 10}, {easing: "easeInOutQuad", duration: 1000, delay: 0});
}
if (triangle.style.background == "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat")
{ runTriangle(); }
}, 1000);
runAll();
The URLs in IE are different from webkit and/or Gecko, it is not safe to base your logic on the url paths.
if (triangle.style.background == "url(http://garyvoss.co.uk/images/triangle.svg) no-repeat" || triangle.style.background == 'url("http://garyvoss.co.uk/images/triangle.svg") no-repeat' )
{ runTriangle(); }
I've managed to find a convoluted way around the issue.
Using .match I can identify a section of the url path and apply that to the if statement so that if that section is present then the animation runs.
I've create a third example (the green circle) in this JS Fiddle that shows how it works.
var str = circle.style.background;
var res = str.match(/circle/g);
document.getElementById("check").innerHTML = res;
if (document.getElementById("check").innerHTML === "circle")
{ runCircle(); }
I made some simple animation for a website with jQuery inside Joomla!, all seems fine but I have a very strange issue during the loop. Even cells are all fixed dims. inside the loop I. You could check it here http://db.tt/uuD00TKc the issue only happens with Firefox.
The JS code is:
jQuery(document).ready(function () {
function loop() {
jQuery("#txt1").animate({
backgroundColor: "#0089BC"
}, 3000, function() {
loop();
});
jQuery("#txt1").animate({
backgroundColor: "#FFF"
}, 3000);
jQuery("#txt2").animate({
backgroundColor: "#0089BC"
}, 9000, function() {
loop();
});
jQuery("#txt2").animate({
backgroundColor: "#FFF"
}, 9000);
jQuery("#txt3").animate({
backgroundColor: "#0089BC"
}, 6000, function() {
loop();
});
jQuery("#txt3").animate({
backgroundColor: "#FFF"
}, 6000);
}
loop();
});
jQuery(document).ready(function () {
jQuery("#img1").hide().fadeIn(3000);
setInterval(function () {
jQuery("#img1").fadeOut(3000).fadeIn(3000);
}, 5000);
jQuery("#img2").hide().fadeIn(9000);
setInterval(function () {
jQuery("#img2").fadeOut(9000).fadeIn(9000);
}, 5000);
jQuery("#img3").hide().fadeIn(6000);
setInterval(function () {
jQuery("#img3").fadeOut(6000).fadeIn(6000);
}, 5000);
});
HTML Code
<div id="home-mosaico">
<div class="row">
<span class="cell-img" id="img1"><img src="http://www.quatrotd.co.uk/images/home/substation-02.jpg" alt="Substation" title="Substation" /></span>
<span class="cell" id="txt1">Engineering<br />and Construction</span>
<span class="cell-img" id="img2"><img src="http://www.quatrotd.co.uk/images/home/substation-01.jpg" alt="Substation" title="Substation" /></span>
</div>
<div class="row">
<span class="cell" id="txt2">Transmission Lines</span>
<span class="cell-img" id="img3"><img src="http://www.quatrotd.co.uk/images/home/transmision_lines-01.jpg" alt="Transmision Lines" title="Transmision Lines" /></span>
<span class="cell" id="txt3">Substations</span>
</div>
</div>
CSS code
/*** Home mosaico ***/
#home-mosaico {
display: table;
width: 940px;
height: 500px;
}
#home-mosaico .row {
display: table-row;
height: 250px;
}
#home-mosaico .cell-img {
display: table-cell;
width: 313px;
background-color: #0089BC;
vertical-align:middle;
text-align:center;
font-size:20px;
line-height: 24px;
font-weight:normal;
color:#ffffff;
}
#home-mosaico .cell {
display: table-cell;
width: 313px;
background-color: #FFF;
vertical-align:middle;
text-align:center;
font-size:20px;
line-height: 24px;
font-weight:normal;
color:#ffffff;
}
Your loop function looks like it will run into some problems. As soon as the loop function starts, it will keep recursively calling itself instantly putting a large strain on the browser as there isn't even a seconds break between calls.
On top of that, as soon as any of the animations are finished, they will also additionally call the loop function again compounding the first issue. While the animations may stack correctly (one after the other on the elements you told it to animate), there is a huge amount of recursion occurring in that loop function.
An alternative for the loop function but still getting the same effect (animation stacking) might be something like:
jQuery(document).ready(function () {
var txt1Animate = function()
{
jQuery("#txt1").animate({
backgroundColor: "#0089BC"
}, 3000, function(){
jQuery(this).animate({
backgroundColor: "#FFF"
}, 3000, txt1Animate);
});
}
var txt2Animate = function()
{
jQuery("#txt2").animate({
backgroundColor: "#0089BC"
}, 9000, function(){
jQuery(this).animate({
backgroundColor: "#FFF"
}, 9000, txt2Animate);
});
}
var txt3Animate = function()
{
jQuery("#txt3").animate({
backgroundColor: "#0089BC"
}, 6000, function(){
jQuery(this).animate({
backgroundColor: "#FFF"
}, 6000, txt3Animate);
});
}
txt1Animate();
txt2Animate();
txt3Animate();
});
This would now correctly wait for the first animation to finish on the element, then do the second and only once the second is complete will it start again. This stops the animation queue from spiraling out of control with 100s to 1000s of animations being queued a second.
Addressing your second part of the question, you are calling fadeOut and then straight away calling fadeIn. While this should queue that animation, that goes for 12 seconds and then you have it already being called again looped by setInterval. This would also create issues in the long term with the queue growing every 10 or so seconds without any chance of finishing.
jQuery(document).ready(function () {
jQuery("#img1").hide().fadeIn(3000);
var img1Fade = function()
{
jQuery("#img1").fadeOut(3000).fadeIn(3000,function()
{
setTimeout(img1Fade,5000);
});
}
jQuery("#img2").hide().fadeIn(9000);
var img2Fade = function()
{
jQuery("#img2").fadeOut(9000).fadeIn(9000,function()
{
setTimeout(img2Fade,5000);
});
}
jQuery("#img3").hide().fadeIn(6000);
var img3Fade = function()
{
jQuery("#img3").fadeOut(6000).fadeIn(6000,function()
{
setTimeout(img3Fade,5000);
});
}
img1Fade();
img2Fade();
img3Fade();
});
Similar to the other code I provided, this loops on itself in a way that won't have a huge queue of animations at once. It nicely waits for the fade in to finish before running setTimeout to loop the function again.
EDIT
Picked up one bug in the code I supplied originally, I was using $ for jQuery however in your code on the site you linked, I required to do jQuery instead.
Mmmh to me it looks like you might have an unclosed DIV or some other unclosed tag somewhere.
Every modern browser tries to solve this common mistake but FF does it in an odd way.
Let us know.
I want to have a div that animates the currently active image out of the view and instead animates in another image. There are several of these divs, and each one should have the same basic functionality but linked to different images. The problem I'm having is that you can click many of the divs before the animation is complete, which fires the other animations at the same time. My goal is to only be able to fire one animation at a time, and when the animation finishes you're able to fire the next animation. I've tried using unbind which works OK but then I'd have to rebind it later and I don't know how to do this. I'm really a jQuery noob so I would greatly apreciate an answer. Thanks!
My code:
$('.div1').click(function clickevent() {
$('.img2, .img3').animate({
opacity: 0.1,
left: 600
}, 1000, function() {
$('.img1').animate({
opacity: 1,
left: 0
}, 500, function() {
$('.div2, .div3').bind('click', clickevent); /* Here I want to rebind the function */
});
});
$(this).addClass("active");
$('.div2, div3').removeClass("active");
$('div2, .div3').unbind('click', clickevent);
});
I have two other codeblocks for .div2 and .div3 which look the same but with different classes in different places. Is there any way to make the images finish their animation before being able to animate again? Thanks.
Is this what you need:
var canAnimate = true;
$('.div1').click(function clickevent() {
// these 4 lines have to be in all code blocks (ie. for .div2 and .div3)
if (! canAnimate) {
return;
}
canAnimate = false;
$('.img2, .img3').animate({
opacity: 0.1,
left: 600
}, 1000, function() {
$('.img1').animate({
opacity: 1,
left: 0
}, 500, function() {
canAnimate = true; // this should also be included for .div2 and .div3 code blocks
});
});
$(this).addClass("active");
$('.div2, div3').removeClass("active");
});
I think queue() will append the animations but not stop them, so if you click 10 times on the images, the click handler will animate it 10 times but one after another. I guess you want only animate the images when no image is currenty animated so you can use:
$('.div1').click(function clickevent() {
// When no image is currently animated then perform the animation
if($j('.img1, .img2, .img3').is(':animated') == false)
{
$('.img2, .img3').animate({
opacity: 0.1,
left: 600
}, 1000, function() {
$('.img1').animate({
opacity: 1,
left: 0
}, 500);
});
$(this).addClass("active");
$('.div2, div3').removeClass("active");
} else {
// There is currently an animation runnig, do nothing
}
});
See this for more information: http://api.jquery.com/animated-selector/
You should also get some information about caching of selection results.