jquery rotate callback not called if image not rotated - javascript

I have this piece of code rotating an image and then moving it - which works fine unless the image does not rotate - meaning the current angle of the image is equal to the angle it should rotate to - in this case the callback function is not called, so there is no animation. The rotate function comes from a plugin.
$("#Ship" + shipID).rotate({
duration: 500,
angle: $(this).getRotateAngle(),
animateTo: parseInt(rotate),
callback: function () {
$("#" + shipID).animate({
left: parseInt(moveX),
top: parseInt(moveY)
}, 500, function () {
});
}
})
If the animate function is written after the rotate - then the rotate and animation happen at the same time.
I don't think I can force the callback as I would have to edit the plugin (but im not sure about that). Is there a way to write the animate after the rotate, but wait for rotate to finish? I guess one way would be is to use delay, but is there a more proper way?

You have to check the rotation before you try to execute anything with the plugin. I'm not exactly sure how you'll check the current rotation, but:
var currentRotation = $("#Ship" + shipID).getRotateAngle();
if(currentRotation != rotate) {
$("#Ship" + shipID).rotate({
duration: 500,
angle: $(this).getRotateAngle(),
animateTo: parseInt(rotate),
callback: function () {
$(this).rotate({
animateTo: rotate
});
$("#" + shipID).animate({
left: parseInt(moveX),
top: parseInt(moveY)
}, 500);
}
});
}
Depending on your exact setup and how the plugin works, you may need to check your currentRotation inside of the plugin method. Or, you may need to set up some events to execute the if statement. Again, this would depend on how you're brinding this all together (how do you know when you want something to rotate?)

Related

How to make JQuery wait inside a loop in rotation animation

