Issue:
I am using the Circle Progress JQuery plugin (version: 0.6.0) for a project and have made some modifications to it, however, each circle seems to repeat itself (or loop) for an extended period of time rather than only performing the animation once.
Due to the modifications made, such as adding a link to where if it is clicked, the animation begins, doesn't seem to be where the issue lies. It's when you start to scroll down, and when you do - every circle starts animating based on the percentage set but keeps repeating itself several times before it stops. It should only start the animation for each circle once when the user scrolls down but I can't seem to figure out the root of why this is occurring.
Here is what I have:
$('.about_nav a:nth-of-type(2)').click(function () {
function animateElements() {
$('.progressbar').each(function () {
var elementPos = $(this).offset().top;
var topOfWindow = $(window).scrollTop();
var percent = $(this).find('.circle').attr('data-percent');
var percentage = parseInt(percent, 10) / parseInt(100, 10);
var animate = $(this).data('animate');
if (elementPos < topOfWindow + $(window).height() - 30 && !animate) {
$(this).data('animate', false); // Change this 'false -or- true' - Currently set to false so that each time a user clicks on 'Skill-set' link, animation occurs
$(this).find('.circle').circleProgress({
startAngle: -Math.PI / 2,
value: percent / 100,
thickness: 2, // Change this for thickness
fill: {
color: '#16A085'
}
}).on('circle-animation-progress', function (event, progress, stepValue) {
$(this).find('.percent').text((stepValue*100).toFixed(0) + "%"); // NOTE: Change '.toFixed(0)' to '.toFixed(1)' to get 1 decimal place to the right...
}).stop();
}
});
}
animateElements();
$('.about_body_wrapper').scroll(animateElements);
});
Here is a rough demo of what I mean: DEMO - Click "Skill-set" tab and scroll down.
Any help on this would be greatly appreciated!
so I think I've achieved what you wanted on This updated(again) JSFIDDLE
basically, I set the data-animate property to true right before the animation begins, which stops any subsequent animate calls from animating it again (the looping issue you were seeing).
Then, I took the animateElements function definition out of the click handling event. I did this so I could call it on a more global scope. I now call animateElements in the click handler that changes the tabs. Had to do that because it being fired on page load was making all the elements offsetTop = 0 because they started out hidden.
Lastly, I added an init property to the animate elements function which resets all the data-animate to false when true. Its only true when called from a tab click, not by the scroll event.
heres the relevant code update:
...new init param (also have to make room for the scroll event passed in)
function animateElements(e, init) {
if(init){
$('.progressbar').data('animate', false);
}
...animateElements is now initially called by the tab click handler
$(currentlist).fadeOut(250, function () {
$(newlist).fadeIn(200, function(){
animateElements({}, true);
});
});
lastly, note theres a bunch of stuff in there now you can cut out now that I forgot to in the jsfiddle from when I was proving the concept.
cheers!
Related
So I'm trying to add a progress bar to the "Superslides" slider. I've used setInverval to trigger this when a slide finishes animating and for the most part it works.
I also added a little bit that resets the interval if someone clicks one of the links on the slider (next slide, prev, or pagination) and that also works however the slider has touch support using hammer.js and when I try to do the same thing after a swipe event it doesn't seem to reset properly. It resets the progess bar's width back to 0 but the interval continues despite trying to clear it.
I'm probably doing something fairly stupid but I've been scratching my head for a while so I thought I'd ask what I'm doing wrong.
$(document).on('animated.slides', function() {
var progressBar = $('#progress-bar');
width = 0;
progressBar.width(width);
var interval = setInterval(function() {
width += 1;
progressBar.css('width', width + '%');
if (width >= 100) {
clearInterval(interval);
}
//Trying to reset on swipe (I've also tried putting this below outside of interval
Hammer($slides[0]).on("swipeleft swiperight", function(e) {
width = 0;
clearInterval(interval);
});
}, 160);
//reset on anchor click
$("#slides a").click(function(){
clearInterval(interval);
});
});
I believe I solved the issue myself. The slider's implementation uses $slides as a variable for "#slider" and then uses that to trigger the swipe animations. I copied and pasted this into my interval function as is. When I used the id rather than the variable it seems to have worked.
Is it possible to slow down the speed of a draggable element?
I have build a simple slider with jQuery drag and drop. When the slider element (the draggable element) moves to certain positions a picture fades in. So if you move the draggable element not too fast it looks like you can handle a "picture animation" with the slider. Now, I want to slow down the draggable element. So the user never can drag the element too fast.
This is an example of my code.
$('.slider').mousemove(function(){
if($(this).position().left >= 0 && $(this).position().left <= 2 ) {
$('.slider_1').fadeIn();
$('.slider_2').fadeOut();
}
...
I hope someone can help me :)
Ah! finally an interesting jQuery question.
This can definitely be achieved. Below I've explained how. If you want to go straight to the demo, click here.
Let's assume your HTML is setup as follows:
<div id="slider">
<div id="bar"></div>
</div>
Where the bar is the actual thing you click and drag.
Now what you need to do is the following:
get the $('#bar').offset().left
explicitly specify the position of #bar when the draggable is dragged, using some extra variable SPEED
For example:
ui.position.left += (ui.offset.left - ui.originalPosition.left - leftOffset)*SPEED;
Then, you can use the $('#bar').offset().left in jQuery's .fadeTo() (or other) function to change the opacity of the image you are talking about.
This all seems rather trivial, but it's not. There are some problems when trying to implement this. For example:
When the slider reaches the maximum sliding distance, it should stop animating or be reset. You can do this in multiple ways but I think the easiest solution is to write a .mousedown / .mouseup listener which updates a variable dragging, that keeps track whether the user is still trying to drag #bar. If it's not, reset #bar. If it is, keep the slider at the maximum distance until .mouseup is fired.
Also, you must be careful with predefined borders.
The code I propose is the following:
// Specify your variables here
var SPEED = -0.6;
var border = 1; // specify border width that is used in CSS
var fadeSpeed = 0; // specify the fading speed when moving the slider
var fadeSpeedBack = 500; // specify the fading speed when the slider reverts back to the left
// Some pre-calculations
var dragging = false;
var slider = $('#slider');
var leftOffset = slider.offset().left + border;
var adjustedSliderWidth = 0.5*slider.width();
// the draggable function
$('#bar').draggable({
axis: "x",
revert : function(event, ui) {
$(this).data("draggable").originalPosition = {
top : 0,
left : 0
};
$('#image').fadeTo(fadeSpeedBack, 0);
return !event;
},
drag: function (event, ui) {
var barOffset = $('#bar').offset().left - leftOffset;
if (barOffset >= 0) {
if (barOffset < adjustedSliderWidth) {
ui.position.left += (ui.offset.left - ui.originalPosition.left - leftOffset)*SPEED;
} else {
if (!dragging) { return false; }
else { ui.position.left = adjustedSliderWidth; }
}
}
// fading while moving:
$('#image').fadeTo(fadeSpeed, (ui.position.left/adjustedSliderWidth));
// remove this if you don't want the information to show up:
$('#image').html(ui.position.left/adjustedSliderWidth
+"<br \><br \>"
+ui.position.left);
}
});
// the mouse listener
$("#bar").mousedown(function(){ dragging = true; });
$("#bar").mouseup(function(){ dragging = false; });
I've also implemented the revert option on draggable so the slider nicely returns to zero when the user releases #bar. Of course you can delete this if you want.
Now the variable that your whole question is about is the variable: SPEED.
You can specify the speed of dragging by specifying a number for this variable.
E.g.:
var SPEED = 0.0; // the normal dragging speed
var SPEED = 0.5; // the dragging speed is 1.5 times faster than normal
var SPEED = -0.5; // the dragging speed is 0.5 times faster than normal
So negative values give a slower dragging speed and positive values give a faster dragging speed.
Unfortunately (or actually: fortunately), it is not possible to change the speed of the mouse pointer. This because only the OS has control over the mouse coordinates and speed. Browsers cannot influence this. Personally I think it doesn't matter: moving the slider slower than normal is what you're trying to achieve, so you can ignore the mouse pointer.
To see all this in action, I've prepared a working jsFiddle for you:
DEMO
I hope this helps you out :)
I'm trying to write a menu that expands the subcategories on hover - so only one subcategory can be expanded at a time. It will looks something like this (completely expanded):
X
Y
Y.1
Y.2
Z
Z.1
Z.2
My issue is this:
The animation works correctly, except if I hover over Y and then try to hover over Z, all of X closes. I know why: there needs to be a delay because Z starts moving up, so you're no longer hovering on Z and it starts closing.
Below is the code:
$( document ).ready(function() {
$("#m2l2").hoverIntent(
function() {
clearTimeout(z_timer);
$("#m2l2").toggleClass("child childopen");
$("#u12").slideToggle("slow", "linear");
},
function() {
z_timer = setTimeout(function() {
$("#u12").slideToggle("slow", "linear", function () {
$("#m2l2").toggleClass("childopen child");
});
}, 10000);
});
});
Is there any way to avoid a delay or to make a delay that only activates in certain case?
Here's the link: http://jsfiddle.net/stamblerre/XYp48/12/
Thank you!!!
Here's how to add timeout for hoverIntent by using the object from hoverIntent jQuery Plugin
$('.selector').hoverIntent({
over: function(){},
out: function(){},
timeout: 1000 // in miliseconds
});
so here's what it will look like : JSFIDDLE, even though sometimes it takes to long before the out function called, so define it with whatever best usage for your case
It is not the js code issue but css issue, you have a vertical menu where 3rd level also opens vertically.
Its tricky but try to visualize
When your mouse enters option Y its 3rd level menu shows ,now when you take mouse on option Z the mouseout event for Y fires and it hides its 3rd level due to which position of option Z shifts and now your mouse pointer is outside the main menu #id="m2l0" and its mouseout event fires and hides both options Y and Z.
I am trying to create a very simple slideshow.
I would like the slideshow to pause on hover and resume when the user moves their mouse off the slideshow (#slide_container). While the slideshow works fine, and so does the hover (to an extent), if I flick my mouse on and off the slideshow repeatedly, it completely messes the slide and starts animating sporadically (check the fiddle below to see what I mean).
I tried adding promise, so that before animating it completes any queued animation, but despite this, the behaviour remains.
How should I go about fixing this?
Here is the fiddle: http://jsfiddle.net/hR6wZ/
my js code:
$(document).ready(function() {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var i = 0;
var hover_switch = 0;
$('.slider_container').hover(function() {
//Hover mode on
hover_switch = 1;
}, function() {
//Hover mode off
hover_switch = 0;
sliderLoop()
});
function animateSlider() {
$(":animated").promise().done(function() {
$('.slider').finish().animate({ marginLeft: -(slide_width * i) });
});
}
function sliderLoop() {
setTimeout(function(){
//Only runs if hover mode is off;
if(i < number_of_slides-1 && !hover_switch) {
i++;
animateSlider();
sliderLoop();
}
else if (!hover_switch)
{
i = 0;
animateSlider();
sliderLoop()
}
},4000);
}
sliderLoop();
});
EDIT: also I did try using stop instead of finish() but this didn't fix the issue..
Becuase your calling the slider loop each time you hover out everytime even if you hover back and forth like ten times it tells it and queus it up to animate the x amount of times you did that.
What you can try is Only have the slider loop check right then and their when it's about to animate if it is being hovered or not and don't call the slider loop from the every time that it hovers out.
Another way is right before it begins animating set a variable for the duration of the animation to tell it not to call the animateSlider function if Currently_animating
so add && !currently_animating to each if statement within the sliderloop function.
That method however will help but probably the first way would be better as then it will never animate more then every x miliseconds or however long you set it to be.
But in General you probably should not call the sliderloop function if hover_switch = 0 becuase then it will just queue up the slider loop each time you hover out.
I try to make a mousewheel event script, but getting some issues since I'm using an Apple Magic Mouse and its continue-on-scroll function.
I want to do this http://jsfiddle.net/Sg8JQ/ (from jQuery Tools Scrollable with Mousewheel - scroll ONE position and stop, using http://brandonaaron.net/code/mousewheel/demos), but I want a short animation (like 250ms) when scrolling to boxes, AND ability to go throught multiple boxes when scrolling multiple times during one animation. (If I scroll, animation start scrolling to second box, but if I scroll again, I want to go to the third one, and if I scroll two times, to the forth, etc.)
I first thought stopPropagation / preventDefault / return false; could "stop" the mousewheel velocity (and the var delta) – so I can count the number of new scroll events (maybe with a timer) –, but none of them does.
Ideas?
EDIT : If you try to scroll in Google Calendars with these mouses, several calendars are switched, not only one. It seems they can't fix that neither.
EDIT 2 : I thought unbind mousewheel and bind it again after could stop the mousewheel listener (and don't listen to the end of inertia). It did not.
EDIT 3 : tried to work out with Dates (thanks to this post), not optimal but better than nothing http://jsfiddle.net/eZ6KE/
Best way is to use a timeout and check inside the listener if the timeout is still active:
var timeout = null;
var speed = 100; //ms
var canScroll = true;
$(element).on('DOMMouseScroll mousewheel wheel', function(event) {
// Timeout active? do nothing
if (timeout !== null) {
event.preventDefault();
return false;
}
// Get scroll delta, check for the different kind of event indexes regarding delta/scrolls
var delta = event.originalEvent.detail ? event.originalEvent.detail * (-120) : (
event.originalEvent.wheelDelta ? event.originalEvent.wheelDelta : (
event.originalEvent.deltaY ? (event.originalEvent.deltaY * 1) * (-120) : 0
));
// Get direction
var scrollDown = delta < 0;
// This is where you do something with scrolling and reset the timeout
// If the container can be scrolling, be sure to prevent the default mouse action
// otherwise the parent container can scroll too
if (canScroll) {
timeout = setTimeout(function(){timeout = null;}, speed);
event.preventDefault();
return false;
}
// Container couldn't scroll, so let the parent scroll
return true;
});
You can apply this to any scrollable element and in my case, I used the jQuery tools scrollable library but ended up heavily customizing it to improve browser support as well as adding in custom functionality specific to my use case.
One thing you want to be careful of is ensuring that the timeout is sufficiently long enough to prevent multiple events from triggering seamlessly. My solution is effective only if you want to control the scrolling speed of elements and how many should be scrolled at once. If you add console.log(event) to the top of the listener function and scroll using a continuous scrolling peripheral, you will see many mousewheel events being triggered.
Annoyingly the Firefox scroll DOMMouseScroll does not trigger on magic mouse or continuous scroll devices, but for normal scroll devices that have a scroll and stop through the clicking cycle of the mouse wheel.
I had a similar problem on my website and after many failed attempts, I wrote a function, which calculated total offset of selected box and started the animation over. It looked like this:
function getOffset() {
var offset = 0;
$("#bio-content").children(".active").prevAll().each(function (i) {
offset += $(this)[0].scrollHeight;
});
offset += $("#bio-content").children(".active")[0].scrollHeight;
return offset;
}
var offset = getOffset();
$('#bio-content').stop().animate( {
scrollTop: offset
}, animationTime);
I hope it gives you an idea of how to achieve what you want.
you can try detecting when wheel stops moving, but it would add a delay to your response time
$(document).mousewheel(function() {
clearTimeout($.data(this, 'timer'));
$.data(this, 'timer', setTimeout(function() {
alert("Haven't scrolled in 250ms!");
//do something
}, 250));
});
source:
jquery mousewheel: detecting when the wheel stops?
or implement flags avoiding the start of a new animation
var isAnimating=false;
$(document).bind("mousewheel DOMMouseScroll MozMousePixelScroll", function(event, delta) {
event.preventDefault();
if (isAnimating) return;
navigateTo(destination);
});
function navigateTo(destination){
isAnimating = true;
$('html,body').stop().animate({scrollTop: destination},{complete:function(){isAnimating=false;}});
}