`queue` callback only executes once? - javascript

I have a jQuery function that loops. What I want to do is for the $bird_wing_left element to rotate 30 degrees and then rotate back to 0 degree (in an infinite loop).
$(document).ready(function() {
var rotate = 0;
setInterval(function(){
rotate = 30;
$bird_wing_left.css({ transform: "rotate(" + rotate + "deg)" }).delay(1000).queue(function(){
rotate = 0;
$(this).css({ transform: "rotate(" + rotate + "deg)" });
});
}, 3000);
});
The first time it did rotate 30 degrees, then to 0 degrees, then to 30 degrees. However, afterwards, it seems to ignore the callback (which resets the degree value to 0), hence, it just keeps on being at 30 degrees on and on.
What could be the issue?
This is the jsFiddle: https://jsfiddle.net/iamacatperson/86z26hdw/

When you queue a function, within the function you have to dequeue (or call "next", more below) to allow the queue to continue processing (as shown in the examples). Just add $(this).dequeue() within your queue callback:
var $bird_wing_left = $("#wing");
$(document).ready(function() {
var rotate = 0;
setInterval(function() {
rotate = rotate + 30;
$bird_wing_left.css({
transform: "rotate(" + rotate + "deg)"
}).delay(1000).queue(function() {
rotate = rotate - 30;
$(this).css({
transform: "rotate(" + rotate + "deg)"
}).dequeue(); // <====================
});
}, 3000);
});
body {
padding-top: 2em;
}
<div id="wing" style="width: 10em">Bird wing</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Alternately, since jQuery 1.4 the queue callback has been given an argument (traditionally called next) it can call to keep the queue going:
var $bird_wing_left = $("#wing");
$(document).ready(function() {
var rotate = 0;
setInterval(function() {
rotate = rotate + 30;
$bird_wing_left.css({
transform: "rotate(" + rotate + "deg)"
}).delay(1000).queue(function(next) { // <=====
rotate = rotate - 30;
$(this).css({
transform: "rotate(" + rotate + "deg)"
});
next(); // <=====
});
}, 3000);
});
body {
padding-top: 2em;
}
<div id="wing" style="width: 10em">Bird wing</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Side note: You can use += and -= if you like, e.g. rotate += 30; and rotate -= 30;

Quick fix could be to check rotate variable value before setting it.
if(rotate == 0)
rotate = rotate + 30;
else
rotate = 0;

Related

Simulate an object falling over with jQuery

I'm simulating a bowling game in jQuery. So, I throw the ball (through animate function) and when it hits a pin I simulate it falling over (also through animate function). But I can only make it rotate. I want it to fall over in place, to the left or to the right. Like this. This is the jQuery code for the pin animation:
this.animation = function (pinID) {
var rdm = ((Math.random()*10)+1);
var degree;
if (rdm <= 5)
degree = -90;
else
degree = 90;
$(pinID).animate({ deg: degree },
{
duration: 1000,
step: function (now) {
// In the step-callback (that is fired each step of the animation),
// the pin will rotate to the current degree of the animation
$(pinID).css({
transform: 'rotate(' + now + 'deg)'
});
},
complete: function () {
// When the animation is complete, removes the pin from play
$(pinID).css({
"left": -200, "top": -200
});
}
});
}
I tried to have a left and top in the beginning of the animate function the it just simulated a weird movement.
I'd appreciate it if anyone could help me. Thanks.
EDIT Here's the result (thanks to Zs V):
this.animation = function (pinID) {
if (knockedPins.indexOf(pinID) == -1) {
var rdm = ((Math.random() * 10) + 1);
var degree;
var transFormOrigin;
if (rdm <= 5) {
degree = -90;
transFormOrigin = '0% 100%';
}
else {
degree = 90;
transFormOrigin = '100% 100%';
}
$(pinID).css({ "transform-origin": transFormOrigin });
knockedPins.push(pinID);
$(pinID).animate({ deg: degree },
{
duration: 1000,
step: function (now) {
// In the step-callback (that is fired each step of the animation),
// the pin will rotate to the current degree of the animation
$(pinID).css({
transform: 'rotate(' + now + 'deg)'
});
},
complete: function () {
// When the animation is complete, removes the pin from play
$(pinID).css({
"left": -200, "top": -200
});
}
});
}
}
I added the transform-origin property and had to make use of an array to store the ids of the pins that were already knocked, otherwise it would shake until it was put to rest. hehe
You have to rotate the object (the picture) around its corner instead of the center. Here it is a discussion how to do that: https://stackoverflow.com/a/6633676/6624619