I have a circle and in it a percentage text, starts with 0%. Once I hover the circle it goes from 0 to 100% (with another effect around the circle). As for now, the percentage goes from 0 to 100 directly and I want it to show the progress (0,1,2...,99,100) but I can't manage to make JQuery wait between each for iteration.
This is what I've tried: JSFiddle demo.
Note: My code works with chrome for now.
That's one iteration:
function actions(i){
var box = $('#box');
box.css('transform','rotate(' + i + ' deg)');
box.css('-ms-transform','rotate(' + i + 'deg)');
box.css('-webkit-transform','rotate(' + i + 'deg)');
prec = (100*(i + 135))/360;
$("div.prec").delay(100).html(Math.round(prec)+"%");
}
I understand that delay() needs to be queued and html() is not queued so I already tried setTimeout, but that it didn't work either. I also tried setInterval - see the next code snippet:
setInterval(function () {
$("div.prec").html(Math.round(prec)+"%");
},100);
To be more clear, I want the percentage to fit the effect progress - if the triangle that goes around travels half of the way, the percentage should be 50, and so, when I'm not hovering the circle anymore it should gradually go back to 0.
First, remove the surplus transition: all 1s css rule! This is making trouble in all the solutions.
1. Educational - using setTimeout
The for loop will not work as you expect, javascript is not build for active-wait loop like this:
for (var i = -135; i < 225; i++){
actions(i);
sleep(some time);
}
You have to use timeout and callbacks. Disable the .delay function call and rewrite your for loop to iterative setTimeout callback as shown here:
function loopit(dir, i){
if (typeof i == "undefined")
i = -135;
if (i >= 225)
return;
actions(i);
setTimeout(function () {
loopit(dir, i + 1);
}, 1);
}
The back-rotation would be written analogically - you can write it yourself as a homework :-)
http://jsfiddle.net/NNq3z/10/
2. Easy - using jQuery .animate()
The easiest way is to use jQuery .animate() function, that will do the animation "loop" with timing for you. To animate the percent text, use progress callback. Animating rotation is tricky though, you need to use special trick:
$({ deg: deg_from } ).animate({
deg: deg_to
}, {
duration: 1000,
progress: function (animation, progress) {
$("div.prec").html(Math.round(progress*100)+"%");
},
step: function(now) {
$('#box').css({
transform: 'rotate(' + now + 'deg)'
});
}
});
http://jsfiddle.net/q9VXC/1/
http://jsfiddle.net/NNq3z/13/
var i = -135,box = $("#box"),prec;
setTimeout(function(){
if($("#circle").is(":hover"))
loopit("c");
else
loopit("nc");
},1);
function loopit(dir){
if (dir=="c")
i++;
else
i--;
if(i<-135)
i=-135;
if(i>225)
i=225;
prec = (100*(i + 135))/360;
$(".prec").html(Math.round(prec)+"%");
box.css("transform","rotate("+i+"deg)")
.css("-ms-transform","rotate("+i+"deg)")
.css("-moz-transform","rotate("+i+"deg)")
.css("-webkit-transform","rotate("+i+"deg)");
setTimeout(function(){
if($("#circle").is(":hover"))
loopit("c");
else
loopit("nc");
},1);
}
Removed transition:all 1s.
In your code, the percentage of the box immediately change to 100% because you use for loop. For loop will be executed very fast as if it immediately change to 100% so it is not recommended.
You should use setInterval, and you have to increment percentage each time:
var percentage = 0;
var timer = setInterval(function() {
percentage++;
if (percentage > 100) {
clearInterval(timer);
} else {
$("div.prec").html(percentage + "%");
}
}
You could also call actions() inside there.

how to stop animation once max width is reached

I am working to make a slider that moves continuously while the users mouse is positioned over the arrow. It works but it keeps moving even when the content has ended.
How can I make it stop so that the forward/back motion is disabled once all the slides have been viewed, or so that they can't go backwards when they are viewing the first slide?
My code is below - open to other methods to achieve this type of slider if what I have is bad.
$(document).ready(function() {
var timer;
$("#leftarrow").hover(function() {
timer = setInterval(function() {slideLeft();}, 50);
}, function() {
clearInterval(timer);
});
$("#rightarrow").hover(function() {
timer = setInterval(function() {slideRight();}, 50);
}, function() {
clearInterval(timer);
});
function slideLeft() {
$("img#background").stop().animate({
'left': '-=200px'
}, 50);
$(".mid").stop().animate({
'left': '-=20px'
}, 50);
console.log('alert');
}
function slideRight() {
$("img#background").stop().animate({
'left': '-=200px'
}, 50);
$(".mid").stop().animate({
'left': '+=20px'
}, 50);
}
});
Here is a fiddle with my slider: http://jsfiddle.net/rYYDv/
You can use an additional if:
For slide left:
if(($(".mid").position().left) >= -500){ .. }
For slide right:
if(($(".mid").position().left) <= -10){ .. }
Disadvantage: You have to take care of the correct values manually. Which is not a problem, if the pictures don't change very often.
You should probably also add an additional else to ensure a correct final position (for the animate left property). But i think you get the idea.
http://jsfiddle.net/rYYDv/2/
I do not have enough points to comment on this post; hence, I'm writing it down here -
Similar post: How to make the Animate jQuery method stop at end of div?

Animate tooltip on user hover with jQuery

Im trying to make my tooltip bounce onmouse hover,
I have the following that works with sporadic results, as in the the tooltip bounces fast for 3 seconrds ro so, then slow for 3 seconds etc... I also need to stop this function on mouseout, Can somebody see where im going wrong to get the variation in bounce speed?
// Tooltip title
$('.male').mouseover(function(e) {
var tiptitle = $(this).find('.highlight');
setInterval(function(){
tiptitle.animate({top:'-85px'}, 100, function() {
tiptitle.animate({top:'-75px'}, 100);
});
},200);
}).mouseout(function() {
});
if you choose to go the route of the effects plugin bounce effect use this code , then use stop() on mouseout
$('.male').mouseover(function(e) {
var tiptitle = $(this).find('.highlight');
tiptitle.effect("bounce", { times:3 }, 300);
}).mouseout(function() {
$(this).find('.highlight').stop();
});
otherwise , I believe you are getting sporadic speeds of bounce because of -85px and -75px both at 100

How to track element movement and trigger function at specific spot?

I have a #ball that when clicked uses jquery animate to move down 210px using this code:
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, 500);
setTimeout(crack, 400);
});​
currently Im using Timeout to trigger the next function which is "crack".
Instead I want to track the movement of #ball and when its css top = 210px I want to trigger the function crack(), how can I do this?
I saw in a somewhat similar post that the Step function might be what I'm looking for, but I am not sure how to approach that solution based on the info provided at http://api.jquery.com/animate/
Look at Demo: http://jsfiddle.net/EnigmaMaster/hbvev/4/
I am not sure why you want to use a tracker if you know that the ball will reach the box in 210px.
If you want to get rid of setTimeout, then use the .animate callback function which will be called when the ball reaches the box.
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, 500, crack); //<== crack will be called after ball animation
});​
DEMO
Incase if you want to call crack when the ball touches the box and still continue the movement of box then you can execute it 2 steps like below,
$('#ball').click(function() {
$(this).animate({
top: '+=180px'
}, 400, function() {
crack();
$(this).animate({
top: '+=30px'
}, 100);
});
});
Also check this version for fun in slow motion http://jsfiddle.net/skram/hbvev/8/
If you truly want to do something based on the position of the ball, then yes, step is probably the best way to go:
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function() {
if($(this).offset().top > 208) {
crack();
}
}
});
});
Demo: http://jsfiddle.net/qJjnN/1/
Now, there are a couple of caveats:
There will be a possible performance hit.
The position at each step will not necessarily be a whole number, and the object will not exist at every pixel between the start and stop location.
step is not called on the final position, so you cannot actually check for 210 if it is the final location.
Taking those into mind, you will not be able to check for the exact position of 210px. Instead, you will want to watch when it passes a certain position and only trigger crack at that point and not every point after:
$('#ball').click(function() {
var cracked = false;
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function() {
if($(this).offset().top > 208 && !cracked) {
cracked = true;
crack();
}
}
});
});
Demo: http://jsfiddle.net/qJjnN/2/
The step function also has parameters now and fx that can be used to see the current value of the css being animated. step is called for each step of each css attribute being animated. So, you have to be careful using those, because you need to look at fx to see what attribute value you are looking at (if you are animating more than one, i.e. top and left).
$('#ball').click(function() {
var cracked = false;
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function(now, fx) {
if(fx.prop != 'top') {
return;
}
if(now > 208 && !cracked) {
cracked = true;
crack();
}
}
});
});

how to remove a method with a callback or otherwise

I have the following code that animates an object with a delay of 800 ms:
$('#navMenu').mousemove(function (e) {
thisX = e.pageX
if (thisX >= 1625) {
$('#prbBtnHolder').animate({ left: '-=150' }, 300).delay(800);
}
});
If the #prbBtnHolder has a certain css left property i want to be able to remove the delay()method and stop the animation. How do i do this? This is what I've tried so far:
//...
$('#prbBtnHolder').animate({ left: '-=150' }, 300).delay(800);
if ($('#prbBtnHolder').css('left') < -100) {
$(this).animate({left: '-=0px'});
}
But this does not remove the delay method nor does it achieve the desired effect. Any other ideas?
In order to clear the effects queue, you'll need to use the step callback to see if your condition is met.
http://api.jquery.com/animate/
$('#prbBtnHolder').animate({
left: '-=150'
},
{
duration: 300,
step: function(now, fx) {
if (now < -100) {
// uncomment and you'll see the next animation
$(fx.elem).clearQueue().stop();
}
}
}).delay(800).animate({ width: '200px', height: '200px' }, 300);
Here is a jsbin example:
http://jsbin.com/utejew/3
$(this).clearQueue();
jQuery Docs for clearQueue
Removes all elements in the effect Queue for the given Element. Otherwise you could use js native setTimeoutfunction to animate which can easily be cleared with clearTimeout.
Before you Animate $('#prbBtnHolder') you can calculate how far the Button is away from -100 and animate it only that far.

Categories