Rotating an image with jQuery with 2 buttons

I have been trying to rotate an image by 90 degrees when clicked on the right button and rotate it by -90 when click on the left button. My code is here.
I'm trying to create some sort of a loop with a counter set at 0 and looping through the if and else statements. but I didn't get it to work:
HTML:
<button id="left" class="button">left</button>
<img src="images/cartoon.jpg" alt="Cartoon" style="width:304px;height:228px;" id="rotate">
<button id="right" class="button">right</button>
CSS:
#draaien {
}
jQuery:
$(document).ready(function(){
var counter = 0;
$("#left").click(function(){
if (counter == 0){
$("#rotate").css({
"-webkit-transform": "rotate(-90deg)",
"-moz-transform": "rotate(-90deg)",
"transform": "rotate(-90deg)"
teller +=1;
});
counter=0;
$("#rotate").css({
}
}else if($("#right").click()){
$("#rotate").css({
"-webkit-transform": "rotate(90deg)",
"-moz-transform": "rotate(90deg)",
"transform": "rotate(90deg)"
}
});
});
});
Basically I was trying to create some kind of counter that upon clicking "left", it increments by 1 and adds the various CSS elements so it can rotate to the left, and decrementing by -1 so it can rotate to the right (+90), it doesnt seem to have any effect. Thanks!
If I understand, you want to set a variable to track the degree turn and add 90 if right, and subtract 90 if left.
$(document).ready(function() {
var deg = 0;
$(".button").on("click", function() {
if ($(this).is("#left")) {
deg = deg - 90;
} else {
deg = deg + 90;
}
$("#rotate").css({
"-webkit-transform": "rotate(" + deg + "deg)",
"-moz-transform": "rotate(" + deg + "deg)",
transform: "rotate(" + deg + "deg)"
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="left" class="button">left</button>
<img src="https://futurism.com/wp-content/uploads/2015/11/neildegrassetyson.jpg" alt="Cartoon" style="width:304px;height:228px;" id="rotate">
<button id="right" class="button">right</button>
Try this, the point is its a 360 degree rotation, so you need to know how much is currently rotated and how far it should go,
$(document).ready(function(){
$("#left").click(function(){
rotate("#rotate",-90)
});
$("#right").click(function(){
rotate("#rotate",90);
});
});
function rotate(whom,angle)
{
var rv=$(whom).prop("data-rot")?$(whom).prop("data-rot"):0;
rv=rv+1;
n=rv*angle;
if(Math.abs(n)>=360){n=0;rv=0;}
$(whom).css({
"-webkit-transform": "rotate(" + n + "deg)",
"-moz-transform": "rotate(" + n + "deg)",
"transform": "rotate(" + n + "deg)"
});
$(whom).prop("data-rot",rv);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="left" class="button">left</button>
<img src="https://cdn.livechatinc.com/s3/default/eyeCatchers/049.png" alt="Cartoon" style="width:304px;height:228px;" id="rotate">
<button id="right" class="button">right</button>
Your thought was right, setting a counter decrease when rotate left and vice versa, but there is some syntax error in the example given by you.
$("#rotate").css({
"-webkit-transform": "rotate(-90deg)",
"-moz-transform": "rotate(-90deg)",
"transform": "rotate(-90deg)"
teller +=1;
});
taller += 1; was an statement, it should't appear inside of a object. Objects are key,value pairs, seperated by colon, and conjoin by comma.
}else if($("#right").click()){
$("#right").click() is a method accepted a event handler function parameter to bind click event handlers on the element, it returns the jQuery Object.
$("#rotate").css({
}
and this wouldn't clear css on the element.
I wrote a simple example here: https://jsfiddle.net/yzjk4v37/
there is 2 buttons controls the block make rotate left or right

Rotating an object 45 degrees on specified onkeydown

I have been working on a game project for a while and have hit a snag with a particular control. I have decided to change some of the mechanics a bit to deal with this. I had written a chunk of code to make an object rotate with my mouse movement but now I need to make my object rotate on keypress.
I want to make it rotate 45 degrees clockwise when I press the right arrow key, and 45 degrees counter clockwise on left arrow key press. I have the input key call all written up I just need to translate my old code to the new code.
This is my existing code
window.onmouseclick = function(event) {
var box = hypeDocument.getElementById('bolt')
cx = event.pageX; // Mouse X
cy = event.pageY; // Mouse Y
bx = parseInt(hypeDocument.getElementById('group').style.left);
by = parseInt(hypeDocument.getElementById('group').style.top);
tx = hypeDocument.getElementProperty(box, 'left') +
(hypeDocument.getElementProperty(box, 'width')/2) + bx;
ty = hypeDocument.getElementProperty(box, 'top') +
(hypeDocument.getElementProperty(box, 'height')/2) + by;
angle = Math.atan2((cy-ty),(cx-tx)) * (180/Math.PI) ; // AHHHH MATH!
hypeDocument.setElementProperty(box, 'rotateZ', angle)
}
hypeDocument.setElementProperty(box, 'rotateZ', angle) // hype api code for
box.style.webkitTransform = "rotate(" + angle + "deg)";
box.style.mozTransform = "rotate(" + angle + "deg)";
box.style.transform = "rotate(" + angle + "deg)";
This is the code I want to change, as I state in the comment the last line is hype api for the 3 box styles below it to help anybody who reads this understand what that line is.
I'm not sure about the hypedocument markup, but I put this together for you. Can you extract the meaningful parts re: the keycodes to make it work with your project?
window.addEventListener('keyup',function(e) {
var keyCode = e.keyCode,
dir = '',
box = document.getElementById('box');
if (keyCode == 39) {
dir = 'left';
} else if (keyCode == 37) {
dir = 'right';
}
box.setAttribute('data-dir','');
setTimeout(function() {
box.setAttribute('data-dir',dir);
})
})
#box {
width: 100px;
height: 100px;
background: black;
transform: rotate(0);
}
[data-dir="left"] {
animation: left .5s forwards;
}
[data-dir="right"] {
animation: right .5s forwards;
}
#keyframes left {
from {
transform: rotate(0);
}
to {
transform: rotate(90deg);
}
}
#keyframes right {
to {
transform: rotate(-90deg);
}
}
<div id="box"></div>

Javascript - Click to rotate image infinitely and click again to stop

I've been trying to figure out how to get this script to rotate an image infinitely onclick and then stop it when you click it again. Can anyone modify it to get it to do that?
$(function() {
var $rota = $('.spin'),
degree = 0,
timer;
function rotate() {
$rota.css({ transform: 'rotate(' + degree + 'deg)'});
// timeout increase degrees:
timer = setTimeout(function() {
++degree;
rotate(); // loop it
},5);
}
rotate(); // run it!
});
you could create a bool to determine if the element has been clicked, change it on click and stop the process if the click has happened.
$(function() {
var $rota = $('.spin'),
degree = 0,
clicked = false,
timer;
$rota.on('click', function() { clicked = true; return false; } );
function rotate() {
if ( clicked )
$rota.css({ transform: 'rotate(' + degree + 'deg)'});
// timeout increase degrees:
timer = setTimeout(function() {
++degree;
rotate(); // loop it
},5);
}
rotate(); // run it!
});
Try using setInterval and clearInterval instead of setTimeout:
function rotate() {
$rota.css({ transform: 'rotate(' + degree + 'deg)'});
++degree;
}
var loop;
$rota.click(function() {
if(loop) {
clearInterval(loop);
loop = false;
}
else {
loop = setInterval(rotate, 5);
}
});
You can read up on setInterval here
Try
$(function() {
var $rota = $('.spin')
$rota.click(function(){
var $this = $(this);
if($this.data('rotating')){
clearInterval($this.data('rotating'));
$this.data('rotating', false)
} else {
$this.data('rotating', setInterval(function(){
var degree = $this.data('degree') || 0;
$this.css({ transform: 'rotate(' + degree + 'deg)'});
$this.data('degree', ++degree)
}, 5));
}
});
});
Demo: Fiddle
$(function() {
var $rota = $('img'), degree = 0, timer, enabled;
var rotate = function() {
timer = setInterval(function() {
++degree;
$rota.css({
transform: 'rotate(' + degree + 'deg)'
});
},5);
};
$rota.on('click', function(){
enabled = !enabled;
enabled ? rotate() : clearInterval(timer);
});
});

jQuery .position() strangeness while using CSS3 rotate attribute

I'm getting absolutely positioned rotated elements position with jQuery .position() method, then setting position-related attributes (top, left) with jQuery .css(pos), where pos is the data returned by .position(). I think it'll leave the element in it's place, but elements position is changing.
How can I use set rotated elements position, so that it'll be placed as expected? Maybe there is a coefficient depended on angle that changes position?
I'm testing in Google Chrome v.9, Windows XP.
HTML
<div id="container">
<div id="element">
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcS0Fawya9MVMez80ZusMVtk_4-ScKCIy6J_fg84oZ37GzKaJXU74Ma0vENc"/>
</div>
</div>
CSS
#container {
position: relative;
border: 1px solid #999;
padding: 5px;
height: 300px;
width:300px;
}
#element {
position: absolute;
top:50px;
left: 60px;
width: auto;
border: 1px solid #999;
padding: 5px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
}
JS
$(document).ready(function(){
var $el = $('#element'),
// getting position
pos = $el.position();
alert(pos.left + '/' + pos.top);
// alerts 37/11
// setting css position attributes equal to pos
$el.css(pos);
// re-getting position
pos = $el.position();
alert(pos.left + '/' + pos.top);
// alerts 14/-28
});
View it http://jsfiddle.net/Antaranian/2gVL4/
// Needed to read the "real" position
$.fn.adjustedPosition = function() {
var p = $(this).position();
return {
left: p.left - this.data('dx'),
top: p.top - this.data('dy')
}
};
$(function() {
var img = $('img'),
pos;
// Calculate the delta
img.each(function() {
var po = $(this).position(), // original position
pr = $(this).addClass('rot').position(); // rotated position
$(this).data({
dx: pr.left - po.left, // delta X
dy: pr.top - po.top // delta Y
});
});
// Read the position
pos = img.adjustedPosition();
alert(pos.left + '/' + pos.top);
// Write the position
img.css(pos);
// Read the position again
pos = img.adjustedPosition();
alert(pos.left + '/' + pos.top);
});
Live demo: http://jsfiddle.net/2gVL4/4/
So what is going on here:
The CSS code that rotates the image is stored inside a special CSS class. I do this because I want to read the original position of the image (before rotating). Once I read that original position, I apply the .rot class, and then read the position again to calculate the difference (delta), which is stored inside the element's data().
Now, I can read the position via the custom method adjustedPosition (which is defined above). This method will read the position of the element and then subtract the delta values stored inside the data() of the element.
To write the position, just use the css(pos) method like normally.
Had similar problem. There is simple solution (not elegant, but working):
set current angle to 0
read X/Y position
revert angle back to its value
var temp = $(this).position();
temp.angle = getRotationDegrees( $(this) ); // remember current angle
rotateObject($(this), 0); // set angle to 0
temp.left = Math.round($(this).position().left); // proper value
temp.top = Math.round($(this).position().top); // proper value
// revert back the angle
rotateObject($(this), temp.angle);
Used functions:
function rotateObject(obj, angle) {
obj.css({ '-webkit-transform': 'rotate(' + angle + 'deg)'});
obj.css({ '-moz-transform': 'rotate(' + angle + 'deg)'});
obj.css({ '-ms-transform': 'rotate(' + angle + 'deg)'});
obj.css({ 'msTransform': 'rotate(' + angle + 'deg)'});
obj.css({ '-o-transform': 'rotate(' + angle + 'deg)'});
obj.css({ '-sand-transform': 'rotate(' + angle + 'deg)'});
obj.css({ 'transform': 'rotate(' + angle + 'deg)'});
}
function getRotationDegrees(obj) {
var matrix = obj.css("-webkit-transform") ||
obj.css("-moz-transform") ||
obj.css("-ms-transform") ||
obj.css("-o-transform") ||
obj.css("transform");
if(matrix !== 'none') {
var tr;
if (tr = matrix.match('matrix\\((.*)\\)')) {
tr = tr[1].split(',');
if(typeof tr[0] != 'undefined' && typeof tr[1] != 'undefined') {
var angle = Math.round(Math.atan2(tr[1], tr[0]) * (180/Math.PI));
}else{
var angle = 0;
}
}else if(tr = matrix.match('rotate\\((.*)deg\\)')){
var angle = parseInt(tr[1]);
}
} else { var angle = 0; }
return (angle < 0) ? angle + 360 : angle;
}

Categories

Resources